我对SQL很新,并且面临以下两难困境。我有以下部分表:
Account Description ShortDescription Balance ------------------------------------------------ 100001 Blah, blah Blah, blah 28350.68 100020 " " 2537.35 111000 " " 86898.12 111001 " " 63943.63 121000 " " 55325.68 121012 " " 65264.35 122000 " " 94898.85
我需要以前两位数字开头的所有账户余额。所以前两个余额总和,接下来两个求和,接下来三个求和等等。然后我需要拿这些总和并创造一个总计。
结束表将包含所有列,SubTotal和GrandTotal。我无法找到一个好方法来做到这一点;我尝试了OVER - PARTITION BY但没有成功(SELECT SUM(Balance)OVER(PARTITION BY Account)AS SubTotal)。任何帮助,将不胜感激。提前谢谢。
答案 0 :(得分:2)
这是输出包含总计和小计的表的一种方法:
-- select individual Rows
select Account, Description, ShortDescription, Balance from Accounts
union
-- subtotals
select
substring(Account, 1, 2) as Account,
substring(Account, 1, 2) + ' Subtotal' as Description,
'' as ShortDescription,
sum(Balance) as Balance
from Accounts
group by substring(Account, 1, 2)
union
-- grand total
select
'' as Account,
'Grand Total' as Description,
'' as ShortDescription,
sum(Balance) as Balance
from Accounts
-- order all records to give the illusion of interlaced subtotals/grand total
order by Account desc
但是,我认为最佳解决方案是从表中进行简单选择,并使用报告工具(如SQL Server Reporting Services)处理总数/小计。
请注意,在上述声明中我假设Account
列的类型为char
/ varchar
。如果它被声明为int
或其他数字类型,则应添加适当的强制转换/转换变换。 (union
中的所有数据集必须具有相同数量的列和相同的数据类型)
答案 1 :(得分:0)
我认为最初的问题是正确编写分区有点困难,因为语法有点痛苦。如果我找不到您要查找的内容(各行中的所有值和总数),作为w0lf提供的简单替代方法,这可能是一个更快的解决方案:
Select *, SUM(Balance) OVER (PARTITION BY substring(Account, 1, 2)) as Subtotal,
Sum(Balance) over(Partition by 1) as Total
from dbo.Accounts
除了小计列外,还使用分区上的和来为每个原始列(*)和总列提供。
我使用了以下结构和您的数据,如果您收到任何错误,这可能会有所帮助:
CREATE TABLE dbo.Accounts (Account varchar(10), [Description] varchar(10),
ShortDescription varchar(10), Balance money) GO
INSERT INTO Accounts (Account, Description, ShortDescription, Balance) VALUES
(100001, 'Blah', 'Blah2', 28350.68),(100020, 'Blah', 'Blah2', 2537.35),
(111000, 'Blah', 'Blah2', 86898.12),(111001, 'Blah', 'Blah2', 63943.63),
(121000, 'Blah', 'Blah2', 55325.68),(121012, 'Blah', 'Blah2', 65264.35),
(122000, 'Blah', 'Blah2', 94898.85)
作为附录,如果帐户存储为数字,则可以使用substring(cast(Account as varchar(max)),1,2)而不是substring(Account,1,2)。