首页 > 解决方案 > MariaDB 查询使用 IN 和 LIMIT by row

问题描述

我在尝试在我的一个子查询中使用 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 - 此版本的 MySQL 尚不支持 'LIMIT & IN/ALL/ANY/SOME 子查询

这个问题有一个答案,但我无法让它满足我的需求,主要是因为我需要通过连接逐行完成,我尝试将相同的东西应用于我的查询,但我不确定如何保持连接在职的

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 个子记录

标签: mysqlsubquerymariadblimitgreatest-n-per-group

解决方案


原始查询的解决方法:

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;

保留原始子查询操作以ch_id从子表中提取,LIMIT 3但是通过在联接中添加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;

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

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

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


推荐阅读