MYSQL внутреннее объединение 3-я таблица сортировка самые последние - PullRequest
0 голосов
/ 20 января 2019

У меня есть 3 таблицы, категории / сообщения / галерея.

Требуется вернуть список категорий, отсортированных в порядке сортировки с первой фотографией gsort из новейшего поста. Если нет фото или сообщения, то покажите ноль.

Первая фотография для каждого сообщения, как правило, будет gsort = 1, однако, если эта фотография удалена, она должна показывать самое низкое значение gsort, так как я тогда покажу изображение заполнителя.

categories
----------
cid cname   curl    csort
1   ccc     ccc/    3   
2   bbb     bbb/    2
3   aaa     aaa/    1
4   ddd     ddd/    4


posts
-----
pid pname   purl            cid padded              poffon
1   apples  apples.html     2   2019-01-02 10:11:12 1
2   orange  orange.html     1   2019-01-02 10:12:00 1
3   grape   red-grapes.html 1   2019-01-06 10:15:12 1
4   banana  bannas.html     2   2019-01-08 10:19:54 0   //Note: this post is hidden
5   kiwi    kiwi-fruit.html 3   2019-01-10 10:26:20 1


gallery_photos
--------------
gid pid gsrc        gsort
1   1   img01a.jpg  6
2   1   img01b.jpg  2
3   1   img01c.jpg  4
4   3   img03a.jpg  2
5   3   img03b.jpg  1
6   3   img03c.jpg  4
7   3   img03d.jpg  3
8   2   img02a.jpg  1
9   1   img01d.jpg  5
10  1   img01e.jpg  3

Ожидаемые результаты >>>

cid cname   curl    gsrc
3   aaa     aaa/    null        //Note: no photos exist for this post
2   bbb     bbb/    img02a.jpg  //Note: 1 post exists for this category, show gsrc for lowest gsort
1   ccc     ccc/    img03b.jpg  //Note: 2 posts exist for this category, show gsrc for lowest gsort for the latest post date
4   ddd     ddd/    null        //Note: no posts exist for this category... a holding page with other content will be shown

Вот что я получил до сих пор для запроса, НО он возвращает слишком много результатов:

SELECT C.id
     , C.name
     , GA.medium_path AS gsrc
     , GA.gsort
  FROM CATEGORIES C 
  LEFT 
  JOIN POSTS P 
    ON C.cid = P.cid 
  JOIN 
     ( SELECT cid
            , MAX(padded) max_date 
         FROM POSTS 
        GROUP 
           BY cid 
        ORDER 
           BY padded DESC
     ) t 
    ON t.max_date = P.padded 
   AND C.cid = P.cid 
  LEFT 
  JOIN GALLERY GA 
    ON GA.pid = P.pid

Большое спасибо заранее

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Вот решение, которое расширяет вашу логику. Он использует серию LEFT JOIN s для идентификации, затем извлекает последнюю запись, а затем идентифицирует и вытаскивает более раннюю картинку.

SELECT 
    c.cid, 
    c.cname, 
    c.curl,
    g.gsrc, 
    g.gsort 
FROM 
    categories c
    LEFT JOIN (SELECT cid, MAX(padded) padded FROM posts WHERE poffon = 1 GROUP BY cid) pmax ON pmax.cid = c.cid
    LEFT JOIN posts p ON p.cid = c.cid AND p.padded = pmax.padded
    LEFT JOIN (SELECT pid, MIN(gsort) gsort FROM gallery_photos GROUP BY pid) gmin ON gmin.pid = p.pid
    LEFT JOIN gallery_photos g ON g.pid = p.pid AND g.gsort = gmin.gsort
ORDER BY c.cname

