Вычисление таблицы населения из таблицы рождения/смерти

87
8

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

person | born | died
1 | 2001 | 9999
2 | 2002 | 2003
3 | 2002 | 2008
4 | 2004 | 2009
5 | 2005 | 9999
6 | 2010 | 2012

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

year | population
2001 | 1 (1)
2002 | 3 (1,2,3)
2003 | 2 (1,3)
2004 | 3 (1,3,4)
2005 | 4 (1,3,4,5)
2006 | 4 (1,3,4,5)
2007 | 4 (1,3,4,5)
2008 | 3 (1,4,5)
2009 | 2 (1,5)
2010 | 3 (1,5,6)
2011 | 3 (1,5,6)
2012 | 2 (1,5)

Я могу получить эту запись программы на С# и прокручивать каждую из строк в исходной таблице и увеличивать количество посещений каждого года, летящего между годами рождения и смерти. Однако мне нужно сделать это полностью в TSQL-скрипте. Я новичок в TSQL. Как мне это сделать? Если подобная проблема уже обсуждалась, укажите мне ее. Спасибо.

спросил(а) 2021-01-19T10:39:37+03:00 2 месяца, 3 недели назад
1
Решение
62

DECLARE @t TABLE(person INT, born INT, died INT);

INSERT @t VALUES
(1,2001,9999),
(2,2002,2003),
(3,2002,2008),
(4,2004,2009),
(5,2005,9999),
(6,2010,2012);

DECLARE @start INT, @end INT;

SELECT @start = 2001, @end = 2012;

;WITH n(y) AS
(
SELECT TOP (@end - @start + 1)
@start - 1 + ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects
)
SELECT
[year] = n.y,
population = SUM(CASE WHEN n.y >= t.born AND n.y < t.died THEN 1 ELSE 0 END)
FROM n CROSS JOIN @t AS t GROUP BY n.y;

Результаты:

year    population
---- ----
2001 1
2002 3
2003 2
2004 3
2005 4
2006 4
2007 4
2008 3
2009 2
2010 3
2011 3
2012 2

FWIW Я только что начал серию блога по этому поводу:

http://www.sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

ответил(а) 2021-01-19T10:39:37+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема