2012-07-24 94 views
1

當我使用下面的查詢沒有限制嵌套子查詢限制子查詢

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

我該怎麼做才能得到正確的結果?

+1

所以你想限制photos_list級聯到2的照片數量? – dnagirl 2012-07-24 12:45:42

+2

'LIMIT'適用於整個查詢。您只需從'gallery'中將兩行總計的行與您的查詢結果相關聯,這兩行恰好與'id = 2'關聯。 – mellamokb 2012-07-24 12:45:52

+0

@dnagirl,是的,我正在嘗試限制照片。 – serg66 2012-07-24 12:52:24

回答

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` 
+0

謝謝!我已經想過這種方式。但性能如何?如果會有長串?但似乎這是唯一的工作解決方案。 – serg66 2012-07-24 13:41:20

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 
+0

謝謝!它的工作原理 – serg66 2012-07-24 14:20:02

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 
+0

「WHERE」子句中的「c.id」無法訪問外部查詢的比賽表。這不幸的是不會執行。 – 2012-07-24 14:09:54

+0

是的,當我嘗試執行它時,出現一個錯誤:#1054 - 'where子句'中的未知列'c.id' – serg66 2012-07-24 14:21:33

1

你如何決定應該返回哪一個可能的特定比賽的照片集?這是否意味着隨機的事情?或者是2張最近的照片,還是2張最高評價的照片,或者是其他一些標準?一旦你可以設置一個條件來選擇照片,其餘的是直截了當的。此查詢會得到你的2張爲每個contest_id最高photo_ids:

 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 
+0

非常感謝您提供如此詳細的答案! – serg66 2012-07-25 18:20:01

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