Подзапрос SQL с объединением трех таблиц - PullRequest
0 голосов
/ 09 октября 2019

Мне нужно запросить по 3 таблицам. Вот примеры:

Студенты стол:

 StudentId     Name
 --------------------
    1           Aaa
    2           Bbb
    3           Ccc

ClassStudent стол

 ClassId       StudentId
 -----------------------
    1             1
    1             2
    2             3

Оплата таблица:

PaymentTime   ClassId
---------------------
08.10.2019       1
08.10.2019       2
08.09.2019       1
08.09.2019       2
08.08.2019       1
08.07.2019       1
08.06.2019       1

Мне нужно вот так: из таблицы Payment мне нужно количество тех, чей PaymentTime больше, чем 08.09.2019.

Как мне это сделать

SELECT ClassStudent.ClassId, COUNT(ClassStudnet.ClassId) AS StudentCount
FROM ClassStudent CS
INNER JOIN PaymentTable PT ON PT.ClassId = CS.ClassId 
AND WHERE PT.PaymentTime > CONVERT(date,'08.09.2019')
GROUP BY CS.ClassId

Как найти количество запросов для Class в таблице Payment?

Я хочу количестволюди платят до и после "08.09.2019" отдельно.

Как:

ClassId TotalStudent PaymentBefore08.09.2019 PaymentAfter08.09.2019
--------------------------------------------------------------------
 1            10                3                       7  
 2            15                4                      11

Ответы [ 3 ]

0 голосов
/ 10 октября 2019
    SELECT 
COUNT(CASE WHEN PT.PaymentTime > CONVERT(date, '08.09.2019') THEN COUNT(PT.PaymentTime) END) AS 'AfterTotalCount08.09.2019',
COUNT(CASE WHEN PT.PaymentTime < CONVERT(date, '08.09.2019') THEN COUNT(PT.PaymentTime) END) AS 'BeforeTotalCount08.09.2019'
    FROM PaymentTable PT

Я хочу, чтобы это понравилось

0 голосов
/ 11 октября 2019

Схема прилагается в конце для тех, кто хочет поиграть.

Запрос

select cs.ClassID, TotalStudent=count(s.StudentID),[PaymentBefore08.09.2019]=count(pB.StudentID), [PaymentAfter08.09.2019]=count(pA.StudentID)
     from ClassStudent cs
     inner join Students s on cs.StudentID = s.StudentID
     left join Payment pA on s.StudentID = pA.StudentID and datediff(day, pA.PaymentTime, '2019-08-09') < 0
     left join Payment pB on s.StudentID = pB.StudentID and datediff(day, pB.PaymentTime, '2019-08-09') >= 0
group by cs.ClassID

Выход

enter image description here

Объяснение

Сначала выбирается таблица ClassStudent для получения списка всех классов.

Во-вторых, таблица «Студенты» объединяется для получения общего числа студентов в классе.

В-третьих, в таблицу «Платежи» было сделано два соединения. Один, чтобы получить платежи, сделанные до 08.09.2019, а другой, чтобы получить платеж, сделанный позже.

Наконец, запрос сгруппирован по ClassID, потому что нам нужно отображать его без агрегирования.

Схема

CREATE TABLE Students 
    ([StudentID] int, [Name] varchar(57));

CREATE TABLE ClassStudent 
    ([StudentID] int, [ClassID] int);


CREATE TABLE Payment 
    ([StudentID] int,[PaymentTime] datetime);


INSERT INTO Students values (1, 'Aaa');
INSERT INTO Students values (2, 'Bbb');
INSERT INTO Students values (3, 'Ccc');
INSERT INTO Students values (4, 'Ddd');
INSERT INTO Students values (5, 'Eee');
INSERT INTO Students values (6, 'Fff');
INSERT INTO Students values (7, 'Ggg');
INSERT INTO Students values (8, 'Hhh');
INSERT INTO Students values (9, 'Iii');

INSERT INTO ClassStudent values (1, 1);
INSERT INTO ClassStudent values (2, 2);
INSERT INTO ClassStudent values (3, 3)
INSERT INTO ClassStudent values (4, 1);
INSERT INTO ClassStudent values (5, 2);
INSERT INTO ClassStudent values (6, 3)
INSERT INTO ClassStudent values (7, 1);
INSERT INTO ClassStudent values (8, 2);
INSERT INTO ClassStudent values (9, 3);


INSERT INTO Payment values (1, '2019-08-10');
INSERT INTO Payment values (2, '2019-08-10');
INSERT INTO Payment values (3, '2019-08-09')
INSERT INTO Payment values (4, '2019-08-09');
INSERT INTO Payment values (5, '2019-08-08');
INSERT INTO Payment values (6, '2019-08-07')
INSERT INTO Payment values (7, '2019-08-06');
INSERT INTO Payment values (8, '2019-08-09');
INSERT INTO Payment values (9, '2019-08-09')
0 голосов
/ 09 октября 2019

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

SELECT PT.ClassId, COUNT(*) AS PaymentCount
FROM PaymentTable PT
WHERE PT.PaymentTime > CONVERT(date, '08.09.2019')
GROUP BY PT.ClassId

Но это не учитывает студентов. Он считает платежи (следовательно, PaymentCount вместо StudentCount). Если один ученик может сделать 2 платежа за 1 класс, это будет считаться как 2 в приведенном выше запросе. Для фактического подсчета студентов вам понадобится прямая связь между платежом и студентом, которого нет в таблицах, которые вы представили.

Исправленный ответ на основе ваших комментариев:

SELECT T1.ClassID, T1.TotalStudents,
   isnull(T2.PaymentCountAfter, 0) PaymentCountAfter,
   isnull(T2.PaymentCountBeforeEqual, 0) PaymentCountBeforeEqual
FROM (
   SELECT CS.ClassId, COUNT(*) TotalStudents
   FROM ClassStudent CS
   GROUP BY CS.ClassId
) T1
LEFT OUTER JOIN (
   SELECT PT.ClassId,
      COUNT(CASE WHEN PT.PaymentTime > CONVERT(date, '08.09.2019') THEN 1) AS PaymentCountAfter,
      COUNT(CASE WHEN PT.PaymentTime <= CONVERT(date, '08.09.2019') THEN 1) AS PaymentCountBeforeEqual
   FROM PaymentTable PT
   GROUP BY PT.ClassId
) T2 on T2.ClassId  = T1.ClassId

Возможно, это можно сделать с помощью функций Windows, а не присоединять их к подзапросам.

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