我有这两张桌子:
Person
(id, name, address, age
)Knows
(personA_id, personB_id
)我希望返回比他们所知道的Person
年龄超过5岁的Person
的名字。
我正在尝试这个:
SELECT
P1.name
FROM
Persons P1, Persons P2, Knows K1
WHERE
P1.id = K1.personA_id
AND P2.id = K1.personB_id
AND NOT EXISTS (SELECT *
FROM Persons P3, Persons P4, Knows K2
WHERE P3.id = K2.personA_id
AND P4.id = K2.personB_id
AND (P3.age - P4.age) <= 5)
但它不起作用,我也不太清楚为什么。你能指出我正确的方向吗?提前致谢
答案 0 :(得分:2)
对于每个人,找到他们的年龄和他们认识的每个人的年龄。然后计算他们认识的人的最大年龄并过滤掉:
SELECT P1.name
FROM Persons P1 JOIN
Knows K1
ON P1.id = K1.personA_id JOIN
Persons P2
ON P2.id = K1.personB_id
GROUP BY P1.name, P1.age
HAVING ( p1.age - MAX(p2.age) ) > 5;
虽然您可以使用exists
执行此操作,但我认为聚合是一种更简单的查询和更简单的逻辑。
答案 1 :(得分:1)
如果您只需要显示年龄差异> 5的关系
SELECT P1.name
FROM Persons P1
INNER JOIN Knows K1 ON P1.id = K1.personA_id
INNER JOIN Persons P2 ON P2.id = K1.personB_id
WHERE (P1.age - P2.age) > 5
如果你只需要让人们认为他们的所有关系至少有5年的年龄差异,那么@Gordon Linoff的答案就是你要找的
答案 2 :(得分:1)
如果你真的坚持存在,这可以解决问题:
SELECT p1.name AS the_older
, p2.name AS the_younger
FROM Persons p1, Persons p2
WHERE p1.age - p2.age > 5 -- They are more than 5 years older
AND EXISTS ( -- than the one they know
SELECT *
FROM Knows Kx
WHERE Kx.personA_id = p1.id AND Kx.personB_id = p2.id
);
可以使用JOIN
语法完成类似的事情(年龄条件也可以移入连接条件):
SELECT p1.name AS the_older
, p2.name AS the_younger
FROM Persons p1
JOIN Persons p2 ON EXISTS (
SELECT * FROM Knows Kx
WHERE Kx.personA_id = p1.id AND Kx.personB_id = p2.id
)
WHERE p1.age - p2.age > 5
;
更新:澄清问题后:
SELECT p1.name
FROM Persons p1
WHERE EXISTS ( -- must have friends
SELECT * FROM Knows Kx
WHERE Kx.personA_id = p1.id
)
AND NOT EXISTS ( -- but no friends less than 5 years younger
SELECT *
FROM Knows Knx
JOIN Persons p2 ON Knx.personB_id = p2.id
WHERE Knx.personA_id = p1.id
AND p1.age - p2.age <= 5
);
);
答案 3 :(得分:1)
起点是Knows表的结合:
SELECT personA_id ,
personB_id
FROM @k k
UNION
SELECT personB_id ,
personA_id
FROM @k k
如果您只是从表格Knows的一侧进行验证,则会得到不正确的结果。
DECLARE @p TABLE
(
id INT ,
name NVARCHAR(MAX) ,
age INT
)
DECLARE @k TABLE
(
personA_id INT ,
personB_id INT
)
INSERT INTO @p
VALUES ( 1, 'a', 10 ),
( 2, 'b', 14 ),
( 3, 'c', 30 ),
( 6, 'f', 35 ),
( 7, 'g', 45 )
INSERT INTO @k
VALUES ( 1, 2 ),
( 1, 3 ),
( 2, 3 ),
( 7, 6 )
SELECT t.personA_id ,
t.name
FROM ( SELECT personA_id ,
name ,
paage - pbage AS diff
FROM ( SELECT personA_id ,
personB_id ,
pa.age paage ,
pb.age pbage ,
pa.name
FROM @k k
JOIN @p pa ON pa.id = k.personA_id
JOIN @p pb ON pb.id = k.personB_id
UNION
SELECT personB_id ,
personA_id ,
pb.age pbage ,
pa.age paage ,
pb.name
FROM @k k
JOIN @p pa ON pa.id = k.personA_id
JOIN @p pb ON pb.id = k.personB_id
) k
) t
GROUP BY t.personA_id ,
t.name
HAVING ( MIN(diff) > 5 )
输出:
personA_id name
3 c
7 g
如果您将直接加入表Knows,那么您将获得:
SELECT t.personA_id ,
t.name
FROM ( SELECT personA_id ,
name ,
paage - pbage AS diff
FROM ( SELECT personA_id ,
personB_id ,
pa.age paage ,
pb.age pbage ,
pa.name
FROM @k k
JOIN @p pa ON pa.id = k.personA_id
JOIN @p pb ON pb.id = k.personB_id
) k
) t
GROUP BY t.personA_id ,
t.name
HAVING ( MIN(diff) > 5 )
输出:
personA_id name
7 g