Reputation: 16150
Can i reuse a complex select Where clause to different group by?
What i am doing:
(Select X, Count(*) From [Big where clause with many tables] Group By X)
Union All
(Select Y, Count(*) From [Big where clause with many tables] Group By Y)
How can i optmise this?
I'm using SQL Server 2008 and this will go inside a Function, but could be a stored procedure.
Upvotes: 1
Views: 3600
Reputation: 77667
SQL Server 2008 has introduced GROUPING SETS ()
which seems to be just what you are after. The UNION solution suggested by others can now easily be replaced with a single select with GROUPING SETS
.
Basically, you are using it like this:
SELECT A, B, C
FROM …
WHERE …
GROUP BY GROUPING SETS ( (A), (B), (C) )
which is equivalent to
SELECT A, NULL, NULL, …
FROM …
WHERE …
GROUP BY A
UNION ALL
SELECT NULL, B, NULL, …
FROM …
WHERE …
GROUP BY B
UNION ALL
SELECT NULL, NULL, C, …
FROM …
WHERE …
GROUP BY C
So, your query might look like this:
SELECT X, Y, COUNT(*)
FROM your complex joins and filters
GROUP BY GROUPING SETS ( (X), (Y) )
Or like this:
SELECT
CASE WHEN X IS NULL THEN 'Y' ELSE 'X' END AS ObjType
CASE WHEN X IS NULL THEN Y ELSE X END AS Obj,
COUNT(*)
FROM your complex joins and filters
GROUP BY GROUPING SETS ( (X), (Y) )
The second one assumes that X
cannot be NULL.
References:
Upvotes: 2
Reputation: 19320
WITH basequery AS (Select * From [Big where clause with many tables])
SELECT X, COUNT(*) FROM basequery GROUP BY X
UNION ALL
SELECT Y, COUNT(*) FROM basequery GROUP BY Y;
CTEs were made for situations like this.
Upvotes: 5
Reputation: 297
create view
CREATE VIEW SomeView
AS
Select X, Y, Count(*) AS C From [Big where clause with many tables]
then use the view:
Select X, C FROM SomeView GROUP BY X
Upvotes: 0
Reputation: 453243
One option you could evaluate (particularly if there are relatively few x,y
groups) would be to materialise the intermediate results yourself into a @table
or #temp
table then just SELECT
from that (a #temp
table would be better as you could set up better indexes than the below and it allows the select query that populates it to be parallelised but these are not available in a function)
DECLARE @T TABLE
(
X int,
Y int,
Cnt int,
UNIQUE(X,Y,Cnt), /*Cnt just included to make index covering*/
UNIQUE(Y,X,Cnt)
)
INSERT INTO @T
Select X, Y, Count(*)
From [Big where clause with many tables]
Group By X, Y
SELECT X, SUM(Cnt)
FROM @T
GROUP BY X
UNION ALL
SELECT Y, SUM(Cnt)
FROM @T
GROUP BY Y
Upvotes: 2