sql表如下:喜欢列饮酒和啤酒,卖柱栏和啤酒,经常与列饮酒者和酒吧。
我之前已经回答了以下声明:
"Drinkers who frequent bars which serve some beer they like"
使用SQL查询:
SELECT DISTINCT y.drinker
FROM likes a, sells, frequents y
WHERE a.beer = sells.beer
AND sells.bar = y.bar
AND y.drinker = a.drinker;
现在,我正在尝试修改上面列出的查询,以回答类似但不同的声明:
"Drinkers who only frequent bars which serve beers they like"
从逻辑上讲,修改只包括那些经常为他们喜欢的啤酒供应酒吧的人,以及消除那些访问任何不供他们喜欢啤酒的酒吧的人。
我最难修改上面的查询以满足第二个语句。
我的思维过程可能是做一个双重否定,例如:获取以下组中不存在的饮酒者名单:不经常酒吧的饮酒者不会出售他们喜欢的啤酒。但正确的实施正在逃避我。
这是我尝试解决此问题的最佳尝试,但我很清楚这是不正确的,因为这个查询仍然会让那些频繁出现一些酒吧(不仅仅是)供应啤酒的消费者喜欢:
SELECT distinct x.drinker
FROM frequents x
WHEREexists (SELECT*
FROM frequents y, sells z, likes u
WHERE x.drinker=y.drinker
AND y.bar = z.bar and z.beer = u.beer
AND y.drinker = u.drinker);
任何帮助都会很棒,感谢您提供的任何见解。
答案 0 :(得分:1)
我认为这是一个有效的解决方案......
子查询用于筛选频繁出现酒吧的饮酒者,他们喜欢的啤酒数为0。
select distinct drinker
from frequents
where drinker not in (
select f.drinker
from frequents f
join sells s on f.bar = s.bar
left join likes l on l.drinker = f.drinker and l.beer = s.beer
group by f.drinker, f.bar
having count(l.drinker) = 0
);
答案 1 :(得分:0)
我为你建了一个小fiddle并想出了你已经建议的内容:一个基于负面选择饮酒者的查询,这些饮酒者去了没有提供啤酒的地方:
SELECT DISTINCT fdrinker FROM frequents f WHERE NOT EXISTS (
SELECT 1 FROM frequents WHERE NOT EXISTS
(SELECT 1 FROM sells WHERE sbar=fbar AND
sbeer IN (SELECT lbeer FROM likes WHERE ldrinker=fdrinker) )
AND fdrinker=f.fdrinker )
最里面的子选择列出所有"喜欢"特定饮酒者的饮料。如果出售至少一个喜欢的啤酒,则下一个外部子选择级别将从sells
表中列出此栏。然后上一级检查经常出现的条形图,以防止任何条形图未能交付"。如果没有这样的"失败"发生顶级选择将呈现饮用者,只有频繁的酒吧,其中至少有一个他们喜欢的啤酒供应。
答案 2 :(得分:0)
饮酒者通常与他们经常出售他们最喜欢的酒吧的数量完全相同:
select drinker
from frequents
group by drinker
having count(bar) = (
select count(distinct f.bar)
from
sells s
inner join likes l on l.beer = s.beer
inner join frequents f on f.bar = s.bar and f.drinker = l.drinker
where f.drinker = frequents.drinker
)
当你无法匹配三个关系三角形时,内部计数会降低。 (注意啤酒,酒吧和饮料的每个测试在内部查询中是如何出现的。)如果你想寻找相反的一组人,你只需将相等测试改为大于。
编辑:
我正在考虑采用其他方法来解决这个问题。有趣的是,您可能会发现右外连接有用(而不是连接表周围的括号。)
frequents
表仍然是下面查询的焦点,逻辑是由找出哪些常去的酒吧也是可以出售喜欢/喜欢的酒吧的想法驱动的。由于外连接,“频率”方面永远不会为空,但只有当一对不能匹配时,“喜欢卖”方才会有空值。 having
子句中的最后一个测试是多余的,但是我希望显示出能够匹配“频繁”两列的计数的对称性,即使只有一个是严格必要的。
select f.drinker
from
frequents f left outer join (
likes l inner join sells s on s.beer = l.beer
) on f.drinker = l.drinker and f.bar = s.bar
group by f.drinker
having count(f.drinker) = count(l.drinker) and count(f.bar) = count(s.bar)
答案 3 :(得分:0)
E.g:
SELECT a.drinker
FROM likes a
LEFT
JOIN ( SELECT DISTINCT f.drinker
FROM frequents f
LEFT
JOIN sells s
ON s.bar = f.bar
JOIN likes l
ON l.drinker = f.drinker
LEFT
JOIN sells x
ON x.bar = f.bar
AND x.beer = l.beer
WHERE x.beer IS NULL
) b
ON b.drinker = a.drinker
WHERE b.drinker IS NULL;