SQL Server的复杂选择查询

时间:2015-08-12 04:24:00

标签: sql sql-server

我在SQL服务器中有一个临时表,如下所示

╔═══════╦═════════╦══════╦═════════╗
║Serial ║ Account ║ Due  ║ Balance ║
║1      ║ A1      ║ 1000 ║ 3100    ║
║2      ║ A1      ║ 1000 ║ 3100    ║
║3      ║ A1      ║ 1000 ║ 3100    ║
║4      ║ A1      ║ 1000 ║ 3100    ║
║1      ║ A2      ║ 100  ║ 3100    ║
║2      ║ A2      ║ 100  ║ 3100    ║    
║1      ║ B1      ║ 1000 ║ 1100    ║
║2      ║ B1      ║ 1000 ║ 1100    ║
║1      ║ B2      ║ 100  ║ 1100    ║
║2      ║ B2      ║ 100  ║ 1100    ║
╚═══════╩═════════╩══════╩═════════╝

我想确定要收集到期的行。 A1和A2到期将从3100收取,B1和B2将从1100收集。

首先,我使用了累积的Due,如下所示

╔═══════╔═════════╦══════╦════════════╦═════════╦
║Serial ║ Account ║ Due  ║ Cumulative ║ Balance ║
║1      ║ A1      ║ 1000 ║  1000      ║    3100 ║
║2      ║ A1      ║ 1000 ║  2000      ║    3100 ║
║3      ║ A1      ║ 1000 ║  3000      ║    3100 ║
║4      ║ A1      ║ 1000 ║  4000      ║    3100 ║
║1      ║ A2      ║ 100  ║   100      ║    3100 ║
║2      ║ A2      ║ 100  ║   200      ║    3100 ║
║1      ║ B1      ║ 1000 ║  1000      ║    1100 ║
║2      ║ B1      ║ 1000 ║  2000      ║    1100 ║
║1      ║ B2      ║ 100  ║   100      ║    1100 ║
║2      ║ B2      ║ 100  ║   200      ║    1100 ║
╚═══════╚═════════╩══════╩════════════╩═════════╝

现在我想选择以下行作为输出

╔═══════╔═════════╦══════╦════════════╦═════════╦
║Serial ║ Account ║ Due  ║ Cumulative ║ Balance ║  
║1      ║ A1      ║ 1000 ║  1000      ║    3100 ║
║2      ║ A1      ║ 1000 ║  2000      ║    3100 ║ 
║3      ║ A1      ║ 1000 ║  3000      ║    3100 ║  
║1      ║ A2      ║ 100  ║   100      ║    3100 ║
║1      ║ B1      ║ 1000 ║  1000      ║    1100 ║
║1      ║ B2      ║ 100  ║   100      ║    1100 ║
╚═══════╚═════════╩══════╩════════════╩═════════╩

这是我被困的地方。如何在不使用游标或循环的情况下选择这些行。所有我想用select语句和窗口函数来做这件事。 感谢。

可能的解决方案:如果表格可以更新如下,则问题将得到解决。

╔═══════╔═════════╦══════╦═══════════════════╦
║Serial ║ Account ║ Due  ║ Balance Remaining ║
║1      ║ A1      ║ 1000 ║  3100             ║
║2      ║ A1      ║ 1000 ║  2100             ║
║3      ║ A1      ║ 1000 ║  1100             ║
║4      ║ A1      ║ 1000 ║   100             ║
║1      ║ A2      ║ 100  ║   100             ║
║2      ║ A2      ║ 100  ║     0             ║
║1      ║ B1      ║ 1000 ║  1100             ║
║2      ║ B1      ║ 1000 ║   100             ║
║1      ║ B2      ║ 100  ║   100             ║
║2      ║ B2      ║ 100  ║     0             ║
╚═══════╚═════════╩══════╩═══════════════════╩

案例剩余余额等于/大于到期我们用差异更新它,否则它将保持原样。这里的问题是通过在A& A之间划分来更新行。乙

更新 我提供了与新数据集的链接,以更清楚地表达我的要求。 new dataset

2 个答案:

答案 0 :(得分:1)

非常简单

select * from account 
where (Balance-(Select sum(ac.Due) from account ac where 
ac.SerialNo<=account.SerialNo and  ac.Account =account.Account )>0)

更新

A1和A2之间没有任何关系,说平衡3100是在A1和A2之间共享而不是B1。

所以你必须指定a1和a2在同一组上的位置 有建议的选择  在表中添加组没有列,并为A1和A2赋予相同的no,对于B1和B2,其他相同的no。然后添加优先级列,指定A1应先扣除,然后如果剩余余额a2将获得机会

然后查询

    SELECT          *
    FROM            account
    WHERE
        ( Balance - ( SELECT
                        SUM(ac.Due)
                      FROM
                        account ac
                      WHERE
                        ( ac.GroupNo = account.GroupNo
                          AND ( ( ac.Account = account.Account
                                  AND ( ac.SerialNo <= account.SerialNo )
                                )
                                OR ac.Prioirty < account.Prioirty
                              )
                        )
                    ) > 0 )

答案 1 :(得分:0)

要获得此输出,您可以使用如下的简单查询:

╔═══════╔═════════╦══════╦════════════╦═════════╦
║Serial ║ Account ║ Due  ║ Cumulative ║ Balance ║  
║1      ║ A1      ║ 1000 ║  1000      ║    3100 ║
║2      ║ A1      ║ 1000 ║  2000      ║    3100 ║ 
║3      ║ A1      ║ 1000 ║  3000      ║    3100 ║  
║1      ║ A2      ║ 100  ║   100      ║    3100 ║
║1      ║ B1      ║ 1000 ║  1000      ║    1100 ║
║1      ║ B2      ║ 100  ║   100      ║    1100 ║
╚═══════╚═════════╩══════╩════════════╩═════════╩

select Serial,Account,Due,Cumulative,Balance from
(Select *, row_number() over(Partition by Account, order by serial number desc) as r from Temp) t
where t.r>1