Я пишу SQL-запрос, используя таблицу. Мое требование - мне нужно создать два логических столбца из одного физического столбца с определенными условиями. В SQL, как сгенерировать два логических столбца в окончательном наборе результатов?
До сих пор я пытался использовать подзапросы для получения этих логических столбцов. Но этот подзапрос возвращает ошибку при включении его в качестве столбца в основной запрос.
В целом есть другие таблицы, которые будут объединены с использованием SQL JOIN
для получения соответствующих столбцов.
Колонки:
CarrierName NVARCHAR(10)
MonthDate DATETIME
Stage INT
Сценарий:
В моей таблице SQL Server есть столбец с именем Stage
типа int
, который содержит значения, такие как 1, 2, 3, 4.
Теперь у меня есть два критерия даты, которые нужно применить к столбцу выше, чтобы получить два логических столбца в окончательном наборе результатов.
Критерии № 1:
Получите носителей с прошлых 12 месяцев и априорных значений до даты окончания прошлого месяца, и значение «CurrentStage» должно быть меньше, чем и получить «PriorStage»
Пример:
Текущий месяц: март 2019 (2019-03-25) или любая другая дата
Последняя дата окончания последнего месяца будет: 2019-02-28
12 месяцев до предыдущего прошлого месяца будет:
С 2018-02-01 по 2019-01-31
Критерии № 2:
Получите носителей с даты последнего последнего месяца и получите "CurrentStage"
При написании двух независимых операторов SQL SELECT я получаю желаемые результаты.
Моя проблема заключается в том, когда я думаю, что они объединяются в одном утверждении выбора.
Я получаю эту ошибку:
Подзапрос вернул более 1 значения. Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения
Код:
DECLARE @DATE DATETIME
SET @DATE = '2018-08-25';
--QUERY 1 - RECORDS WITH PREVIOUS MONTH END DATE
SELECT
T1.CarrierName AS 'Carrier_Number',
T1.Stage AS 'Monitoring_Stage–Current'
FROM
table1 T1
WHERE
T1.Stage IS NOT NULL AND
CONVERT(DATE, T1.MonthDate) = CONVERT(DATE, DATEADD(D, -(DAY(@DATE)), @DATE))
--QUERY 2 - RECORDS FROM PAST 12 MONTHS PRIOR PREVIOUS MONTH END DATE
SELECT
T2.CarrierName,
T2.Stage AS 'Monitoring_Stage–Prior'
FROM
table2 T2
WHERE
T2.Stage IS NOT NULL AND
CONVERT(DATE, T2.MonthDate) BETWEEN CONVERT(DATE, DATEADD(M, -12, DATEADD(D, -(DAY(@DATE)), @DATE)))
AND CONVERT(DATE, DATEADD(D, -(DAY(@DATE) + (DAY(DATEADD(D, -(DAY(@DATE)), @DATE)))), @DATE))
AND T2.Stage) > (SELECT DISTINCT MAX(m.Stage AS INT))
FROM table1 m
WHERE CONVERT(DATE, m.MonthDate) = CONVERT(DATE, DATEADD(D, -(DAY(@DATE)), @DATE))
AND T2.CarrierName = m.CarrierName)
Мой окончательный ожидаемый набор результатов должен содержать столбцы ниже.
Где значение CurrentStage
меньше значения PriorStage
.
Ожидаемые результаты
CarrierName | CurrentStage | PriorStage
--------------+--------------+-------------
C11122 | 1 | 2
C32233 | 3 | 4
Фактический результат
Я ищу альтернативы. То есть CTE, Union, временная таблица и т. Д.
Что-то вроде:
SELECT
CarrierName,
Query 1 Result As 'CurrentStage',
Query 2 Result As 'PrioreStage'
FROM
table1
Чтобы улучшить этот пост, я добавляю свой ответ сюда. Мое решение ниже по этому опубликованному вопросу все еще находится в стадии оценки, поэтому я не публикую его в качестве окончательного ответа. Но это действительно пролило свет на мои усилия.
Решение:
SELECT
DISTINCT M.CarrierName, A.[CurrentStage], B.[PriorStage]
FROM
--QUERY 1 - RECORDS WITH CURRENT MONTH END DATE
(SELECT M.CarrierName, M.CarrierID
, Stage AS 'CurrentStage'
FROM table1 M
WHERE M.Stage IS NOT NULL AND
CONVERT(date, M.MonthDate) = CONVERT(date, DATEADD(D,-(DAY(@DATE)), @DATE))
)
A **inner join**
(
--QUERY 2 - RECORDS FROM PAST 12 MONTHS PRIOR CURRENT MONTH END DATE
SELECT M2.CarrierName, M2.CarrierID
, Stage AS 'PriorStage'
FROM table1 M2
WHERE M2.Stage IS NOT NULL AND
CONVERT(date, M2.MonthDate) BETWEEN CONVERT(date, DATEADD(M, -12, DATEADD(D,-(DAY(@DATE)), @DATE)))
AND CONVERT(date, DATEADD(D,-(DAY(@DATE)+(DAY(DATEADD(D,-(DAY(@DATE)), @DATE)))), @DATE))
AND M2.Stage > (SELECT DISTINCT max(m.Stage)
FROM table1 m
WHERE CONVERT(date, m.MonthDate) = CONVERT(date, DATEADD(D,-(DAY(@DATE)), @DATE)) AND
M2.CarrierName = m.CarrierName
)
) B on b.Carrier_Number = a.Carrier_Number
INNER JOIN table1 M ON A.CarrierID = M.CarrierID AND B.CarrierID = M.CarrierID