SQL子关系查询帮助

时间:2010-11-06 20:26:53

标签: sql database

我有一对多关系看起来像这样:

| Parent |  | Child  |
|   id   |  |   id   |
|        |  |parentID|
|        |  |  date  |

我正在尝试构建一个查询,以便我得到所有拥有子记录的父母,其中所有记录都在指定日期之前有一个日期。

像这样的东西

SELECT * FROM parent
JOIN child on child.parentid = parent.id
WHERE child.date <= '10/13/2010'

但问题是我得到的父母在指定的日期之前有孩子的日期,并且在指定的日期之后有一个日期的子记录,当我只想要在给定日期之前有日期的孩子的父母。

有没有人对如何处理此案有一些建议?

谢谢!

3 个答案:

答案 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)

我彻底阅读了你的问题并总结如下:

  • 子行可能存在于日期X之前,之后或之后
  • 我希望所有孩子的父母都在Date X
  • 之前/之前约会

见下面的代码。我们使用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')