如何为每个父记录选择1个子表项?

时间:2013-07-15 03:41:24

标签: mysql sql

我有一个列表和一个列表项表。我想制定一个查询,为列表中的每个项目只选择一个列表项。这里有一些简单的数据来说明我的问题:

 'lists' table
id   updated   share
--- ---------- -----
1   2013-07-11   1
2   2013-07-13   0
3   2013-07-15   1
4   2013-07-14   0
5   2013-07-14   1

'list_items' table
id l_id description sort likes
-- ---- ----------- ---- -----
1   1    hello       0     3
2   1    goodbye     0     0
3   1    thanks      0     4
4   2    ok          0     0
5   3    love        0     2
6   3    hate        1     1
7   4    celebrate   0     0
8   5    party       0     1
9   5    summer      1     5
10  5    winter      2     2

现在说我想从每个共享列表中获取第一个项目(share = 1)。首先,我的意思是列表项是否按“排序”排序。

基于上述数据的预期结果将是:

lists.id id l_id description sort likes
-------- -- ---- ----------- ---- -----
   1     1   1    hello       0     3
   3     5   3    love        0     2
   5     8   5    party       0     1

更新 我很难理解peterm和hims056提供的解决方案,而kayla的解决方案看起来更像是我可以遵循的东西并没有返回正确的结果。从这些解决方案中汲取灵感,我自己也有了解决方法并提出了

  SELECT * FROM (
    SELECT lists.id AS listid, lists.share, list_items.* 
    FROM list_items, lists
    WHERE lists.id = l_id
    AND lists.share = 1 
    ORDER BY sort) q
  GROUP BY q.listid

这似乎有效,但正如peterm所指出的那样,select子句中不属于group by子句的列的值可能不明确。

我虽然有人会想出一个使用LIMIT的解决方案,因为这是我第一次考虑这样做的方式。您可以返回仅允许共享的列表ID:

SELECT lists.id FROM lists WHERE share = 1

并且对于给定的列表ID,您可以通过以下方式返回顶部列表项:

SELECT lists.id AS listid, lists.share, list_items.* 
FROM list_items, lists
WHERE lists.id = l_id 
AND lists.id = 1
ORDER BY sort
LIMIT 1

但有没有办法将这两个语句组合在一起,为每个允许共享的列表返回顶部列表项?

3 个答案:

答案 0 :(得分:1)

更新要确保按sort的顺序获得每个小组的第一个,请尝试

SELECT q.l_id list_id, q.id, i.description, i.sort, i.likes 
  FROM 
(
  SELECT l_id, id, @n := IF(@g = l_id, @n + 1, 1) n, @g := l_id g
    FROM 
  (
    SELECT i.l_id, i.id
      FROM list_items i JOIN lists l
        ON i.l_id = l.id 
     WHERE l.share = 1
     ORDER BY l_id, sort, id
  ) b CROSS JOIN (SELECT @n := 0, @g := 0) a
  HAVING n = 1
) q JOIN list_items i 
   ON q.id = i.id

示例输出:

| LIST_ID | ID | DESCRIPTION | SORT | LIKES |
---------------------------------------------
|       1 |  1 |       hello |    0 |     3 |
|       3 |  5 |        love |    0 |     2 |
|       5 |  8 |       party |    0 |     1 |

这是 SQLFiddle 演示

答案 1 :(得分:1)

SELECT lists.id, list_items.id, l_id, description, sort, likes 
  FROM (SELECT * FROM lists WHERE share = 1) lists 
  LEFT JOIN (SELECT * FROM list_items GROUP BY l_id) list_items 
  ON  lists.id = l_id

答案 2 :(得分:0)

由于您希望按list_items.id排序最小list_items.sort,因此需要执行双嵌套查询,如下所示:

SELECT tbl.l_id list_id, tbl.minID, li.description, li.sort, li.likes 
FROM list_items li
JOIN
(
    SELECT l.l_id,MIN(l.id) minID FROM list_items l
    JOIN
    (
        SELECT li.l_id,MIN(li.sort) sort FROM list_items li
          JOIN lists l ON li.l_id = l.id WHERE l.share = 1
         GROUP BY li.l_id
    ) l2
    ON l.l_id = l2.l_id
    AND l.sort = l2.sort
    GROUP BY l.l_id
) tbl
ON  li.id = tbl.minID;