SQL объединить таблицу с 0 доступными значениями - PullRequest
0 голосов
/ 11 марта 2020

У меня проблемы с поиском правильных соединений, чтобы получить точный вывод из моей таблицы. Мой набор данных существует из разных таблиц:

Clienttable

+-----------+------------+------------+-------------+--------+
| Client_No | Start_Date |   End_Date | YearOfBirth |  City  |
+-----------+------------+------------+-------------+--------+
|     1     |  1-1-2018  |    null    |    1962     |    A   |
+-----------+------------+------------+-------------+--------+
|     2     |  10-4-2016 |    null    |    1987     |    B   |
+-----------+------------+------------+-------------+--------+
|     3     | 31-12-2015 |    null    |    1992     |    A   |
+-----------+------------+------------+-------------+--------+
|     4     |  1-4-2019  | 31-12-2019 |    2001     |    B   |
+-----------+------------+------------+-------------+--------+
|     5     |  1-1-2018  |    null    |    1999     |    A   |
+-----------+------------+------------+-------------+--------+

Таблица календарей

+-----------+
|   Date    |
+-----------+
| 1-1-2019  |
+-----------+
| 1-2-2019  |
+-----------+
| 1-3-2019  |
+-----------+
| 1-4-2019  |
+-----------+
| ........  |
+-----------+
| 1-12-2020 |
+-----------+

Таблица YearOfBirth

+--------+
|  Year  |
+--------+
|  1910  |
+--------+
|  1911  |
+--------+
|  ....  |
+--------+
|  2020  |
+--------+

Что я хочу это таблица с количеством людей, живущих в каждом городе, посчитанным YearOfBirth. Но я хочу, чтобы это считалось снова для каждой даты в моем календаре. Это также должно показать сумму, если это 0 для YearOfBirth. Запрос, который я получил до сих пор:

SELECT a.City, a.YearOfBirth, c.Date, 
       (SELECT COUNT(DISTINCT(b.ClientNo))
        FROM Client as b
        WHERE b.Start_Date < c.Date
        AND (b.End_Date > c.Date OR b.End_Date is null)
        AND a.City = b.City
        AND a.YearOfBirth = b.YearOfBirth) as Amount
FROM Client as a
FULL OUTER JOIN Calender as c
ON a.Start_Date <= c.Date
AND b.Start_Date >= c.Date
FULL OUTER JOIN YearOfBirth as d
ON a.YearOfBirth = d.YearOfBirth
GROUP BY a.City, a.YearOfBirth, c.Date

Запрос работает нормально, но я скучаю по всем годам, считая 0. Есть идеи, как это исправить?

Ожидаемый результат :

+------+----------+-------------+--------+
| City |   Date   | YearOfBirth | Amount |
+------+----------+-------------+--------+
|  A   | 1-1-2019 |    1910     |    0   |
+------+----------+-------------+--------+
|  A   | 1-1-2019 |    1911     |    0   |
+------+----------+-------------+--------+
|  A   | 1-1-2019 |    1912     |    0   |
+------+----------+-------------+--------+
|  A   | 1-1-2019 |    1962     |    1   |
+------+----------+-------------+--------+

Я не помещаю все записи, потому что я ожидаю, что для каждого города будет запись за дату с количеством людей, родившихся в конкретном c году, даже когда это 0.

1 Ответ

1 голос
/ 11 марта 2020

Я бы поступил следующим образом.

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

После этого мне просто нужно сравнить значения с записи в clienttable на основании того, совпадают ли город, year_of_birth и date с начальной и конечной датами, за которыми следует группировка.

Таким образом, в случае отсутствия Clientid они будут считаться нулевыми, что будет отображаться как 0

with data
  as (select c.city,a.year_of_birth,b.date
        from YearOfBirth a
        join calendar b
          on 1=1
        join (select distinct city
                from clienttable
             )c
          on 1=1 
      )
 select m.city 
       ,m.date
       ,m.year_of_birth
       ,count(clientid) as amount
   from data m
left join clienttable n
     on m.city=n.city
    and m.year_of_birth=n.year_of_birth
    and m.date between n.start_date and isnull(n.end_date,'3000-12-31')
group by m.city 
       ,m.date
       ,m.year_of_birth
...