在不使用案例时如何对值进行求和

时间:2017-12-28 11:20:44

标签: sql sql-server database

我需要调整查询以使其运行得更快。目前,我正在使用案例何时总结值我们如何调整它以解决性能问题

  

注意表包含120列,包含1000万条记录。

当前查询为

select week ,nullif(Sum(Convert(Numeric(18,2),Amt)),0) [Amt] , 
nullif((case when (Desc<>'FF')then Sum(Convert(Numeric(18,2),Amt)) else 0 end ),0) [Amt2] 
from Table1 group by Week,Desc

表1:

╔════════╦═══════╦════════╗
║  Week  ║ Desc  ║  Amt   ║
╠════════╬═══════╬════════╬
║      1 ║  FF   ║  25.00 ║
║      1 ║  ss   ║  55.00 ║
║      2 ║  ss   ║  78.00 ║
║      2 ║  FF   ║  99.00 ║
║      3 ║  ss   ║  54.00 ║
║      4 ║  FF   ║  58.00 ║
║      5 ║  FF   ║  55.00 ║ 
║      5 ║  ss   ║  55.00 ║ 
║      1 ║  ss   ║  77.00 ║
╚════════╩═══════╩════════╝


CREATE TABLE [dbo].[Table] ([Client_Billing_Id] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
                            [Weekday] [varchar](10) NULL,
                            [Description] [varchar](1500) NULL,
                            [NetAmount] [varchar](100) NULL )

CREATE NONCLUSTERED INDEX [Description] ON [dbo].[Table] ( [Description] ASC )
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

1 个答案:

答案 0 :(得分:0)

问题在于您的专栏NetAmount。您将数值存储为字符串,因此SQL服务器可能会对值进行求和。

此外,您在列Weekday上没有索引,这意味着服务器可以扫描整个表,然后才能对任何内容进行分组。

接下来,您的专栏Description。为什么它是varchar(1500)?从您发布的明确仅存储2个字符,那么其他1498个字符的含义是什么?

我会做以下

  1. 根据您的查询将NetAmount列更改为decimal(可能为(18,2)。)
  2. Description列更改为char(2),因为您只使用2个字符。其他1498个字符的空间是完全浪费
  3. 将工作日更改为int。它显然不是varchar,这意味着订购是正确的。工作日不应该是1, 10, 12, 13...19, 2, 20, 21,...3, 30, 31, 4, 5, 6, 7...
  4. 的顺序
  5. [Weekday][Description]以及INCLUDENetAmount上添加索引。
  6. 这导致类似:

    ALTER TABLE dbo.[Table] ALTER COLUMN NetAmount decimal(18,2);
    ALTER TABLE dbo.[Table] ALTER COLUMN [Description] char(2);
    ALTER TABLE dbo.[Table] ALTER COLUMN [Weekday] int;
    CREATE INDEX Week_Desc_IX ON dbo.[Table] ([Weekday] ASC, [Description] ASC) INCLUDE ([NetAmount]);
    

    然后,您的查询将变为:

    SELECT [WeekDay],
           CASE [Description] WHEN 'FF' THEN [Description] ELSE 'SS' END AS [Description],
           NULLIF(SUM(NetAmount),0) AS [Amt],
           NULLIF(SUM(CASE [Description] WHEN 'FF' THEN Amt END),0) AS [Amt2] 
    FROM [Table]
    GROUP BY [Weekday],
             CASE [Description] WHEN 'FF' THEN [Description] ELSE 'SS' END;
    

    应该表现得更好。