选择“拥有”列的多对多关系

时间:2017-03-31 12:33:24

标签: sql postgresql many-to-many

我努力解决以下问题: 我的数据库中有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的视频和类别表

2 个答案:

答案 0 :(得分:1)

您可以在没有UNIONEXCEPT的情况下执行此操作

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

rightleft加入的互换只是因为我觉得它更容易阅读。

修改

要过滤特定类别的结果(根据问题编辑),您可以在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;