Я проверил это в этой скрипте дБ , и результат соответствует ожидаемому результату (за исключением gsrc для cid 2, который, я считаю, должен быть 'img01b.jpg' вместо 'img02a.jpg' ).

 WITH
     categories AS (
         SELECT 1 cid, 'ccc' cname, 'ccc/' curl, 3 csort
         UNION SELECT 2, 'bbb', 'bbb/', 2
         UNION SELECT 3, 'aaa', 'aaa/', 1
         UNION SELECT 4, 'ddd', 'ddd/', 4
     ),
     posts AS (
         SELECT 1 pid, 'apples' pname, 'apples.html' purl, 2 cid, '2019-01-02 10:11:12' padded, 1 poffon
         UNION SELECT 2, 'orange', 'orange.html', 1, '2019-01-02 10:12:00', 1
         UNION SELECT 3, 'grape', 'red-grapes.html', 1, '2019-01-06 10:15:12', 1
         UNION SELECT 4, 'banana', 'bannas.html', 2, '2019-01-08 10:19:54', 0
         UNION SELECT 5, 'kiwi', 'kiwi-fruit.html', 3, '2019-01-10 10:26:20', 1
     ),
     gallery_photos AS (
         SELECT 1 gid, 1 pid, 'img01a.jpg' gsrc, 6 gsort
         UNION SELECT 2, 1, 'img01b.jpg', 2
         UNION SELECT 3, 1, 'img01c.jpg', 4
         UNION SELECT 4, 3, 'img03a.jpg', 2
         UNION SELECT 5, 3, 'img03b.jpg', 1
         UNION SELECT 6, 3, 'img03c.jpg', 4
         UNION SELECT 7, 3, 'img03d.jpg', 3
         UNION SELECT 8, 2, 'img02a.jpg', 1
         UNION SELECT 9, 1, 'img01d.jpg', 5
         UNION SELECT 10, 1, 'img01e.jpg', 3
     )
 SELECT 
     c.cid, 
     c.cname, 
     c.curl,
     g.gsrc, 
     g.gsort 
 FROM 
     categories c
     LEFT JOIN (SELECT cid, MAX(padded) padded FROM posts WHERE poffon = 1 GROUP BY cid) pmax ON pmax.cid = c.cid
     LEFT JOIN posts p ON p.cid = c.cid AND p.padded = pmax.padded
     LEFT JOIN (SELECT pid, MIN(gsort) gsort FROM gallery_photos GROUP BY pid) gmin ON gmin.pid = p.pid
     LEFT JOIN gallery_photos g ON g.pid = p.pid AND g.gsort = gmin.gsort
 ORDER BY c.cname;

 cid | cname | curl | gsrc       | gsort
 --: | :---- | :--- | :--------- | ----:
   3 | aaa   | aaa/ | <em>null</em>       |  <em>null</em>
   2 | bbb   | bbb/ | img01b.jpg |     2
   1 | ccc   | ccc/ | img03b.jpg |     1
   4 | ddd   | ddd/ | <em>null</em>       |  <em>null</em>
 
0 голосов
/ 20 января 2019

Этот запрос должен дать вам результаты, которые вы хотите. Он использует два подзапроса; один для получения новейшего сообщения по категории, а второй для получения фотографии с самым низким значением gsort для каждого сообщения. Результаты этих двух подзапросов затем LEFT JOIN заносятся в таблицу categories, чтобы получить самое новое сообщение с самым низким значением gsort для категории:

SELECT c.*, pm.pid, pm.pname, pm.purl, pm.padded, pm.poffon, gm.gsrc, gm.gsort
FROM categories c
LEFT JOIN (SELECT p.*
           FROM posts p
           JOIN (SELECT cid, MAX(padded) AS latest
                 FROM posts
                 WHERE poffon = 1
                 GROUP BY cid) pl ON pl.cid = p.cid AND pl.latest = p.padded
          ) pm ON pm.cid = c.cid
LEFT JOIN (SELECT g.*
           FROM gallery_photos g
           JOIN (SELECT pid, MIN(gsort) AS earliest
                 FROM gallery_photos
                 GROUP BY pid) ge ON ge.pid = g.pid AND ge.earliest = g.gsort
          ) gm ON gm.pid = pm.pid
ORDER BY cname

Выход:

cid     cname   curl    csort   pid     pname   purl                padded                  poffon  gsrc        gsort
3       aaa     aaa/    1       5       kiwi    kiwi-fruit.html     2019-01-10 10:26:20     1       
2       bbb     bbb/    2       1       apples  apples.html         2019-01-02 10:11:12     1       img01b.jpg  2
1       ccc     ccc/    3       3       grape   red-grapes.html     2019-01-06 10:15:12     1       img03b.jpg  1
4       ddd     ddd/    4                       

Демонстрация по dbfiddle

Примечание Я думаю, что ваш ожидаемый результат для категории bbb неверен, для cid = 2 самое последнее сообщение - это сообщение 1, а самое низкое значение gsort для этого сообщения - 2, что соответствует img01b. img02a принадлежит посту 2, который находится в cid 1, а не 2.

...