СЛЕДУЕТ ПРИСОЕДИНИТЬСЯ к той же таблице, удваивая строки - PullRequest
0 голосов
/ 19 декабря 2018

У меня есть две таблицы, к которым я пытаюсь присоединиться ВЛЕВО, но я не получаю ожидаемых результатов.

В комнатах есть несколько детей в разные дни, однако дети учитываются в комнате только после их запуска иесли у них есть часы, выделенные в этот день.Вывод, который я пытаюсь получить, таков:

Room  | MaxNum | Mon(Week1) | Tue(Week1) | Mon(Week2) | Tue(Week2)
Blue  | 5      | 4          | 4          | 3          | 2
Green | 10     | 10         | 10         | 9          | 9  
Red   | 15     | 15         | 15         | 15         | 15 

Вот схема и некоторые данные ...

create table Rooms(
  id       INT,
  RoomName VARCHAR(10),
  MaxNum   INT
);

create table Children (
  id          INT,
  RoomID      INT,
  MonHrs      INT,
  TueHrs      INT,
  StartDate   DATE
);

INSERT INTO Rooms VALUES (1, 'Blue', 5);
INSERT INTO Rooms VALUES (2, 'Green', 10);
INSERT INTO Rooms VALUES (3, 'Red', 15);

INSERT INTO Children VALUES (1, 1, 5, 0, '2018-12-02');
INSERT INTO Children VALUES (2, 1, 0, 5, '2018-12-02');
INSERT INTO Children VALUES (3, 1, 5, 5, '2018-12-09');
INSERT INTO Children VALUES (4, 1, 0, 5, '2018-12-09');
INSERT INTO Children VALUES (5, 2, 5, 0, '2018-12-09');
INSERT INTO Children VALUES (6, 2, 0, 5, '2018-12-09');

У меня возникла проблема с SQL.Это может быть неправильный подход.

SELECT R.RoomName, R.MaxNum,
       R.MaxNum - SUM(CASE WHEN C1.MonHrs > 0 THEN 1 ELSE 0 END) AS Mon1,
       R.MaxNum - SUM(CASE WHEN C1.TueHrs > 0 THEN 1 ELSE 0 END) AS Tue1,
       R.MaxNum - SUM(CASE WHEN C2.MonHrs > 0 THEN 1 ELSE 0 END) AS Mon2,
       R.MaxNum - SUM(CASE WHEN C2.TueHrs > 0 THEN 1 ELSE 0 END) AS Tue2
  FROM Rooms R
        LEFT JOIN Children C1 
          ON R.id = C1.RoomID
         AND C1.StartDate <= '2018-12-02'     
        LEFT JOIN Children C2
          ON R.id = C2.RoomID
         AND C2.StartDate <= '2018-12-09'
 GROUP BY R.RoomName;         

MySQL output

На строках в левом соединении происходит удвоение, которое приводит к подсчетудалеко, и я не знаю, как их предотвратить.Вы можете увидеть эффект, если заменить SELECT на *

SELECT *

Любые предложения очень помогут.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Вам необходимо использовать one LEFT JOIN и переместить фильтр дат из условия JOIN в агрегат:

SELECT R.id, R.RoomName, R.MaxNum
    , R.MaxNum - COUNT(CASE WHEN C.StartDate <= '2018-12-02' AND C.MonHrs > 0 THEN 1 END) AS Mon1
    , R.MaxNum - COUNT(CASE WHEN C.StartDate <= '2018-12-02' AND C.TueHrs > 0 THEN 1 END) AS Tue1
    , R.MaxNum - COUNT(CASE WHEN C.StartDate <= '2018-12-09' AND C.MonHrs > 0 THEN 1 END) AS Mon2
    , R.MaxNum - COUNT(CASE WHEN C.StartDate <= '2018-12-09' AND C.TueHrs > 0 THEN 1 END) AS Tue2
FROM Rooms R
LEFT JOIN Children C ON R.id = C.RoomID
GROUP BY R.id, R.RoomName, R.MaxNum
0 голосов
/ 19 декабря 2018

Проблема такого рода обычно возникает из-за выполнения агрегации в слишком широкой точке в запросе, что приводит к двойному счету записей.Попробуйте агрегировать таблицу Children в отдельном подзапросе:

SELECT
    R.RoomName,
    R.MaxNum,
    R.MaxNum - C.Mon1 AS Mon1,
    R.MaxNum - C.Tue1 AS Tue1,
    R.MaxNum - C.Mon2 AS Mon2,
    R.MaxNum - C.Tue2 AS Tue2
FROM Rooms R
LEFT JOIN
(
    SELECT
        RoomID,
        COUNT(CASE WHEN MonHrs > 0 AND StartDate <= '2018-12-02'
                   THEN 1 END) AS Mon1,
        COUNT(CASE WHEN TueHrs > 0 AND StartDate <= '2018-12-02'
                   THEN 1 END) AS Tue1,
        COUNT(CASE WHEN MonHrs > 0 AND StartDate <= '2018-12-09'
                   THEN 1 END) AS Mon2,
        COUNT(CASE WHEN TueHrs > 0 AND StartDate <= '2018-12-09'
                   THEN 1 END) AS Tue2
    FROM Children
    GROUP BY RoomID
) C
    ON R.id = C.RoomID;

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

Позднее редактирование: вам, вероятно, вообще не нужен подзапрос, см. Ответ @Salman.Но любой из наших ответов должен решить проблему двойного счета.

...