SQL Pivot на основе значения между двумя столбцами - PullRequest
3 голосов
/ 24 июня 2009

У меня есть таблица, в которой, помимо прочего, есть два столбца, один для даты начала и другой для даты окончания. Мне нужно написать запрос, который будет возвращать столбец для каждого месяца года, и значение этого столбца равно 1, если месяц находится между 0 в противном случае. Кажется, что здесь я искал оператор PIVOT, но, насколько я могу судить, предложение PIVOT ищет совпадения, а не проверяет, находится ли значение между двумя другими. Является ли предложение PIVOT правильной конструкцией или мне нужно разбить и написать 12 операторов case, а затем агрегировать их?

Ответы [ 3 ]

2 голосов
/ 25 июня 2009

Я думаю, у меня есть решение здесь. Есть 3 основных шага:

  1. Получить дату в каждом из 12 месяцев
  2. Проверьте, находится ли эта дата между начальной и конечной датой
  3. PIVOT результат

Чтобы получить 12 дат, по одной на каждый месяц, я использовал небольшую рекурсивную инструкцию типа WITH для создания временной таблицы с 1 столбцом из 12 дат:

WITH months (date) AS (
SELECT GETDATE() AS date
UNION ALL
SELECT 
    DATEADD(MONTH,1,date)
FROM months
WHERE DATEDIFF(MONTH,GETDATE(),date) < 12)

Отсюда я могу ПЕРЕКРЕСТИТЬ эту временную таблицу с таблицей с информацией, которая мне действительно нужна. Затем я использую ГДЕ дату между началом и концом, чтобы отфильтровать записи, не относящиеся к этому месяцу. Вот как то так:

SELECT other.Title, MONTH(months.date) CROSS JOIN other
WHERE months.date BETWEEN other.start AND other.end

На этом шаге мы должны быть осторожны, чтобы ВЫБРАТЬ только те столбцы, которые мы хотим получить в результате, или те, которые будут агрегированы с помощью оператора PIVOT.

Наконец, мы должны повернуть результат:

PIVOT (MAX(PID) FOR date IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]))

Таким образом, результирующий запрос может выглядеть примерно так:

WITH months (date) AS (
SELECT GETDATE() AS date
UNION ALL
SELECT 
DATEADD(MONTH,1,date)
FROM months
WHERE DATEDIFF(MONTH,GETDATE(),date) < 12)
SELECT  Title,
    [1]     AS January,
    [2]     AS February,
    [3]     AS March,
    [4]     AS April,
    [5]     AS May,
    [6]     AS June,
    [7]     AS July,
    [8]     AS August,
    [9]     AS September,
    [10]    AS October,
    [11]    AS November,
    [12]    AS December
FROM
(
SELECT other.Title,MONTH(months.date)
CROSS JOIN other
WHERE months.date BETWEEN other.startDate AND other.endDate
) AS subquery
PIVOT (MAX(PID) FOR date IN
([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) AS p

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

0 голосов
/ 26 июля 2010

Почему бы не вычислить столбец для месяца, а затем использовать его для поворота?

DatePart (месяц, [дата])

или я неправильно понял проблему?

0 голосов
/ 24 июня 2009

Я бы пошел с 12 утверждениями о делах.

На самом деле это решение, которое я набросал, прежде чем вернуться и увидел, что вы упомянули в нем свой вопрос.

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