我努力解决以下问题: 我的数据库中有2个表: 视频和用户_视频作为视频和用户之间的支点(我从令牌接收user_id,因此用户表位于另一个数据库中)
拥有用户ID,我想选择所有视频并附加包含true或false的列,无论用户是否拥有视频。
到目前为止,我通过以下查询实现了这一点:
SELECT v.*, TRUE AS has_video FROM users_videos AS uv
RIGHT JOIN videos AS v
ON uv.video_id = v.id
WHERE (uv.user_id = 1)
UNION
(
SELECT v.*, FALSE AS has_video FROM videos AS v
EXCEPT
SELECT v.*, FALSE AS has_video FROM users_videos AS uv
RIGHT JOIN videos AS v
ON uv.video_id = v.id
WHERE (uv.user_id = 1)
)
虽然它选择了所有视频3次。是否有针对此类问题的最佳解决方案?
@EDIT ---
表格结构
users_videos:
id integer
user_id integer
video_id integer
videos:
id: integer
title: string
示例数据:
users_videos
| id | user_id | video_id
-------------------------
1 1 1
视频
| id | title |
----------------
1 | Example 1
-----------------
2 | Example 2
-----------------
期望的结果:
| id | title | has_video
------------------------------
1 | Example 1 | true
------------------------------
2 | Example 2 | false
------------------------------
@UPDATE -
使用@Stefano Zanini方法:
SELECT DISTINCT
v.*,
CASE
WHEN uv.user_id IS NULL OR uv.user_id <> 1 THEN FALSE
ELSE TRUE
END has_video
FROM videos v
LEFT JOIN
users_videos uv
ON uv.video_id = v.id
但是我想到了另外一个问题:
如果我想要显示特定类别的视频怎么办? 让我们说它是
上的另一个多对多关系带有pivot videos_categories的视频和类别表
答案 0 :(得分:1)
您可以在没有UNION
和EXCEPT
的情况下执行此操作
select distinct
v.*,
case
when uv.user_id is null or uv.user_id <> 1 then false
else true
end has_video
from videos v
left join
user_videos uv
on uv.video_id = v.id
由于您将此描述为many-to-many
关系,因此多个用户可以拥有相同的视频,因此需要distinct
。
从right
到left
加入的互换只是因为我觉得它更容易阅读。
修改强>
要过滤特定类别的结果(根据问题编辑),您可以在join
where
和一个条件
select distinct
v.*,
case
when uv.user_id is null or uv.user_id <> 1 then false
else true
end has_video
from videos v
join videos_categories vc
on v.id = vc.video_id
join categories c
on vc.category_id = c.id
left join
user_videos uv
on uv.video_id = v.id
where c.category = 'someCategory'
答案 1 :(得分:-1)
您想要选择所有视频,并为每个视频说明用户1是否拥有它。因此,请从视频中进行选择并查看用户的视频:
select
v.*,
id in (select video_id from users_videos where user_id = 1) as has_video
from videos v;