简体   繁体   中英

Without using case when how to sum the values

I need to tune up the query to make it run faster. Currently, I am using case when to sum the value How can we tweak it to solve the performance issue .

Note table contains 120 column with 10 million records.

Current query is :

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

Table1:

╔════════╦═══════╦════════╗
║  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]

The problem is your column NetAmount . You're storing a numeric value as a string, thus the SQL server is having an awful time of summing the values.

Also, you have no index on the column Weekday meaning that the server has the scan the entire table before it can group anything.

Next, your column Description . Why is it a varchar(1500) ? From you're post your clearly only storing 2 characters, so what are the other 1498 characters for...?

I would do the following

  1. Change your NetAmount column to a decimal (possibly (18,2) based on your query).
  2. Change the Description column to a char(2) as you only ever use 2 characters. The space for the other 1498 characters is a complete waste
  3. Change the Weekday to an int . it's clearly not a varchar and this means ordering will be correct. Weekday shouldn't be in the order 1, 10, 12, 13...19, 2, 20, 21,...3, 30, 31, 4, 5, 6, 7...
  4. Add an index on [Weekday] and [Description] and INCLUDE the column NetAmount .

This results in something like:

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]);

Then, your query simply becomes:

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;

This should perform significantly better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM