如何在同一查询中引用另一列中的聚合列?

时间:2013-07-10 12:39:51

标签: sql-server-2008 tsql subquery aggregate-functions

我有一个看起来或多或少像这样的查询:

INSERT INTO #results
SELECT Name, 
        (SELECT 
            SUM(CAST(Amount AS BIGINT)) 
         FROM Items 
         WHERE RemittingMember = a.Number 
            and RecordId = 50), 
        (SELECT SUM(CAST(Std_Amount AS BIGINT)) 
         FROM Items 
         WHERE RemittingMember = a.Number 
            AND RecordId = 10)
FROM Member a

其中Amount是一种货币(存储为varchar,没有小数),RemittingMemberItems表和Member表之间的链接,RecordId 1}表示该行的项目类型。在这种情况下,50是借方,10是贷方。

我需要从第二列中减去第一列,并在第三列中包含该值。我知道我可以这样做:

INSERT INTO #results
SELECT Name, 
            (SELECT 
                SUM(CAST(Amount AS BIGINT)) 
             FROM Items 
             WHERE RemittingMember = a.Number 
                and RecordId = 50), 
            (SELECT SUM(CAST(Std_Amount AS BIGINT)) 
             FROM Items 
             WHERE RemittingMember = a.Number 
                AND RecordId = 10),
             (SELECT 
                SUM(CAST(Amount AS BIGINT)) 
             FROM Items 
             WHERE RemittingMember = a.Number 
                and RecordId = 50) - (SELECT SUM(CAST(Std_Amount AS BIGINT)) 
             FROM Items 
             WHERE RemittingMember = a.Number 
                AND RecordId = 10)    
FROM Member a

但如果需要做出改变,这很难阅读,也很难改变。我也知道我可以用局部变量做到这一点,但这是一个报告a.Number将改变,这将涉及我想避免的迭代。

我还需要检查第三列的符号,将值放在第四列。

有没有一种聪明的方法来实现这个目标?

3 个答案:

答案 0 :(得分:1)

您可以使用outer apply声明:

INSERT INTO #results
SELECT Name, 
        s1.Value, 
        s2.Value,
        s2.Value - s1.Value,
        case
            when s2.Value > s1.Value then 1
            when s2.Value < s1.Value then -1
            else 0
        end
FROM Member a
    outer apply (SELECT 
            SUM(CAST(Amount AS BIGINT)) Value
         FROM Items 
         WHERE RemittingMember = a.Number 
            and RecordId = 50) s1
    outer apply (SELECT 
            SUM(CAST(Std_Amount AS BIGINT)) Value
         FROM Items 
         WHERE RemittingMember = a.Number 
            and RecordId = 10) s2

答案 1 :(得分:1)

您可以使用CTE,如下所示:

;WITH intermediate_results (name, debit, credit)
AS (
SELECT
    Name
    AS name, 

    (SELECT 
        SUM(CAST(Amount AS BIGINT)) 
     FROM Items 
     WHERE RemittingMember = a.Number 
        and RecordId = 50)
    AS debit, 

    (SELECT SUM(CAST(Std_Amount AS BIGINT)) 
     FROM Items 
     WHERE RemittingMember = a.Number 
        AND RecordId = 10)
    AS credit

FROM Member a
)

INSERT INTO #results
SELECT name, debit, credit, debit - credit, SIGN(debit - credit)
  FROM intermediate_results

答案 2 :(得分:0)

您应该能够更简化查询以删除项目表上的其他联接。这样的事情应该有效。 需要使用您的数据进行测试

SELECT
    name, 
    debit, 
    credit, 
    Amount = debit - credit, 
    [SIGN] = SIGN(debit - credit)
FROM Member a
inner join(
     SELECT 
        RemittingMember,
        debit=SUM(CASE WHEN RecordId = 50 THEN CAST(Amount AS BIGINT) ELSE 0 END),
        credit=SUM(CASE WHEN RecordId = 10 THEN CAST(Std_Amount AS BIGINT) ELSE 0 END)
     FROM Items 
     WHERE RecordId IN(10,50)
     GROUP BY
        RemittingMember
) as Amts
    on Amts.RemittingMember = a.Number