我有一对多关系看起来像这样:
| Parent | | Child |
| id | | id |
| | |parentID|
| | | date |
我正在尝试构建一个查询,以便我得到所有拥有子记录的父母,其中所有记录都在指定日期之前有一个日期。
像这样的东西
SELECT * FROM parent
JOIN child on child.parentid = parent.id
WHERE child.date <= '10/13/2010'
但问题是我得到的父母在指定的日期之前有孩子的日期,并且在指定的日期之后有一个日期的子记录,当我只想要在给定日期之前有日期的孩子的父母。
有没有人对如何处理此案有一些建议?
谢谢!
答案 0 :(得分:2)
使用:
SELECT p.*
FROM PARENT p
WHERE EXISTS(SELECT NULL
FROM CHILD c
WHERE c.parentid = p.id
AND c.date <= '2010-10-13')
AND NOT EXISTS(SELECT NULL
FROM CHILD c
WHERE c.parentid = p.id
AND c.date > '2010-10-13')
每个人都会告诉你使用JOIN“因为它们更快”,但通常他们不知道使用的影响 - 如果你不需要来自的信息支持表,你不应该加入它。那是因为在这种情况下不止一个孩子会产生重复的PARENT记录。 JOIN和DISTINCT或GROUP BY与IN或EXISTS之间的权衡可能是平等的,但没有正确处理重复数据的麻烦。
答案 1 :(得分:2)
SELECT
*
FROM
Parent
WHERE
EXISTS (SELECT * FROM Child WHERE Child.ParentId = Parent.Id AND [date] <= '2010-10-13')
AND
NOT EXISTS (SELECT * FROM Child WHERE Child.ParentId = Parent.Id AND [date] > '2010-10-13')
答案 2 :(得分:0)
我彻底阅读了你的问题并总结如下:
见下面的代码。我们使用HAVING语句确保孩子在X之后没有日期。
SELECT P.*
FROM Parent P
WHERE P.id IN
(
SELECT C.parentID
FROM Child C
GROUP BY C.parentID
HAVING MAX(CASE WHEN date > '2010-10-13' THEN 1 ELSE 0 END) = 0
/* do not return children that have a date after 2010-10-13 */
)
想要一起玩的示例架构。 (SQL Server)
(“date”被称为“mydate”,以避免必须转义保留字。)
CREATE TABLE Parent (id INT PRIMARY KEY);
CREATE TABLE Child (id INT IDENTITY PRIMARY KEY, parentID INT NOT NULL REFERENCES Parent(id), mydate DATE );
INSERT INTO Parent VALUES (1);
INSERT INTO Parent VALUES (2);
INSERT INTO Parent VALUES (3);
INSERT INTO Parent VALUES (4);
INSERT INTO Child (parentID, mydate) VALUES (1,'2010-10-11')
INSERT INTO Child (parentID, mydate) VALUES (1,'2010-10-12')
INSERT INTO Child (parentID, mydate) VALUES (1,'2010-10-13')
INSERT INTO Child (parentID, mydate) VALUES (2,'2010-10-12')
INSERT INTO Child (parentID, mydate) VALUES (2,'2010-10-13')
INSERT INTO Child (parentID, mydate) VALUES (2,'2010-10-14')
INSERT INTO Child (parentID, mydate) VALUES (3,'2010-10-14')
INSERT INTO Child (parentID, mydate) VALUES (3,'2010-10-15')
INSERT INTO Child (parentID, mydate) VALUES (3,'2010-10-16')