如何在另一个表中查找缺少属性ID的记录ID

时间:2019-07-16 08:44:49

标签: sql postgresql

PostgreSQL数据库有两个表:user_properties和properties。属性表包含具有ID(字典)的所有可能属性的列表。 user_properties表包含用户拥有的属性,并从属性表中引用属性ID。

属性表:

----------------------
  prop_id | prop_name
----------------------
     1    | Email
----------------------
     2    | Phone number
----------------------
     3    | Something else 1
----------------------
     4    | Something else 2
----------------------

user_properties表:

--------------------------------
  user_id | prop_id | prop_value
--------------------------------
    100   |    1    | asd@zxc.com
--------------------------------
    100   |    2    | 1234567
--------------------------------
    100   |    2    | 2345678
--------------------------------
    101   |    3    | *******
--------------------------------
    101   |    3    | +++++++
--------------------------------

我需要知道每个user_id缺少哪些属性。 预期结果应类似于:

-----------------------
  user_id | missing_prop_id
-----------------------
    100   |    3
-----------------------
    100   |    4
-----------------------
    101   |    1
-----------------------
    101   |    2
-----------------------
    101   |    4
-----------------------

4 个答案:

答案 0 :(得分:0)

您可以将except用作:

with properties(prop_id,prop_name) as
(
  values(1, 'Email'),(2, 'Phone number'),
        (3, 'Something else 1'),(4, 'Something else 2')  
), user_properties(  user_id, prop_id, prop_value) as
(
  values(100,1,'asd@zxc.com'),(100,2,'1234567'),(100,2,'2345678'),
        (101,3,'*******'),(101,3,'+++++++') 
), t2 as
(
select u.user_id, p.prop_id as missing_prop_id
  from user_properties u
 cross join properties p
 group by u.user_id, p.prop_id 
except 
select u.user_id, 
       p.prop_id
  from user_properties u
  right join properties p
    on u.prop_id = p.prop_id
 group by u.user_id, p.prop_id   
) 
select * from t2 order by user_id, missing_prop_id;

user_id      missing_prop_id
100          3
100          4
101          1
101          2
101          4

Demo

答案 1 :(得分:0)

您可以简单地通过加入来解决此问题...

SELECT DISTINCT t3.user_id, t3.prop_id FROM 
(SELECT DISTINCT user_id, t2.prop_id FROM user_properties t1, properties t2) t3 
LEFT JOIN user_properties t4 ON t3.user_id = t4.user_id and t3.prop_id = t4.prop_id WHERE t4.prop_id is null

http://sqlfiddle.com/#!17/0f4e3/2/0

答案 2 :(得分:0)

您可以使用cross join生成所有行,并使用left join过滤掉不存在的行:

select u.user_id, p.prop_id
from (select distinct user_id from user_properties
     ) u cross join
     properties p left join
     user_properties up
     on up.user_id = u.user_id and
        up.prop_id = p.prop_id
where up.user_id is null;

大概您有一个users表,因此不需要u的子查询:

select u.user_id, p.prop_id
from users u cross join
     properties p left join
     user_properties up
     on up.user_id = u.user_id and
        up.prop_id = p.prop_id
where up.user_id is null;

答案 3 :(得分:0)

感谢大家的帮助。我本人想出了以下查询:

select mp.user_id, mp.prop_id missing_prop_id from
(select distinct up.user_id, p.prop_id from user_properties up cross join properties p) mp
except
select distinct user_id, prop_id from user_properties

http://sqlfiddle.com/#!17/0f4e3/3/0