我使用下面的代码,但没有返回我期望的内容,
表关系,
每个gallery
都包含多个media
,每个媒体都包含多个media_user_action
。
我想计算每个gallery
多少media_user_action
并按此计数订购
rows: [
{
"id": 1
},
{
"id": 2
}
]
此查询将返回类似
的重复图库行rows: [
{
"id": 1
},
{
"id": 1
},
{
"id": 2
}
...
]
我认为因为在LEFT JOIN
子查询中只选择media_user_action
行media_id
,
需要按gallery_id
进行分组吗?
SELECT
g.*
FROM gallery g
LEFT JOIN gallery_media gm ON gm.gallery_id = g.id
LEFT JOIN (
SELECT
media_id,
COUNT(*) as mua_count
FROM media_user_action
WHERE type = 0
GROUP BY media_id
) mua ON mua.media_id = gm.media_id
ORDER BY g.id desc NULLS LAST OFFSET $1 LIMIT $2
表
gallery
id |
1 |
2 |
gallery_media
id | gallery_id fk gallery.id | media_id fk media.id
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
....
media_user_action
id | media_id fk media.id | user_id | type
1 | 1 | 1 | 0
2 | 1 | 2 | 0
3 | 3 | 1 | 0
...
media
id |
1 |
2 |
3 |
更新
还有我需要选择的其他表,当用户输入选项然后构建查询时,这是像https://jsfiddle.net/g8wtqqqa/1/这样的函数的一部分。
所以我更正了我的问题,如果用户想通过它计算media_user_action
顺序,我需要找到一种方法,我想知道如何将这些放入子查询中,可能不会更改任何其他代码
基于下面的@trincot答案我更新代码,只在顶部添加media_count
稍微更改并将其放在子查询中。是我想要的,
现在他们是由gallery.id分组,但排序media_count desc和asc是相同的结果不起作用我无法找到原因?
SELECT
g.*,
row_to_json(gi.*) as gallery_information,
row_to_json(gl.*) as gallery_limit,
media_count
FROM gallery g
LEFT JOIN gallery_information gi ON gi.gallery_id = g.id
LEFT JOIN gallery_limit gl ON gl.gallery_id = g.id
LEFT JOIN "user" u ON u.id = g.create_by_user_id
LEFT JOIN category_gallery cg ON cg.gallery_id = g.id
LEFT JOIN category c ON c.id = cg.category_id
LEFT JOIN (
SELECT
gm.gallery_id,
COUNT(DISTINCT mua.media_id) media_count
FROM gallery_media gm
INNER JOIN media_user_action mua
ON mua.media_id = gm.media_id AND mua.type = 0
GROUP BY gm.gallery_id
) gm ON gm.gallery_id = g.id
ORDER BY gm.media_count asc NULLS LAST OFFSET $1 LIMIT $2
答案 0 :(得分:2)
与 gallery_media 表的连接会使您的结果倍增。计数和分组应该在您进行连接后进行。
你可以这样做:
SELECT g.id,
COUNT(DISTINCT mua.media_id)
FROM gallery g
LEFT JOIN gallery_media gm
ON gm.gallery_id = g.id
LEFT JOIN media_user_action mua
ON mua.media_id = gm.id AND type = 0
GROUP BY g.id
ORDER BY 2 DESC
如果您还需要其他信息,可以使用上面的(以简化形式)作为子查询,您可以将其与其他任何需要的东西连接,但不会乘以行数:
SELECT g.*
row_to_json(gi.*) as gallery_information,
row_to_json(gl.*) as gallery_limit,
media_count
FROM gallery g
LEFT JOIN (
SELECT gm.gallery_id,
COUNT(DISTINCT mua.media_id) media_count
FROM gallery_media gm
INNER JOIN media_user_action mua
ON mua.media_id = gm.id AND type = 0
GROUP BY gm.gallery_id
) gm
ON gm.gallery_id = g.id
LEFT JOIN gallery_information gi ON gi.gallery_id = g.id
LEFT JOIN gallery_limit gl ON gl.gallery_id = g.id
ORDER BY media_count DESC NULLS LAST
OFFSET $1
LIMIT $2
以上假设 gallery_id 在表 gallery_information 和 gallery_limit 中是唯一的。
答案 1 :(得分:0)
您按media_id
进行分组以计算,但由于一个gallery
可以包含多个gallery_media
,因此您仍然会为一个gallery
设置多行。您可以从子选择中总结mua_count
:
SELECT g.*, sum(mua_count)
FROM gallery g
LEFT JOIN gallery_media gm ON gm.gallery_id = g.id
LEFT JOIN (
SELECT media_id,
COUNT(*) as mua_count
FROM media_user_action
WHERE type = 0
GROUP BY media_id
) mua ON mua.media_id = gm.media_id
GROUP BY g.id
ORDER BY g.id desc NULLS LAST;
id | sum
----+-----
2 | 1
1 | 2
或者您可以JOIN
一直g.id
在SELECT g.id, count(*)
FROM gallery g
JOIN gallery_media gm ON gm.gallery_id = g.id
JOIN media_user_action mua ON mua.media_id = gm.id
GROUP BY g.id
ORDER BY count DESC;
上进行一次分组:
id | count
----+-------
1 | 2
2 | 1
{{1}}
答案 2 :(得分:-1)
如果您只想显示表gallery
(带select g.*
)的数据,那么为什么要加入其他表?外连接要么将一个或多个记录连接到每个主记录(取决于在外连接表中找到多少匹配),所以毫不奇怪你得到重复(在你的情况下,因为图库ID 1在{{1}中有两个匹配})。