如何识别已连接的表行已更改?

时间:2014-03-28 16:12:11

标签: sql sql-server

我有以下简化的表结构:

CREATE TABLE CustTrans
(
  CUSTACCOUNT VARCHAR(20),
  JOURNALID   BIGINT,
  VALUE       NUMERIC(28,12)
)
CREATE TABLE CustJour
(
  ID BIGINT
)

以下查询(也简化):

DECLARE @LastJourId BIGINT

SELECT ct.CUSTACCOUNT ,
       SUM(ct.VALUE + CASE WHEN @LastJourId != ct.JOURNALID THEN dbo.fnGetAdditionalCharges(ct.JOURNALID) ELSE 0 END)),
       @LastJourId = ct.JOURNALID
FROM CustTrans      AS ct
INNER JOIN CustJour AS cj ON cj.ID = ct.JOURNALID
GROUP BY ct.CUSTACCOUNT
ORDER BY ct.CUSTACCOUNT

这会显示错误消息:

A SELECT statement that assigns a value to a variable must not be combined with
data-retrieval operations.

函数fnGetAdditionalCharges计算适用于期刊的额外费用。因此,每个期刊应该运行一次。

有没有办法在一个查询中计算日记帐的交易金额和额外费用?

在上面的示例中,我尝试使用局部变量来解决它,并将其分配给期刊ID的最后一个值,这就是试图知道日记帐行已更改的方式。

有很多类似的问题。最好的解决方案是对查询进行小的改动。我知道解决方案使用2个具有不同分组的SELECT语句 - 首先是CUSTACCOUNT和JOURNALID),然后是CUSTACCOUNT,并在该步骤上添加fnGetAdditionalCharges值。

示例数据:

INSERT INTO CustJour ( ID ) VALUES (1);
INSERT INTO CustTrans ( CUSTACCOUNT, JOURNALID, VALUE ) VALUES ('1', 1, 1), ('1', 1, 1);

为简化起见,假设函数fnGetAdditionalCharges每次返回1。在SELECT语句中,您可以使用1

替换函数调用

在这种情况下,预期结果将是3. 2 - CustTran.VALUE的总和以及1对现有期刊的费用。

可以有很多期刊。每个期刊可能包含许多交易。

3 个答案:

答案 0 :(得分:1)

将查询分解为较小的部分并没有错;优化器会一直这样做,所以为什么我们不能呢?

如果我理解正确,你需要这样的东西:

with x as (
    SELECT 
        ct.CUSTACCOUNT, ct.JOURNALID,
        SUM(ct.VALUE) AS Value
    FROM 
        CustTrans AS ct
    INNER JOIN 
        CustJour AS cj ON cj.ID = ct.JOURNALID
    GROUP BY ct.CUSTACCOUNT, ct.JOURNALID
)
select CustAccount, sum(Value + dbo.fnGetAdditionalCharges(x.JOURNALID))
from x
GROUP BY 
    x.CUSTACCOUNT
ORDER BY 
    x.CUSTACCOUNT

当然没有经过测试。像其他人说的那样,请给我们一些样本数据来验证它。

答案 1 :(得分:0)

您的问题是SELECT语句可以创建结果集,也可以分配给变量,但不能同时分配两个变量。 我建议将其分成多个部分;首先将CUSTACCOUNT,VALUE和JOURNALID选择到临时表中,然后根据临时表中的NZID值评估@LastJourId,并从临时表中重新选择并结合@LastJourId来获取最终结果集。

答案 2 :(得分:0)

SELECT  CUSTACCOUNT, SUM(Value) + ISNULL(dbo.fnGetAdditionalCharges(journalid), 0) as Custaccvalue
FROM 
(    
     SELECT  distinct ct.CUSTACCOUNT, SUM(ct.VALUE) as Value, ct.JOURNALID as journalid
     FROM 
         CustTrans AS ct
     INNER JOIN 
              CustJour AS cj ON cj.ID = ct.JOURNALID
     GROUP BY 
             ct.CUSTACCOUNT, ct.JOURNALID
    ) a
GROUP BY 
    CUSTACCOUNT    
ORDER BY 
    CUSTACCOUNT

演示:http://sqlfiddle.com/#!3/d910d/14