我有一个表 ORDERS,其中包含“user”、“mark”和“mark_cnt”列。 我需要编写这样一个 sql 查询,它将输出那些与 user2 具有相同标记集的用户。他有 1 个 m1、2 个 m2 和 1 个 m4。所以,基本上,这意味着该集合必须与其他用户标记完全相交。
U1 有:m1、m2、m2、m3、m4、m4、m4
U2 有:m1、m2、m2、m4
U3 有:m1、m2、m2、m2、m3、m3、m3、m3、m3、m3、m3、m4、m4、m4、m5
U4 有:m1、m2、m4
我尝试使用此代码:
select user
from orders
where mark in (
select mark from orders where user='u2'
)
group by user
having count(mark) = (select count(mark) from order where user='u2')
正确答案一定是U1和U3
我使用问题中的数据和尽力解决方案创建了一个 DBFiddle。
我阅读问题的方式是,为了让用户 A 与用户 B 匹配,用户 A 的标记多重集必须是用户 B 多重集的子集。 U1 和 U3 配对满足此条件,但其他配对也满足此条件。例如,U4 和 U1 对。
字面解释是用户 A 的多重集必须完全等于用户 B 的多重集,但这不会产生任何答案。放宽该条件以排除根本不包含在其中一个多重集中的元素将产生 U1 和 U2 作为答案,这与建议的正确答案不同。
由于问题与预期答案相矛盾,这是一个“尽力而为”的答案,您应该澄清包含该行的实际情况。例如,您可以解释为什么 U1 和 U3 是“唯一”答案,或者答案中还有哪些其他对。我不符合在评论中询问的声誉:P
以下是查询的解释:从显而易见的开始:我们想要
SELECT
orders
用户名:
select "user" from orders
select
o1."user"
from
orders o1
inner join
orders o2
on o1.mark = o2.mark
select
o1."user"
from
orders o1
inner join
orders o2
on (
o1."user" != o2."user" and
o1.mark = o2.mark
)
select
o1."user",
o2."user",
o2.mark_cnt >= o1.mark_cnt
as "is_subset"
from
orders o1
inner join
orders o2
on (
o1."user" != o2."user" and
o1.mark = o2.mark
)
is_subset
GROUP BY
来计算每对所有行的逻辑 AND
:
select
o1."user",
o2."user"
from
orders o1
inner join
orders o2
on (
o1."user" != o2."user" and
o1.mark = o2.mark
)
group by
o1."user", o2."user"
having
bool_and(
o2.mark_cnt >= o1.mark_cnt
)
INNER JOIN
LEFT JOIN
来“优先考虑”用户 1 中的行。由于我们切换到外连接,我们还需要使用 o2.mark_cnt
来处理可能是 NULL
的 coalesce
:
select
o1."user",
o2."user"
from
orders o1
left join
orders o2
on (
o1."user" != o2."user" and
o2.mark = o1.mark
)
group by
o1."user", o2."user"
having
bool_and(
coalesce(o2.mark_cnt, 0) >= o1.mark_cnt
)