子查询中的限制

时间:2012-07-24 12:43:02

标签: mysql subquery limit

当我使用以下查询而没有嵌套在子查询中的LIMIT

SELECT   `c`.*, 
         GROUP_CONCAT(g.photo SEPARATOR "|") AS `photos_list` 
  FROM   `contests` AS `c` 
              LEFT JOIN 
                  (
                      SELECT   `gallery`.`contest_id`, 
                               `gallery`.`photo` 
                        FROM   `gallery`
                   ) AS `g` ON c.id = g.contest_id 
GROUP BY `c`.`id`

一切正常

id   title    photos_list 

1    title1   50026c35632eb.jpg
2    title2   50026ac53567f.jpg|50026ac5ec82e.jpg|500e71557270f....

当我添加LIMIT时,我只在一行中获得“photos_list”。以下查询

SELECT   `c`.*, 
         GROUP_CONCAT(g.photo SEPARATOR "|") AS `photos_list` 
  FROM   `contests` AS `c` 
              LEFT JOIN 
                  (
                      SELECT   `gallery`.`contest_id`, 
                               `gallery`.`photo` 
                        FROM   `gallery`
                       LIMIT    0, 2
                   ) AS `g` ON c.id = g.contest_id 
GROUP BY `c`.`id`

将返回

id  title   photos_list 

1   title1  NULL
2   title2  50026ac46ea05.jpg|50026ac53567f.jpg

id = 1 的项目必须包含photos_list,但事实并非如此。值得注意的是, LIMIT 适用于 id = 2 的项目。

我该怎么做才能得到正确的结果?

5 个答案:

答案 0 :(得分:2)

SELECT   `c`.*, 
     GROUP_CONCAT(g.photo SEPARATOR "|") AS `photos_list` 
FROM   `contests` AS `c` 
          LEFT JOIN 
              (
                  SELECT   `gallery`.`contest_id`, 
                           `gallery`.`photo` 
                    FROM   `gallery`
               ) AS `g` ON c.id = g.contest_id 
GROUP BY `c`.`id`

将GROUP_CONCAT更改为:

SUBSTRING_INDEX(GROUP_CONCAT(g.photo SEPARATOR "|"),'|',2) AS `photos_list` 

答案 1 :(得分:2)

您可以使用时间戳(例如AND photo_date > gsub.photo_date)或更复杂的条件执行类似的操作。唯一需要注意的是,如果有几行都符合条件(例如,几张照片具有相同的时间戳),则将包括所有这些行。这就是为什么我选择了photo_id,这可能是唯一的。

将其插入原始查询中,如下所示:

SELECT c.id, c.title,
       GROUP_CONCAT(g.photo SEPARATOR "|") AS photos_list
FROM   contests AS c
  LEFT JOIN (
    //put query from above here
  ) AS g 
ON c.id = g.contest_id  GROUP BY c.id

答案 2 :(得分:1)

这也有效。但是,如果没有包装其他SELECT子句,如果没有比赛照片,则比赛将不会显示。

SELECT c.*, GROUP_CONCAT(g.photo SEPARATOR "|") AS photo_list
FROM 
  contests c 
LEFT JOIN
  (SELECT *, @num:= if(@contest = contest_id, @num + 1,1) as row_num,
             @contest := contest_id as c_id
   FROM gallery
   ORDER BY contest_id) AS g
ON c.id = g.contest_id
WHERE g.row_num <= 2
GROUP BY c.id, c.title

答案 3 :(得分:1)

<击>

<击>
SELECT c.*, ((
  SELECT GROUP_CONCAT(temp.photo SEPARATOR "|")
  FROM (SELECT photo FROM gallery g WHERE c.id = g.contest_id LIMIT 2) temp
)) AS photo_list
FROM contests c

<击>

抱歉答案错误。我不是说以下解决方案是最佳解决方案,但至少它是有效的。顺便说一句,在这个新的解决方案中,我假设你gallery表有一个名为id的主键。

SELECT c.*, GROUP_CONCAT(g.photo SEPARATOR "|") AS photos_list
FROM contests AS c
LEFT JOIN (
    SELECT
        g_0.*
    FROM (
        SELECT
            g_1.*
            , ((SELECT COUNT(*) FROM gallery g_2 WHERE g_2.contest_id = g_1.contest_id AND g_2.id <= g_1.id)) AS i
        FROM gallery g_1
    ) g_0
    WHERE
        g_0.i <= 2
) g ON (c.id = g.contest_id)
GROUP BY c.id

答案 4 :(得分:1)

您如何决定应该返回特定比赛中哪两张可能的照片?它是否意味着随意的事情?或者它是最近的2张照片,或者是评价最高的2张照片,还是其他一些标准?一旦你可以设定一个选择照片的条件,其余的是直截了当的。此查询可为您提供每张contest_id具有最高photo_id的2张照片:

     SELECT contest_id, photo, photo_id
       FROM gallery gsub
       WHERE (
         SELECT COUNT(*) FROM gallery 
           WHERE contest_id=gsub.contest_id //for each category
           AND photo_id > gsub.photo_id 
       ) < 2 //if number of photo_ids > than this photo_id < 2, keep this photo
       ORDER BY contest_id

您可以使用时间戳(例如AND photo_date > gsub.photo_date)或更复杂的条件执行类似的操作。唯一需要注意的是,如果有几行都符合条件(例如,几张照片具有相同的时间戳),则将包括所有这些行。这就是我选择photo_id的原因,这可能是唯一的。

将其插入原始查询中,如下所示:

SELECT c.id, c.title,
           GROUP_CONCAT(g.photo SEPARATOR "|") AS photos_list
    FROM   contests AS c
      LEFT JOIN (
        //put query from above here
      ) AS g 
    ON c.id = g.contest_id  GROUP BY c.id