I am counting the birthdays , sales , order in all 12 months from customers table in SQL server like these
In Customers table birth_date ,sale_date, order_date are columns of the table
select 1 as ranking,'Birthdays' as Type,[MONTH],TOTAL
from ( select DATENAME(month, birth_date) AS [MONTH],count(*) TOTAL
from customers
group by DATENAME(month, birth_date)
)x
union
select 2 as ranking,'sales' as Type,[MONTH],TOTAL
from ( select DATENAME(month, sale_date) AS [MONTH],count(*) TOTAL
from customers
group by DATENAME(month, sale_date)
)x
union
select 3 as ranking,'Orders' as Type,[MONTH],TOTAL
from ( select DATENAME(month, order_date) AS [MONTH],count(*) TOTAL
from customers
group by DATENAME(month, order_date)
)x
And the output is like these(just dummy data)
ranking | Type | MONTH | TOTAL |
---|---|---|---|
1 | Birthdays | January | 12 |
1 | Birthdays | April | 6 |
1 | Birthdays | May | 10 |
2 | Sales | Febrary | 8 |
2 | Sales | April | 14 |
2 | Sales | May | 10 |
3 | Orders | June | 4 |
3 | Orders | July | 3 |
3 | Orders | October | 6 |
3 | Orders | December | 17 |
I want to find count of these all these three types without using UNION
and UNION ALL
, means I want these data by single query statement (or more optimize version of these query)
CodePudding user response:
Here's one way, aggregating against the output of an UNPIVOT:
;WITH src(d, t, j) AS
(
SELECT d = DATENAME(MONTH,d),
t = v.i,
v.j
FROM dbo.Customers AS c
UNPIVOT (d for col in ([birth_date],[sale_date],[order_date])) AS u
CROSS APPLY (VALUES(1, 'birth_date', 'Birthdays'),
(2, 'sale_date', 'sales'),
(3, 'order_date', 'Orders')) AS v(i, h, j)
WHERE u.col = v.h
)
SELECT ranking = t,
[Type] = j,
[MONTH] = d,
[TOTAL] = COUNT(*)
FROM src GROUP BY t, j, d
ORDER BY ranking;
CodePudding user response:
Another approach is to create a CTE with all available ranking
values and use CROSS APPLY
for it, as shown below.
WITH ranks(ranking) AS (
SELECT * FROM (VALUES (1), (2), (3)) v(r)
)
SELECT
r.ranking,
CASE WHEN r.ranking = 1 THEN 'Birthdays'
WHEN r.ranking = 2 THEN 'Sales'
WHEN r.ranking = 3 THEN 'Orders'
END AS Type,
DATENAME(month, CASE WHEN r.ranking = 1 THEN c.birth_date
WHEN r.ranking = 2 THEN c.sale_date
WHEN r.ranking = 3 THEN c.order_date
END) AS MONTH,
COUNT(*) AS TOTAL
FROM customers c
CROSS APPLY ranks r
GROUP BY r.ranking,
DATENAME(month, CASE WHEN r.ranking = 1 THEN c.birth_date
WHEN r.ranking = 2 THEN c.sale_date
WHEN r.ranking = 3 THEN c.order_date
END)
ORDER BY r.ranking, MONTH