首页 > 解决方案 > 是否有使用 SQL 查询语句从物理列创建逻辑列的最佳方法?

问题描述

我正在使用表编写 SQL 查询。我的要求是我需要在一定条件下从一个物理列生成两个逻辑列。在 SQL 中如何在最终结果集中生成两个逻辑列?

到目前为止,我已经尝试使用子查询来派生这些逻辑列。但是,当将子查询合并为主查询中的列时,该子查询会返回错误。

总体而言,还有其他表将被连接SQL JOIN以派生相应的列。

列:

  1. CarrierName NVARCHAR(10)
  2. MonthDate DATETIME
  3. Stage INT

场景:
在我的 SQL Server 表中有一个名为Stagetype的列int,其中包含 1、2、3、4 之类的值。

现在,我有两个日期标准可应用于上述列,以在最终结果集中派生两个逻辑列。

标准#1:

从过去 12 个月和上个月结束日期之前获取运营商,并且“CurrentStage”的值应小于并派生“PriorStage”

例子:

当前月份是:2019 年 3 月(2019 年 3 月 25 日)或任何给定日期 过去最晚的月份结束日期是:2019 年 2 月 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

标签: sql-serversubquery

解决方案


推荐阅读