July 29, 2013 at 4:13 pm
Hi,
Is there any analytical function in sql server for achieve results like below:
I did this with 2 temp tables, but might be something already there to look it nicer.
I also need this group by DateIn, and display % for each delDays category
Thanks all
M
create table #log (shipID int, datein datetime, delDays int)
INSERT INTO #LOG (shipid , datein, delDays)
select 1001, '2012-01-06', 9 union all
select 1002, '2012-01-06', 11 union all
select 1002 , '2012-01-06', 11 union all
select 1003 , '2012-01-06', 11 union all
select 1004 , '2012-01-06', 11 union all
select 1005 , '2012-01-06', 11 union all
select 1006 , '2012-01-06', 11 union all
select 1007 , '2012-01-06', 11 union all
select 1008 , '2012-01-06', 11 union all
select 1009 , '2012-01-06', 11 union all
select 1010 , '2012-01-06', 22 union all
select 2001 , '2012-02-06', 15 union all
select 2002 , '2012-02-06', 16 union all
select 2003 , '2012-02-06', 33 union all
select 2004 , '2012-02-06', 22
-- Need this result result:
DateIn | <20days | <30days | >30days |
----------|----------|-----------------------
2012-01-06| 90% | 10% | |
2012-02-06| 50% | 25% | 25% |
July 29, 2013 at 6:43 pm
Your expected results are off for the <30 days column (can't be less of a percent than <20 days), but something like this should do it:
SELECT datein
,[<20days]=ROUND(100.*SUM(CASE WHEN delDays < 20 THEN 1 END)/COUNT(*),0)
,[<30days]=ROUND(100.*SUM(CASE WHEN delDays < 30 THEN 1 END)/COUNT(*),0)
,[>30days]=ROUND(100.*SUM(CASE WHEN delDays > 30 THEN 1 END)/COUNT(*),0)
FROM #LOG
GROUP BY datein
If you meant >=20 and < 30 for the [<30 days] column just change the WHEN clause to:
CASE WHEN delDays BETWEEN 20 AND 30 THEN 1 END
My thought question: Have you ever been told that your query runs too fast?
My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.
Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
Since random numbers are too important to be left to chance, let's generate some![/url]
Learn to understand recursive CTEs by example.[/url]
[url url=http://www.sqlservercentral.com/articles/St
July 29, 2013 at 7:19 pm
Dwain is a master of minimilism and his response is certainly more succinct than mine. But I'll post what I came up with before Dwain beat me to it. I think the only redeeming quality I add is the number of days and the totals, but mine is a lot more verbose. :laugh:
SELECT
p.datein
,p.[<20DelDays]
,CAST(CAST(p.[<20DelDays] AS NUMERIC)/CAST(p.[TotalDelDays] AS NUMERIC) AS DECIMAL(6,2)) AS [<20DelDays%]
,p.[<30DelDays]
,CAST(CAST(p.[<30DelDays] AS NUMERIC)/CAST(p.[TotalDelDays] AS NUMERIC) AS DECIMAL(6,2)) AS [<20DelDays%]
,p.[>30DelDays]
,CAST(CAST(p.[>30DelDays] AS NUMERIC)/CAST(p.[TotalDelDays] AS NUMERIC) AS DECIMAL(6,2)) AS [<20DelDays%]
,p.TotalDelDays
FROM
(
SELECT DISTINCT
r.datein
,ISNULL(SUM([<20DelDays]) OVER (PARTITION BY r.datein),0) AS [<20DelDays]
,ISNULL(SUM([<30DelDays]) OVER (PARTITION BY r.datein),0) AS [<30DelDays]
,ISNULL(SUM([>30DelDays]) OVER (PARTITION BY r.datein),0) AS [>30DelDays]
,(SELECT COUNT(ALL shipID) AS [TotalShipments]
FROM #log AS l2 WHERE datein = r.datein)
AS [TotalDelDays]
FROM
(
SELECT
l.datein
,l.delDays
,l.shipID
,(SELECT
COUNT(delDays)
WHERE
datein = l.datein
AND delDays < 20)
AS [<20DelDays]
,(SELECT
COUNT(delDays)
WHERE
datein = l.datein
AND delDays < 30
AND delDays >= 20)
AS [<30DelDays]
,(SELECT
COUNT(delDays)
WHERE
datein = l.datein
AND delDays > 30)
AS [>30DelDays]
FROM
#log AS l
GROUP BY
l.datein
,l.delDays
,l.shipID
) r
) p
ORDER BY
p.datein
July 29, 2013 at 7:25 pm
Also...looking at the query plans and statistics, Dwain's solution is certainly more efficient if it satifies your requirements...
July 29, 2013 at 7:43 pm
Steven Willis (7/29/2013)
Dwain is a master of minimilism...
I like it. I'm trying to think of a way to incorporate it in my signature.
Reminds me of the quote ChrisM has in his sig:
"Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw
My thought question: Have you ever been told that your query runs too fast?
My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.
Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
Since random numbers are too important to be left to chance, let's generate some![/url]
Learn to understand recursive CTEs by example.[/url]
[url url=http://www.sqlservercentral.com/articles/St
July 29, 2013 at 7:48 pm
dwain.c (7/29/2013)
Steven Willis (7/29/2013)
Dwain is a master of minimilism...I like it. I'm trying to think of a way to incorporate it in my signature.
Reminds me of the quote ChrisM has in his sig:
"Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw
My SQL coding is like a tractor trailer...it gets the job done but carries a lot of baggage with it. Dwain's code is like a fine Italian sports car... 😛
July 29, 2013 at 8:04 pm
Steven Willis (7/29/2013)
dwain.c (7/29/2013)
Steven Willis (7/29/2013)
Dwain is a master of minimilism...I like it. I'm trying to think of a way to incorporate it in my signature.
Reminds me of the quote ChrisM has in his sig:
"Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw
My SQL coding is like a tractor trailer...it gets the job done but carries a lot of baggage with it. Dwain's code is like a fine Italian sports car... 😛
Yup, that's me all right...
My thought question: Have you ever been told that your query runs too fast?
My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.
Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
Since random numbers are too important to be left to chance, let's generate some![/url]
Learn to understand recursive CTEs by example.[/url]
[url url=http://www.sqlservercentral.com/articles/St
July 29, 2013 at 11:46 pm
Thanks all, guys!!!!
I'm very happy that so nice (not mentioned smart) people are around our planet !!!
Best to all.
Dwain, is this your trophy fish?
Mario
July 29, 2013 at 11:54 pm
mario17 (7/29/2013)
Dwain, is this your trophy fish?Mario
That is my 45kg Mekong Catfish! Not a record by any means (they grow well over 100kg) but a record for me.
And you're welcome.
My thought question: Have you ever been told that your query runs too fast?
My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.
Need to UNPIVOT? Why not CROSS APPLY VALUES instead?[/url]
Since random numbers are too important to be left to chance, let's generate some![/url]
Learn to understand recursive CTEs by example.[/url]
[url url=http://www.sqlservercentral.com/articles/St
August 5, 2013 at 2:16 am
dwain.c (7/29/2013)
Your expected results are off for the <30 days column (can't be less of a percent than <20 days), but something like this should do it:
SELECT datein
,[<20days]=ROUND(100.*SUM(CASE WHEN delDays < 20 THEN 1 END)/COUNT(*),0)
,[<30days]=ROUND(100.*SUM(CASE WHEN delDays < 30 THEN 1 END)/COUNT(*),0)
,[>30days]=ROUND(100.*SUM(CASE WHEN delDays > 30 THEN 1 END)/COUNT(*),0)
FROM #LOG
GROUP BY datein
If you meant >=20 and < 30 for the [<30 days] column just change the WHEN clause to:
CASE WHEN delDays BETWEEN 20 AND 30 THEN 1 END
A couple of things to bear in mind:
1. Both the lower and upper values in the BETWEEN clause are included in the return results e.g. Dwain's last example will include values of 20 and 30. An alternative is to use this construct:
CASE WHEN delDays>=20 AND delDays<30 THEN 1 END
2. Having logic that reads "<30" and ">30" misses out values that are spot on 30. May make more sense to choose all of your lower bounds to be <= and upper ones to be >, or similar.
Forum Etiquette: How to post data/code on a forum to get the best helpMake sure that you include code in the appropriate IFCode tags, e.g. <your code here>
. You can find the IFCode tags under the INSERT options when you are writing a post.
Viewing 10 posts - 1 through 9 (of 9 total)
You must be logged in to reply to this topic. Login to reply