【问题标题】:MYSQL inner join 3rd table sort most recentMYSQL 内连接第三个表排序最近
【发布时间】:2019-01-20 12:16:17
【问题描述】:

我有 3 个表格,类别/帖子/图库。

需要返回一个按 csort 顺序排序的类别列表,其中包含最新帖子中的第一张 gsort 照片。如果没有照片或帖子,则显示 null。

每个帖子的第一张照片通常是 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

在此先感谢

【问题讨论】:

  • 您使用的是哪个版本的 MySQL?使用 8.0 可能更容易实现这一点。
  • @GMB 它的 v5.5.52,由于其他资源需要这样做,因此实际上不是更改 MySQL 版本的选项。
  • 这些答案之一是否解决了您的问题?如果没有,您能否提供更多信息来帮助回答?否则,请考虑将最能解决您的问题的答案标记为已接受(上/下投票箭头下的复选标记)。见stackoverflow.com/help/someone-answers

标签: mysql sql subquery inner-join


【解决方案1】:

这是一个扩展您的逻辑的解决方案。它使用一系列LEFT JOINs进行识别,然后拉出最新的帖子,然后识别并拉出较早的图片。

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

我在this db fiddle 中对其进行了测试,结果与您的预期输出相匹配(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;

西德 |名称 |卷曲 | gsrc |排序 --: | :---- | :--- | :--------- | ----: 3 |啊!啊/ | | 2 | bbb | bbb/ | img01b.jpg | 2 1 |抄送 |抄送/ | img03b.jpg | 1 4 | dd | ddd/ | |

【讨论】:

    【解决方案2】:

    这个查询应该会给你想要的结果。它使用两个子查询;一个按类别获取最新帖子,第二个获取每个帖子的gsort 值最低的照片。然后将这两个子查询的结果LEFT JOINed 到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                       
    

    Demo on dbfiddle

    注意我认为您对类别 bbb 的预期结果是错误的,对于 cid=2,最近的帖子是帖子 1,并且该帖子的最低 gsort 值是 2,对应于img01bimg02a 属于帖子 2,在 cid 1 中,而不是 2。

    【讨论】:

      猜你喜欢
      • 2019-01-11
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 2014-02-24
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 2014-10-16
      相关资源
      最近更新 更多