Справка по запросу SQL-отношений - PullRequest
0 голосов
/ 06 ноября 2010

У меня есть отношение один ко многим, которое выглядит так:

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

И я пытаюсь структурировать запрос так, чтобы я получал всех родителей, у которых есть записи о детях, у которых ВСЕ есть дата до указанной даты.

Как то так

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

Но проблема в том, что я получаю родителей, у которых есть дети с датой до указанной даты и есть записи о детях с датой после указанной даты, когда мне нужны ТОЛЬКО родители с датой до этой даты.

У кого-нибудь есть предложения по поводу этого дела?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 06 ноября 2010
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 голосов
/ 06 ноября 2010

Использование:

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, вероятно, равен, но без хлопот с правильной обработкой дублированных данных.

0 голосов
/ 06 ноября 2010

Я внимательно прочитал ваш вопрос и резюмировал ниже:

  • Дочерние строки могут существовать до, в или после даты 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)

(«дата» называется «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')

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...