我有三张桌子:历史,视频和用户。 以下两个查询为每个视频显示法国用户或德国用户的观看次数:
SELECT V.idVideo, COUNT(H.idVideo) AS nb_fr
FROM HISTORY H
INNER JOIN VIDEO V ON V.idVideo = H.idVideo
INNER JOIN USER U ON U.idUser = H.idUser
WHERE U.nationality = 'french'
GROUP BY H.idVideo
ORDER BY V.idVideo;
和
SELECT V.idVideo, COUNT(H.idVideo) AS nb_ge
FROM HISTORY H
INNER JOIN VIDEO V ON V.idVideo = H.idVideo
INNER JOIN USER U ON U.idUser = H.idUser
WHERE U.nationality = 'german'
GROUP BY H.idVideo
ORDER BY V.idVideo
但是如何将这两个查询结合起来只有一个? 我想要这样的东西:
idVideo | nb_fr | nb_ge
-----------------------
1 | 5 | 4
2 | 3 | 6
3 | 2 | 8
4 | 3 | 3
答案 0 :(得分:9)
使用case
表达式进行条件聚合:
SELECT V.idVideo,
COUNT(case when U.nationality = 'french' then H.idVideo end) AS nb_fr,
COUNT(case when U.nationality = 'german' then H.idVideo end) AS nb_ge
FROM HISTORY H
INNER JOIN VIDEO V ON V.idVideo = H.idVideo
INNER JOIN USER U ON U.idUser = H.idUser
WHERE U.nationality in ('french', 'german')
GROUP BY V.idVideo
ORDER BY V.idVideo;
请注意对GROUP BY V.idVideo
的更改,因为这是所选列。
答案 1 :(得分:5)
您可以使用CASE EXPRESSION
的条件聚合:
SELECT V.idVideo,
COUNT(CASE WHEN U.nationality = 'french' THEN 1 END) AS nb_fr,
COUNT(CASE WHEN U.nationality = 'german' THEN 1 END) AS nb_ge
FROM HISTORY H
INNER JOIN VIDEO V ON V.idVideo = H.idVideo
INNER JOIN USER U ON U.idUser = H.idUser
GROUP BY H.idVideo
ORDER BY V.idVideo
答案 2 :(得分:4)
使用条件聚合:
SELECT H.idVideo,
SUM(CASE WHEN U.nationality = 'french' THEN 1 ELSE 0 END) as nb_fr,
SUM(CASE WHEN U.nationality = 'german' THEN 1 ELSE 0 END) as nb_ge
FROM HISTORY H INNER JOIN
USER U
ON U.idUser = H.idUser
GROUP BY H.idVideo
ORDER BY H.idVideo;
另请注意,查询可以简化。可能不需要JOIN
到VIDEO
(假设idVideo
是唯一的,这是一个非常合理的假设)。
此外,ORDER BY
和GROUP BY
应使用相同的列引用。
答案 3 :(得分:2)
从Oracle 11.1开始,您可以使用PIVOT操作:
select idvideo, nb_fr, nb_ge
from ( select h.idvideo, u.nationality
from history h inner join user u on h.iduser = u.iduser
)
pivot ( count(*) for nationality in ('french' as nb_fr, 'german' as nb_ge) )
order by idvideo
;