同一列上的多个子查询

时间:2016-01-26 15:19:15

标签: sql sql-server

我试图使用不同的标准从一张桌子中撤回多个不同的总和。唯一的问题是我的子查询拉回了多个响应,所以我稍微改变了我的查询,然后极度失败,试图找到最好的方法来做到这一点。

以下是我正在使用的查询:

   SELECT TER_ID AS TER_ID,
   SUM(MED_AMT) AS NET_SLS_AMT,
   SUM(SELECT MED_AMT
       FROM DAY_TER_MEDIA
       WHERE TND_CD = 1 AND
       DAY_TER_MEDIA.DT = '') AS CASH_AMT,
   SUM(SELECT MED_AMT
       FROM DAY_TER_MEDIA
       WHERE DAY_TER_MEDIA.TND_CD IN(4,5,16,18,23,31) AND
       DAY_TER_MEDIA.DT = '') AS ELEC_AMT,
   SUM(SELECT MED_AMT
       FROM DAY_TER_MEDIA
       WHERE DAY_TER_MEDIA.TND_CD IN(2,3,8,9,10,11,15,20,52) AND
       DAY_TER_MEDIA.DT = '') AS OTHER_AMT
   FROM DAY_TER_MEDIA
   WHERE DT = ''
   GROUP BY TER_ID;

如您所见,我的目的是从同一列中撤回NET_SLS_AMT,CASH_AMT,ELEC_AMT和OTHER_AMT,并仅对具有特定TND_CD,DT和TER_ID的那些进行求和。正如我所说,我已多次更改此查询,并且我知道它的当前迭代实际上并不是我需要的。关于如何执行此操作我仍有点迷失,同时仍按日期和TER_ID对它们进行分组。有任何想法吗?或者甚至有一个干净的方法来做到这一点?

3 个答案:

答案 0 :(得分:1)

使用案例陈述而不是选择

SELECT TER_ID AS TER_ID,
        SUM(MED_AMT) AS NET_SLS_AMT,
        SUM(CASE WHEN TND_CD = 1 THEN MED_AMT
                 ELSE 0
            END) AS CASH_AMT,
        SUM(CASE WHEN DAY_TER_MEDIA.TND_CD IN (4,5,16,18,23,31) THEN MED_AMT
                 ELSE 0
            END) AS ELEC_AMT,
        SUM(CASE WHEN DAY_TER_MEDIA.TND_CD IN (2,3,8,9,10,11,15,20,52) THEN MED_AMT
                 ELSE 0
            END) AS OTHER_AMT
 FROM   DAY_TER_MEDIA
 WHERE  DT = ''
 GROUP BY TER_ID;

答案 1 :(得分:1)

您未获得预期结果的原因是您的子查询与FROM中的表之间没有关系。您需要在每个子查询WHERE子句中添加该关系(称为相关子查询,因为它使用子查询中外部查询的值):

SELECT TER_ID AS TER_ID,
SUM(MED_AMT) AS NET_SLS_AMT,
SUM(SELECT MED_AMT
   FROM DAY_TER_MEDIA
   WHERE TND_CD = 1 AND TER_ID = t1.TER_ID AND
   DAY_TER_MEDIA.DT = '') AS CASH_AMT,
SUM(SELECT MED_AMT
   FROM DAY_TER_MEDIA
   WHERE DAY_TER_MEDIA.TND_CD IN(4,5,16,18,23,31) AND TER_ID = t1.TER_ID AND
   DAY_TER_MEDIA.DT = '') AS ELEC_AMT,
SUM(SELECT MED_AMT
   FROM DAY_TER_MEDIA
   WHERE DAY_TER_MEDIA.TND_CD IN(2,3,8,9,10,11,15,20,52) AND TER_ID = t1.TER_ID AND
   DAY_TER_MEDIA.DT = '') AS OTHER_AMT
FROM DAY_TER_MEDIA t1
WHERE DT = ''
GROUP BY TER_ID;

但这是一种非常低效的方法。相反,使用没有任何子查询的CASE语句:

SELECT 
    TER_ID,
    SUM(CASE WHEN TND_CD = 1 THEN MED_AMT ELSE 0 END) as CASH_AMT,
    SUM(CASE WHEN TND_CD IN(4,5,16,18,23,31) THEN MED_AMT ELSE 0 END) as ELEC_AMT,
    SUM(CASE WHEN TND_CD IN(2,3,8,9,10,11,15,20,52) THEN MED_AMT ELSE 0 END) AS OTHER_AMT
FROM DAY_TER_MEDIA
WHERE DT= ''
GROUP BY TER_ID

答案 2 :(得分:0)

一种方法是使用CASE expression返回条件总计。我的示例使用以下示例数据:

示例数据

/* Using table variables makes sharing sample data easy.
 */
DECLARE @Example TABLE
    (
        [Type]  INT,
        AMT     MONEY
    )
;

INSERT INTO @Example
    (
        [Type],
        AMT
    )
VALUES
    (1, 10),
    (1, 15),
    (1, 45),
    (2, 30),
    (2, 20)
;

在示例中,每列有条件地包含 AMT 或0,基于 Type SUM函数汇总结果。

示例

/* Removing the SUM functions would highlight how this technique works.
 */
SELECT
    SUM(CASE WHEN [Type] = 1 THEN AMT ELSE 0 END) AS AMT_1,
    SUM(CASE WHEN [Type] = 2 THEN AMT ELSE 0 END) AS AMT_2
FROM
    @Example
;