Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Writing this query more efficiently

Author  Topic 

jordanam
Yak Posting Veteran

62 Posts

Posted - 2007-12-28 : 12:41:24
The query works, but it's ugly and a pain to change. The Ranges aren't completely arbitrary, but if they were determined more programmatically (as a function of the min/max perhaps), it would make some sense.

Any thoughts?

I left out 2 other joins as they are redundant, but left their products in the outermost SELECT just so you can get a better idea of how silly the query is currently written.


SELECT
DurRange
,DurCounts
,ReadCnts
,WriteCnt
,CPUCnts

FROM
(
SELECT
DurRange
,DurCounts = SUM(DurCnt)
FROM
(
SELECT
DurRange = CASE
WHEN Duration < 5000 THEN 5000
WHEN Duration BETWEEN 5000 AND 10000 THEN 10000
WHEN Duration BETWEEN 10001 AND 100000 THEN 100000
WHEN Duration BETWEEN 100001 AND 200000 THEN 200000
WHEN Duration BETWEEN 200000 AND 500000 THEN 500000
WHEN Duration > 500000 THEN 500001
ELSE 0 END
,DurCnt = COUNT(Duration)
FROM tracemee
WHERE Eventclass != 15
GROUP BY
Duration
) duration
GROUP BY
DurRange
) durs

LEFT JOIN
(

SELECT
ReadsRange
,ReadCnts = SUM(ReadsCnt)

FROM
(
SELECT
ReadsRange = CASE
WHEN Reads < 5000 THEN 5000
WHEN Reads BETWEEN 5000 AND 10000 THEN 10000
WHEN Reads BETWEEN 10001 AND 100000 THEN 100000
WHEN Reads BETWEEN 100001 AND 200000 THEN 200000
WHEN Reads BETWEEN 200000 AND 500000 THEN 500000
WHEN Reads > 500000 THEN 500001
ELSE 0 END
,ReadsCnt = COUNT(Reads)
FROM tracemee
WHERE Eventclass != 15
GROUP BY
Reads
) Reads

GROUP BY
ReadsRange
) rds ON rds.ReadsRange = DurRange

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2007-12-28 : 14:05:12
first idea:

create table #range (lrange int, hrange int, rangeDesc int)
insert #range values (0, 4999, 5000)
insert #range values (5000, 10000, 10000)
insert #range values (10001, 100000, 100000)
insert #range values (100001, 500000, 500000)
insert #range values (500001, 2147483647, 500001)

select r.rangeDesc
,count(tr.reads) readsCount
,count(td.duration) durationCount
from #range r
left join tracemee tr
on tr.reads >= r.lrange and tr.reads <= r.hrange and tr.eventclass != 15
left join tracemee td
on td.duration >= r.lrange and td.duration <= r.hrange and tr td.eventclass != 15
group by r.rangeDesc


EDIT: corrected td.EventCalss alias

Be One with the Optimizer
TG
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2007-12-28 : 14:35:37
I just did a quick hack sample that shows one way you might do it. This should only hit the base table once:
DECLARE @TraceMe TABLE (Duration INT, Reads INT, Writes INT, Cpu INT)
DECLARE @Temp TABLE
(
Duration5000 INT,
Duration10000 INT,
Duration100000 INT,
Duration200000 INT,
Duration500000 INT,
Duration500001 INT,
Reads5000 INT,
Reads10000 INT,
Reads100000 INT,
Reads200000 INT,
Reads500000 INT,
Reads500001 INT
-- Etc.
)

INSERT @TraceMe
SELECT 100, 5000, 13000, 12345
UNION ALL SELECT 113113, 400999, 8765432, 987
UNION ALL SELECT 13000, 5001, 101, 19873546


INSERT
@Temp
SELECT
SUM(CASE WHEN Duration < 5000 THEN 1 ELSE 0 END) AS Duration5000,
SUM(CASE WHEN Duration BETWEEN 5000 AND 10000 THEN 1 ELSE 0 END) AS Duration10000,
SUM(CASE WHEN Duration BETWEEN 10001 AND 100000 THEN 1 ELSE 0 END) AS Duration100000,
SUM(CASE WHEN Duration BETWEEN 100001 AND 200000 THEN 1 ELSE 0 END) AS Duration200000,
SUM(CASE WHEN Duration BETWEEN 200000 AND 500000 THEN 1 ELSE 0 END) AS Duration500000,
SUM(CASE WHEN Duration > 500000 THEN 1 ELSE 0 END) AS Duration500001,


SUM(CASE WHEN Reads < 5000 THEN 1 ELSE 0 END) AS Reads5000,
SUM(CASE WHEN Reads BETWEEN 5000 AND 10000 THEN 1 ELSE 0 END) AS Reads10000,
SUM(CASE WHEN Reads BETWEEN 10001 AND 100000 THEN 1 ELSE 0 END) AS Reads100000,
SUM(CASE WHEN Reads BETWEEN 100001 AND 200000 THEN 1 ELSE 0 END) AS Reads200000,
SUM(CASE WHEN Reads BETWEEN 200000 AND 500000 THEN 1 ELSE 0 END) AS Reads500000,
SUM(CASE WHEN Reads > 500000 THEN 1 ELSE 0 END) AS Reads500001
-- etc..
FROM
@TraceMe
-- Ommitted from sample
--WHERE
-- EventClass <> 15

SELECT *
FROM
(
SELECT
5000 AS [Range],
Duration5000 AS DurationCount,
Reads5000 AS ReadsCount
-- etc
FROM
@Temp

UNION ALL

SELECT
10000,
Duration10000,
Reads10000
-- etc
FROM
@Temp
) AS Temp
ORDER BY
[Range]
Go to Top of Page

jordanam
Yak Posting Veteran

62 Posts

Posted - 2008-01-02 : 09:19:35
Thank you both so much. Both solutions make so much more sense...
Go to Top of Page
   

- Advertisement -