MariaDB 查询使用 IN 和 LIMIT by row

Posted

技术标签:

【中文标题】MariaDB 查询使用 IN 和 LIMIT by row【英文标题】:MariaDB Query using IN with LIMIT by row 【发布时间】:2019-09-15 23:30:18 【问题描述】:

我在尝试在我的一个子查询中使用 LIMIT 时遇到了一些困难,我遇到了错误

MariaDB doesn't yet support 'LIMIT in subquery'

关于一个类似于我在 PostgreSQL 中所做的查询,以便为每个有孩子的父母获得 3 个孩子结果

select * from parent
join child on child.ch_pa_id = parent.pa_id
and child.ch_id in (
  select child.ch_id from child
  where child.ch_id = parent.pa_id
  limit 3
)
order by parent.pa_id;

我看到这里有一个关于同一件事的问题

mysql - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery

这个问题有答案,但我无法让它满足我的需要,主要是因为我需要通过连接逐行完成,我尝试将同样的事情应用于我的查询,但我不确定如何保持连接工作

select * from parent as p
join (
  select * from child
  where child.ch_pa_idno = p.pa_idno # this line breaks it
  limit 3
) as c on c.ch_pa_id = p.pa_id
order by p.pa_id;

p.pa_idno 是一个未知列会给出错误,我确定我是个白痴,这里有明显的问题

示例

这是一个使用 PostgreSQL http://sqlfiddle.com/#!17/4ed4d/2 完成的工作示例。它只返回两个父记录,对于每个父记录,它只返回 2 个子记录

【问题讨论】:

没有ORDER BYLIMIT 可能会导致随机结果。 true 但在这种情况下顺序并不重要,因为它只是一个示例 【参考方案1】:

原始查询的解决方法:

SELECT * FROM parent
JOIN child ON child.ch_pa_id = parent.pa_id
AND child.ch_id IN 
  (SELECT ch_id FROM (
  SELECT child.ch_id FROM child JOIN parent
  WHERE child.ch_id = parent.pa_id
  LIMIT 3) a
)
ORDER BY parent.pa_id;

保留原始子查询操作以从具有LIMIT 3 的子表中提取ch_id,但是通过在联接中添加parent 表。然后执行另一个操作以获取子查询结果,然后将其用于您的IN

编辑: 我有一个有效的查询,但我对它的感觉很复杂:

SELECT * FROM parent 
JOIN child ON parent.pa_id=child.ch_pa_id
LEFT JOIN (
 SELECT ch_pa_id,SUBSTRING_INDEX(chid,' ',1) f,SUBSTRING_INDEX(chid,' ',-1) e 
 FROM (
  SELECT ch_pa_id,
         SUBSTRING_INDEX(GROUP_CONCAT(ch_id ORDER BY ch_id ASC SEPARATOR ' '),' ',3) chid 
         FROM child 
         GROUP BY ch_pa_id) a) b 
 ON child.ch_pa_id=b.ch_pa_id
WHERE child.ch_id 
BETWEEN f AND e;

老实说,我担心这在大数据中表现不佳,但我一直在学习新东西,其中一些功能是我最近才发现的。

根据您的小提琴,我注意到您只为每个父母选择前 3 个ch_id。因此,这个SUBSTRING_INDEX(GROUP_CONCAT(ch_id ORDER BY ch_id ASC SEPARATOR ' '),' ',3) chidGROUP_CONCAT 水平显示数据,SUBSTRING_INDEX 获取程序集中的前 3 个 ch_id。通常 group_concat 会这样返回值; 1,2,3 和 substring_index 只能识别第一个、第二个等值,以[空格]('')分隔。这就是我添加SEPARATOR ' '的原因。

然后我在外部查询中使用SUBSTRING_INDEX 两次来定义fe,其中SUBSTRING_INDEX(chid,' ',1) 获取第一个值,SUBSTRING_INDEX(chid,' ',-1) 从列中获取最后一个值。然后我将它与原始查询一起加入并添加BETWEEN f and e

【讨论】:

这很接近,但它只获取链接到限制 3 返回的子行的父行,而不是像我的 PostgreSQL 那样为每个父行返回 3 个子行 哇,这似乎确实有效,但是 phewww... 看起来很复杂 XD 确实如此!我仍在尝试找到一种更简单的方法,而且我是 MariaDB 的新手:D 我也是!不过,PostgreSQL 永远是我的宝贝【参考方案2】:

请用文字解释想要的结果。

同时,看看这是否能满足您的需求:

SELECT p.*
    FROM parent AS p
    JOIN child AS c ON c.ch_pa_idno = p.pa_idno
    ORDER BY p.pa_id
    LIMIT 3

我被pa_弄糊涂了;这听起来很像“父母”,但显然ch_ 表示“父母”。

_id_idno有什么区别?

在父子(分层)关系的许多实现中,两者都在同一个表中。该表有PRIMARY KEY(id) 和一个名为parent_id 的列,然后使用“selfjoin”连接父子节点。

如果您同时为parentchild 提供SHOW CREATE TABLE 也可能会有所帮助。

【讨论】:

这是一个使用 PostgreSQL sqlfiddle.com/#!17/4ed4d/2 完成的工作示例,我也会将其包含在我的问题中

以上是关于MariaDB 查询使用 IN 和 LIMIT by row的主要内容,如果未能解决你的问题,请参考以下文章

选择 Mariadb 中除顶行以外的所有行

mysql/mariadb学习记录——limit

子查询中不能使用limit或者in

MariaDB 在使用大型 WHERE IN 时崩溃

MySQL 按行数选择 WHERE IN 和 LIMIT

MySQL - 此版本的 MySQL 尚不支持 'LIMIT & IN/ALL/ANY/SOME 子查询