Date counts to be display in specific conditions in the stored proc like [0-6 days],[7-14 days] etc - sql-server

I am creating a ssrs report and SP. so i have requirement like this below.
I have table called management in that we have a column description so the data under the
description are only 'Open' and 'Closed'.
I have parameter called User, Start Date and End Date
I need to display the user who all have the count of open cases which are falls under between the start date and
end date in the below conditions.
The conditions are
0-5 days
6-11 days
12-18 days.
For ex:
If i enter start date(MM/DD/YYYY) as 12-1-2019 and end date as 12-31-2019
So i need to display users who has the open case count between the 0-5 days,6-11 days and 12-18 days.

how about something like that?
select [0-5] = SUM(IIF(DATEDIFF(day,OpenDate, CloseDate) >= 0 and DATEDIFF(day,OpenDate, CloseDate) <= 5,1,0))
,[6-11] = SUM(IIF(DATEDIFF(day,OpenDate, CloseDate) >= 6 and DATEDIFF(day,OpenDate, CloseDate) <= 11,1,0))
,[12-18] = SUM(IIF(DATEDIFF(day,OpenDate, CloseDate) >= 12 and DATEDIFF(day,OpenDate, CloseDate) <= 18,1,0))
from tblOpenClose

With a bit of conditional aggregation.
Combined with a Cross Apply for the ranges.
SELECT t.UserId, a.DateDiffRange
, COUNT(CASE WHEN t.Description LIKE 'Open%' THEN 1 END) AS [Open]
, COUNT(CASE WHEN t.Description LIKE 'Closed%' THEN 1 END) AS [Closed]
, COUNT(*) AS [Total]
FROM management AS t
CROSS APPLY
(
SELECT
(CASE
WHEN DATEDIFF(day, t.[Start Date], t.[End Date]) BETWEEN 0 AND 5 THEN '00-05'
WHEN DATEDIFF(day, t.[Start Date], t.[End Date]) BETWEEN 6 AND 11 THEN '06-11'
WHEN DATEDIFF(day, t.[Start Date], t.[End Date]) BETWEEN 12 AND 18 THEN '12-18'
WHEN DATEDIFF(day, t.[Start Date], t.[End Date]) BETWEEN 19 AND 30 THEN '19-30'
END) AS DateDiffRange
) AS a
WHERE t.[Start Date] >= CAST('2019-12-01' AS DATE)
AND t.[End Date] BETWEEN t.[Start Date] AND EOMONTH(t.[Start Date])
GROUP BY YEAR(t.[Start Date]), MONTH(t.[Start Date]), t.UserId, a.DateDiffRange
ORDER BY t.UserId, a.DateDiffRange;
And for more metrics per user?
Check this out for inspiration:
SELECT (YEAR(t.[Start Date])*100+MONTH(t.[Start Date])) AS YearMonth, t.UserId
, SUM(CASE WHEN a.DateDiff BETWEEN 0 AND 5 THEN a.IsOpen END) AS [Opened Within 0-5]
, SUM(CASE WHEN a.DateDiff BETWEEN 6 AND 11 THEN a.IsOpen END) AS [Opened Within 6-11]
, SUM(CASE WHEN a.DateDiff BETWEEN 12 AND 18 THEN a.IsOpen END) AS [Opened Within 12-18]
, SUM(CASE WHEN a.DateDiff BETWEEN 19 AND 30 THEN a.IsOpen END) AS [Opened Within 19-30]
, SUM(CASE WHEN a.DateDiff BETWEEN 0 AND 5 THEN a.IsClosed END) AS [Closed Within 0-5]
, SUM(CASE WHEN a.DateDiff BETWEEN 6 AND 11 THEN a.IsClosed END) AS [Closed Within 6-11]
, SUM(CASE WHEN a.DateDiff BETWEEN 12 AND 18 THEN a.IsClosed END) AS [Closed Within 12-18]
, SUM(CASE WHEN a.DateDiff BETWEEN 19 AND 30 THEN a.IsClosed END) AS [Closed Within 19-30]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 1 AND 5 THEN a.IsOpen END) AS [Opened Start 1-5]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 6 AND 11 THEN a.IsOpen END) AS [Opened Start 6-11]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 12 AND 18 THEN a.IsOpen END) AS [Opened Start 12-18]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 19 AND 30 THEN a.IsOpen END) AS [Opened Start 19-31]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 1 AND 5 THEN a.IsClosed END) AS [Closed Start 0-5]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 6 AND 11 THEN a.IsClosed END) AS [Closed Start 6-11]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 12 AND 18 THEN a.IsClosed END) AS [Closed Start 12-18]
, SUM(CASE WHEN DAY(t.[Start Date]) BETWEEN 19 AND 31 THEN a.IsClosed END) AS [Closed Start 19-31]
, COUNT(*) AS [Total]
FROM management AS t
CROSS APPLY
(
SELECT
DATEDIFF(day, t.[Start Date], t.[End Date]) AS [DateDiff],
CASE WHEN t.Description LIKE 'Open%' THEN 1 END AS [IsOpen],
CASE WHEN t.Description LIKE 'Closed%' THEN 1 END AS [IsClosed]
) AS a
WHERE t.[Start Date] >= CAST('2019-12-01' AS DATE)
AND t.[End Date] BETWEEN t.[Start Date] AND EOMONTH(t.[Start Date])
GROUP BY YEAR(t.[Start Date]), MONTH(t.[Start Date]), t.UserId
ORDER BY YearMonth, t.UserId;
YearMonth | UserId | Opened Within 0-5 | Opened Within 6-11 | Opened Within 12-18 | Opened Within 19-30 | Closed Within 0-5 | Closed Within 6-11 | Closed Within 12-18 | Closed Within 19-30 | Opened Start 1-5 | Opened Start 6-11 | Opened Start 12-18 | Opened Start 19-31 | Closed Start 0-5 | Closed Start 6-11 | Closed Start 12-18 | Closed Start 19-31 | Total
--------: | -----: | ----------------: | -----------------: | ------------------: | ------------------: | ----------------: | -----------------: | ------------------: | ------------------: | ---------------: | ----------------: | -----------------: | -----------------: | ---------------: | ----------------: | -----------------: | -----------------: | ----:
201912 | 101 | 4 | 4 | 3 | 1 | null | 1 | 3 | 1 | 10 | null | 2 | null | 5 | null | null | null | 17
201912 | 102 | 3 | 2 | null | null | null | null | null | null | 5 | null | null | null | null | null | null | null | 5
Test on db<>fiddle here

Related

Get the count of statuses by date but only count continuous rows

I have this data:
ID Name Status Date
1 Machine1 Active 2018-01-01
2 Machine2 Fault 2018-01-01
3 Machine3 Active 2018-01-01
4 Machine1 Fault 2018-01-02
5 Machine2 Active 2018-01-02
6 Machine3 Active 2018-01-02
7 Machine2 Active 2018-01-03
8 Machine1 Fault 2018-01-03
9 Machine2 Active 2018-01-04
10 Machine1 Fault 2018-01-04
11 Machine3 Active 2018-01-06
INPUT
and i want these data in output
EXPECTED OUTPUT
Name Last Status Count
Machine1 Fault 3
Machine2 Active 3
Machine3 Active 1 Because Date is not Continuous
*Count : Last number of status in continuous history
I believe it is as simple as this:
WITH cte1 AS (
SELECT
Name,
Status,
DATEADD(DAY, ROW_NUMBER() OVER (PARTITION BY Name, Status ORDER BY Date DESC) - 1, Date) AS GroupingDate
FROM testdata
), cte2 AS (
SELECT
Name,
Status,
RANK() OVER (PARTITION BY Name ORDER BY GroupingDate DESC) AS GroupingNumber
FROM cte1
)
SELECT Name, Status AS LastStatus, COUNT(*) AS LastStatusCount
FROM cte2
WHERE GroupingNumber = 1
GROUP BY Name, Status
ORDER BY Name
Result and DBFiddle:
| Name | LastStatus | LastStatusCount |
|----------|------------|-----------------|
| Machine1 | Fault | 3 |
| Machine2 | Active | 3 |
| Machine3 | Active | 1 |
In order to understand how this works, look at the intermediate values generated by CTE:
| Name | Status | Date | RowNumber | GroupingDate | GroupingNumber |
|----------|--------|---------------------|-----------|---------------------|----------------|
| Machine1 | Fault | 04/01/2018 00:00:00 | 1 | 04/01/2018 00:00:00 | 1 |
| Machine1 | Fault | 03/01/2018 00:00:00 | 2 | 04/01/2018 00:00:00 | 1 |
| Machine1 | Fault | 02/01/2018 00:00:00 | 3 | 04/01/2018 00:00:00 | 1 |
| Machine1 | Active | 01/01/2018 00:00:00 | 1 | 01/01/2018 00:00:00 | 4 |
| Machine2 | Active | 04/01/2018 00:00:00 | 1 | 04/01/2018 00:00:00 | 1 |
| Machine2 | Active | 03/01/2018 00:00:00 | 2 | 04/01/2018 00:00:00 | 1 |
| Machine2 | Active | 02/01/2018 00:00:00 | 3 | 04/01/2018 00:00:00 | 1 |
| Machine2 | Fault | 01/01/2018 00:00:00 | 1 | 01/01/2018 00:00:00 | 4 |
| Machine3 | Active | 06/01/2018 00:00:00 | 1 | 06/01/2018 00:00:00 | 1 |
| Machine3 | Active | 02/01/2018 00:00:00 | 2 | 03/01/2018 00:00:00 | 2 |
| Machine3 | Active | 01/01/2018 00:00:00 | 3 | 03/01/2018 00:00:00 | 2 |
The trick here is that if two numbers are contiguous then subtracting contiguous numbers from them will result in same value. E.g. if we have 5, 6, 8, 9 then subtracting 1, 2, 3, 4 in that order will produce 4, 4, 5, 5.
I think this will work, though SQLFiddle is having a fit at the moment, so I can't test:
SELECT [Name], [Status], ct as [Count]
FROM (
SELECT
[name],
[status],
[date],
1 + (SUM( grp ) OVER (PARTITION BY [name], [status] ORDER BY [date] ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) * grp) ct,
row_number() over(partition by [name] order by [date] desc) rn
FROM
(
SELECT *, CASE WHEN LAG([Date]) OVER(PARTITION BY [name], [status] ORDER BY [date] ) = DATEADD(day, -1, [date]) THEN 1 ELSE 0 END grp
FROM t
) x
) y
WHERE
rn = 1
It first off uses LAG to look at the current row and the previous row (grouping the data into machine name and status, ordering the data by date) and if the current date is 1 day different to the previous date it records a 1 else a 0
These 1s and zeroes are summed in a running total fashion, resetting when the machine name or status changes (the partition of the sum() over() )
Also we want to consider the data just in terms of the machine name, and we only want the latest record from each machine, so we partition by the machine name, and count in order of date descending, then just pick (with the where clause) the rows that are numbered 1 for each machine
It actually makes a lot more sense if you run the queries separately, like this
Calculate the "is the current report consecutive with the previous report, for the given status and machine" 1 = yes, 0 = no:
SELECT *, CASE WHEN LAG([Date]) OVER(PARTITION BY [name], [status] ORDER BY [date] ) = DATEADD(day, -1, [date]) THEN 1 ELSE 0 END grp
FROM t
Calculate the "what is the running total of the current block of consecutive reports":
SELECT
[name],
[status],
[date],
1 + (SUM( grp ) OVER (PARTITION BY [name], [status] ORDER BY [date] ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) * grp) ct,
row_number() over(partition by [name] order by [date] desc) rn
FROM
(
SELECT *, CASE WHEN LAG([Date]) OVER(PARTITION BY [name], [status] ORDER BY [date] ) = DATEADD(day, -1, [date]) THEN 1 ELSE 0 END grp
FROM t
) x
Then of course, the whole thing but without the where clause, so you can see the data we're discarding:
SELECT [Name], [Status], ct as [Count]
FROM (
SELECT
[name],
[status],
[date],
1 + (SUM( grp ) OVER (PARTITION BY [name], [status] ORDER BY [date] ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) * grp) ct,
row_number() over(partition by [name] order by [date] desc) rn
FROM
(
SELECT *, CASE WHEN LAG([Date]) OVER(PARTITION BY [name], [status] ORDER BY [date] ) = DATEADD(day, -1, [date]) THEN 1 ELSE 0 END grp
FROM t
) x
) y
Fiddle finally woke up:
http://www.sqlfiddle.com/#!18/77dae/2

SQL server Query for SUM group

I have table:
-------------------------------------
| Code | Name | Type | Qty |
-------------------------------------
| 0001 | Mouse | Purchase | 5 |
| 0002 | KeyBrd | Purchase | 8 |
| 0003 | Mouse | Sale | 2 |
-------------------------------------
i want to select them like this:
------------------------------------------------------------
| Code | Name | Total Purchase | Total Sale | Stock |
------------------------------------------------------------
| 0001 | Mouse | 5 | 2 | 3 |
| 0002 | KeyBrd | 8 | 0 | 8 |
------------------------------------------------------------
Im so confused, please help me with the query, thank you in advance
Try This
SELECT
Code,
Name,
TotalPurchase = SUM(CASE WHEN [Type] = 'Purchase' THEN Qty ELSE 0 END),
TotalSale = SUM(CASE WHEN [Type] = 'Sale' THEN Qty ELSE 0 END),
Stock = SUM(CASE WHEN [Type] = 'Purchase' THEN Qty ELSE 0 END) - SUM(CASE WHEN [Type] = 'Sale' THEN Qty ELSE 0 END)
FROM YourTable
group by Code,
Name
Conditional aggregation with the help of case expression is one approach
select min(Code) Code,
Name,
sum(case when Type = 'Purchase' then Qty else 0 end) [Total Purchase],
sum(case when Type = 'Sale' then Qty else 0 end) [Total Sale],
sum(case when Type = 'Purchase' then -Qty else Qty end) Stock
from table t
group by Name
We can also use like below.(Using Pivot) Please try this.
Data Generation
CREATE TABLE TableCase
(
Code VARCHAR(10)
,[Name] VARCHAR(10)
,[Type] VARCHAR(20)
,Qty INT
)
GO
INSERT INTO TableCase VALUES
('0001','Mouse' ,'Purchase',5),
('0002','KeyBrd' ,'Purchase',8),
('0003','Mouse' ,'Sale',2 )
GO
SOLUTION
SELECT MIN(Code) Code,[Name]
, ISNULL(SUM([Purchase]),0) [TotalPurchase]
, ISNULL(SUM([Sale]),0) TotalSale
, ISNULL(SUM([Purchase]),0) - ISNULL(SUM([Sale]),0) Stock
FROM TableCase
PIVOT
(
MAX(Qty) FOR [Type] IN ([Purchase],[Sale])
)t
GROUP By [Name]
ORDER BY [code]
OUTPUT
Code Name TotalPurchase TotalSale Stock
---------- ---------- ------------- ----------- -----------
0001 Mouse 5 2 3
0002 KeyBrd 8 0 8
(2 rows affected)

Calculate Median of a column (Days on Shelf) for different ranges of another column (Price)

I am trying to find the Median number of Carats of Gold for each day of the year. And I need to segregate these as per the price range of Gold in different columns.
The data:
Create table Daily_Gold_Rate
( S_No int, Dt datetime, Carat int, Gold_Rate numeric(18,2))
Insert into Daily_Gold_Rate values(1,'2013-01-03',18,155.00)
Insert into Daily_Gold_Rate values(2,'2013-01-03',22,190.50)
Insert into Daily_Gold_Rate values(3,'2013-01-03',24,202.23)
Insert into Daily_Gold_Rate values(4,'2013-01-03',18,400.00)
Insert into Daily_Gold_Rate values(5,'2013-01-03',22,480.50)
Insert into Daily_Gold_Rate values(6,'2013-01-03',24,671.23)
Insert into Daily_Gold_Rate values(7,'2013-01-04',18,153.00)
Insert into Daily_Gold_Rate values(8,'2013-01-04',22,191.00)
Insert into Daily_Gold_Rate values(9,'2013-01-04',24,202.25)
Insert into Daily_Gold_Rate values(10,'2013-01-04',18,351.00)
Insert into Daily_Gold_Rate values(11,'2013-01-04',22,892.00)
Insert into Daily_Gold_Rate values(12,'2013-01-04',24,1003.25)
Insert into Daily_Gold_Rate values(13,'2013-01-05',18,150.00)
Insert into Daily_Gold_Rate values(14,'2013-01-05',22,190.00)
Insert into Daily_Gold_Rate values(15,'2013-01-05',24,203.25)
Insert into Daily_Gold_Rate values(16,'2013-01-05',18,773.00)
Insert into Daily_Gold_Rate values(17,'2013-01-05',22,542.00)
Insert into Daily_Gold_Rate values(18,'2013-01-05',24,182.25)
Insert into Daily_Gold_Rate values(19,'2013-01-06',18,158.00)
Insert into Daily_Gold_Rate values(20,'2013-01-06',22,189.50)
Insert into Daily_Gold_Rate values(21,'2013-01-06',24,201.50)
Insert into Daily_Gold_Rate values(22,'2013-01-06',18,624.00)
Insert into Daily_Gold_Rate values(23,'2013-01-06',
Insert into Daily_Gold_Rate values(24,'2013-01-06',24,411.50)
Simple PERCENTILE_CONT shown below:
Select Dt, Carat, Gold_Rate, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY
Carat) OVER (PARTITION BY Carat) AS MedianCont
from Daily_Gold_Rate
order by Dt;Expected output is like this:
Returns this Data:
Dt | Carat | Gold_Rate | MedianCont
2013-01-03 00:00:00.000 | 18 | 155.00 | 18
2013-01-03 00:00:00.000 | 18 | 400.00 | 18
2013-01-03 00:00:00.000 | 22 | 480.50 | 22
2013-01-03 00:00:00.000 | 22 | 190.50 | 22
2013-01-03 00:00:00.000 | 24 | 202.23 | 24
2013-01-03 00:00:00.000 | 24 | 671.23 | 24
2013-01-04 00:00:00.000 | 24 | 202.25 | 24
2013-01-04 00:00:00.000 | 24 | 1003.25 | 24
2013-01-04 00:00:00.000 | 18 | 153.00 | 18
2013-01-04 00:00:00.000 | 18 | 351.00 | 18
2013-01-04 00:00:00.000 | 22 | 892.00 | 22
2013-01-04 00:00:00.000 | 22 | 191.00 | 22
2013-01-05 00:00:00.000 | 22 | 542.00 | 22
2013-01-05 00:00:00.000 | 22 | 190.00 | 22
2013-01-05 00:00:00.000 | 18 | 150.00 | 18
2013-01-05 00:00:00.000 | 18 | 773.00 | 18
2013-01-05 00:00:00.000 | 24 | 203.25 | 24
2013-01-05 00:00:00.000 | 24 | 182.25 | 24
2013-01-06 00:00:00.000 | 24 | 201.50 | 24
2013-01-06 00:00:00.000 | 24 | 411.50 | 24
2013-01-06 00:00:00.000 | 18 | 158.00 | 18
2013-01-06 00:00:00.000 | 18 | 624.00 | 18
2013-01-06 00:00:00.000 | 22 | 735.50 | 22
2013-01-06 00:00:00.000 | 22 | 189.50 | 22
I need to pivot on Gold Price Range. So, I am trying through this query:
with a as (
select year(Dt) as "year", month(Dt) as "month", day(Dt) as "day",
case when Gold_Rate / 200 < 5 then Gold_Rate / 200 else 5 end as
price_bucket,
PERCENTILE_CONT(.50) WITHIN GROUP (ORDER BY Carat) over (PARTITION BY
day(Dt), month(Dt)) as MED_days
from Daily_Gold_Rate
group by year(Dt), month(Dt), day(Dt), Gold_Rate / 200, Carat)
select "year", "month", "day",
[1] as "less than 400", [2] as "400-599", [3] as "600-799", [4] as "800-
999", [5] as "Over 1000"
from a pivot (max(MED_days) for price_bucket in ([1], [2], [3], [4], [5])) p
order by "year", "month", "day";
But, this is what I am getting, instead. :(
Year | Month | Day | 1-399 | 400-599 | 600-799| 800-999| Over 1000
2013 | 1 | 3 | NULL | 22 | NULL | NULL | NULL
2013 | 1 | 4 | NULL | NULL | NULL | NULL | 22
2013 | 1 | 5 | NULL | NULL | NULL | NULL | NULL
2013 | 1 | 6 | NULL | NULL | NULL | NULL | NULL
Pivoting before the percentile calculation:
select distinct
dt
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratelt400) OVER (PARTITION BY dt) ratelt400
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratebtwn400599) OVER (PARTITION BY dt) ratebtwn400599
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratebtwn600799) OVER (PARTITION BY dt) ratebtwn600799
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ratebtwn800999) OVER (PARTITION BY dt) ratebtwn800999
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rateovr1000) OVER (PARTITION BY dt) rateovr1000
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratlt400) OVER (PARTITION BY dt) caratlt400
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratbtwn400599) OVER (PARTITION BY dt) caratbtwn400599
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratbtwn600799) OVER (PARTITION BY dt) caratbtwn600799
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratbtwn800999) OVER (PARTITION BY dt) caratbtwn800999
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY caratovr1000) OVER (PARTITION BY dt) caratovr1000
from (
SELECT
DATEADD(day, DATEDIFF(day, 0, dt), 0) dt
, CASE WHEN Gold_Rate < 400 THEN Gold_Rate END ratelt400
, CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN Gold_Rate END ratebtwn400599
, CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN Gold_Rate END ratebtwn600799
, CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN Gold_Rate END ratebtwn800999
, CASE WHEN Gold_Rate >= 1000 THEN Gold_Rate END rateovr1000
, CASE WHEN Gold_Rate < 400 THEN carat END caratlt400
, CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN carat END caratbtwn400599
, CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN carat END caratbtwn600799
, CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN carat END caratbtwn800999
, CASE WHEN Gold_Rate >= 1000 THEN carat END caratovr1000
FROM Daily_Gold_Rate
) d
GO
dt | ratelt400 | ratebtwn400599 | ratebtwn600799 | ratebtwn800999 | rateovr1000 | caratlt400 | caratbtwn400599 | caratbtwn600799 | caratbtwn800999 | caratovr1000
:------------------ | --------: | -------------: | -------------: | -------------: | ----------: | ---------: | --------------: | --------------: | --------------: | -----------:
03/01/2013 00:00:00 | 190.5 | 440.25 | 671.23 | null | null | 22 | 20 | 24 | null | null
04/01/2013 00:00:00 | 196.625 | null | null | 892 | 1003.25 | 20 | null | null | 22 | 24
05/01/2013 00:00:00 | 186.125 | 542 | 773 | null | null | 23 | 22 | 18 | null | null
06/01/2013 00:00:00 | 189.5 | 411.5 | 624 | null | null | 22 | 24 | 18 | null | null
dbfiddle here
Below are some working queries for values by either carats or rates:
revised answer:
Rates by Day
SELECT DISTINCT
DATEADD(day, DATEDIFF(day, 0, dt), 0) dt
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate < 400 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) lt400
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn400599
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn600799
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn800999
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate >= 1000 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) ovr1000
FROM Daily_Gold_Rate
GO
dt | lt400 | btwn400599 | btwn600799 | btwn800999 | ovr1000
:------------------ | ------: | ---------: | ---------: | ---------: | ------:
03/01/2013 00:00:00 | 190.5 | 440.25 | 671.23 | null | null
04/01/2013 00:00:00 | 196.625 | null | null | 892 | 1003.25
05/01/2013 00:00:00 | 186.125 | 542 | 773 | null | null
06/01/2013 00:00:00 | 189.5 | 411.5 | 624 | null | null
Carats by Day
SELECT DISTINCT
DATEADD(day, DATEDIFF(day, 0, dt), 0) dt
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate < 400 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) lt400
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn400599
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn600799
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) btwn800999
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate >= 1000 THEN carat END) OVER (PARTITION BY DATEADD(day, DATEDIFF(day, 0, dt), 0)) ovr1000
FROM Daily_Gold_Rate
GO
dt | lt400 | btwn400599 | btwn600799 | btwn800999 | ovr1000
:------------------ | ----: | ---------: | ---------: | ---------: | ------:
03/01/2013 00:00:00 | 22 | 20 | 24 | null | null
04/01/2013 00:00:00 | 20 | null | null | 22 | 24
05/01/2013 00:00:00 | 23 | 22 | 18 | null | null
06/01/2013 00:00:00 | 22 | 24 | 18 | null | null
dbfiddle here
By Month: FYI only
SELECT DISTINCT
DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0) dt
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate < 400 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) lt400
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 400 AND 599 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) btwn400599
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 600 AND 799 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) btwn600799
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate BETWEEN 800 AND 999 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) btwn800999
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CASE WHEN Gold_Rate >= 1000 THEN Gold_Rate END) OVER (PARTITION BY DATEADD(MONTH, DATEDIFF(MONTH, 0, dt), 0)) ovr1000
FROM Daily_Gold_Rate
GO
dt | lt400 | btwn400599 | btwn600799 | btwn800999 | ovr1000
:------------------ | -----: | ---------: | ---------: | ---------: | ------:
01/01/2013 00:00:00 | 190.25 | 446 | 671.23 | 892 | 1003.25
dbfiddle here

SQL SERVER How to combine two query on the same table that has "group by"

I want to combine two queries on the same table that has group by.
here is my table :
Date##### | Value1 | Value2 | Value3 | Type
23/04/2014 | 1,2 | 12,3 | 10 | Green
23/04/2014 | 11,2 | 3 | 10,3 | Non-Green
24/04/2014 | 10,9 | 3 | 11 | Green
24/04/2014 | 2,3 | 12,3 | 8 | Green
25/04/2014 | 10 | 2 | 10,8 | Non-Green
25/04/2014 | 1,4 | 5 | 12 | Green
I want it to display:
Date##### | Count |Type
23/04/2014 | 2 | Green
23/04/2014 | 2 | Non-Green
24/04/2014 | 3 | Green
25/04/2014 | 2 | Non-Green
25/04/2014 | 1 | Green
here is my first query :
Dim strCommand As String = "SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth where Type = 'Green' GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC"
It display :
Date##### | Count |Type
23/04/2014 | 2 | Green
24/04/2014 | 3 | Green
25/04/2014 | 1 | Green
my second query :
Dim strCommand As String = "SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth where Type = 'Non-Green' GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC"
It display :
Date##### | Count |Type
23/04/2014 | 2 | Non-Green
25/04/2014 | 2 | Non-Green
I want to combine both query to become one, and take the date, result of green and result of non-green. Assume that I have a lot of group of date, I want it to display only the last 7 group of date based on ASC order. I try to add UNION between my two query. Here is my code so far:
Dim strCommand As String = "Select 'Test1', * from tbBooth where type ='Green' and exist(SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC) Union Select 'Test2', * from tbBooth where type ='Non-Green' and exist(SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC)
it give me an error Incorrect syntax near the keyword 'SELECT'.
is ther anyway how to do it? I tried to look on other SO post but I don't have any clue to do it because both my query are complex...
Thanks in advances....
It's not that your combined query is complex, it's just that it's wrong.
What I don't understand is why you have the WHERE Type = 'Green' and 'Non-green'.
Given what you want as result, you could just remove that where and get pretty much what you're after:
SELECT d ,
LW ,
cnt
FROM ( SELECT TOP 7
[date] AS d ,
[Type] AS LW ,
SUM(CASE WHEN ManualAssists1 >= 10 THEN 1
ELSE 0
END + CASE WHEN ManualAssists2 >= 10 THEN 1
ELSE 0
END + CASE WHEN ManualAssists3 >= 10 THEN 1
ELSE 0
END) AS cnt
FROM tbBooth
--WHERE Type = 'Green'
GROUP BY [date] ,
[Type]
ORDER BY [date] DESC
) x
ORDER BY d ASC
Which gives:
2014-04-23 Green 2
2014-04-23 Non-Green 2
2014-04-24 Green 3
2014-04-25 Green 1
2014-04-25 Non-Green 2
I see no need to "combine" the two queries when the two queries are identical besides the 'Type' in the WHERE?
Bro, in your code change exist to exists
:) this should Work
Updated:
Add Top 7 to select
Select 'Test1', * from tbBooth
where type ='Green' and exists(SELECT **top 7** d, LW, cnt FROM(SELECT TOP 7 [date] AS d,
[Type] as LW,
SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt
FROM tbBooth GROUP BY [date],[Type]
ORDER BY [date] DESC) x ORDER BY d ASC)
Union
Select 'Test2', * from tbBooth where type ='Non-Green'
and exists(SELECT **top 7** d, LW, cnt FROM(SELECT TOP 7
[date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt
FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC)

Multiple PIVOTS? Need to count by Hour Per Month

This should be pretty simple. I have other PIVOT SQL queries working fine. I want to count logins: by hour, by month. I am thinking two PIVOTs or UNPIVOT and then PIVOT? Yes, I have dug around here, other sites, Google, etc. I am pretty stuck.
SELECT
loginid
,DATEPART(MONTH,logtime) Month
, DATEPART(HOUR, logtime) Hour
FROM somelog (nolock)
) temp
PIVOT (
COUNT(loginid)
FOR Month in (JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC)
) AS Pvt
What I want the results to be..
HOUR,JAN,FEB,MAR
00
01
02
..
23
and I don't need 8760 (365 x 24) of them
I have tried GROUP BY HOUR
I have tried GROUP BY temp.hour
I have also tried this as well.. It does seem to work, but I get Hour 00 for example 365 times.. Again, the GROUP BY issue..
SELECT
TimeOfDay
, [1] JAN
, [2] FEB
, [3] MAR
, [4] APR
, [5] MAY
, [6] JUN
, [7] JUL
, [8] AUG
, [9] SEP
, [10] OCT
, [11] NOV
, [12] DEC
FROM (SELECT logintime
, loginid
, datepart(month, logintime) [month]
, DatePart(hour, logintime) TimeOfDay
FROM sometable (nolock)) x
PIVOT (
COUNT(loginid)
for [month] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) AS pvt
ORDER BY 1, 2
Thanks,
Kent
One way to do it
WITH hour_list AS (
SELECT 0 hour
UNION ALL
SELECT hour + 1 FROM hour_list WHERE hour < 23
)
SELECT h.hour,
COALESCE(jan, 0) jan,
COALESCE(feb, 0) feb,
COALESCE(mar, 0) mar,
COALESCE(apr, 0) apr,
COALESCE(may, 0) may,
COALESCE(jun, 0) jun,
COALESCE(jul, 0) jul,
COALESCE(aug, 0) aug,
COALESCE(sep, 0) sep,
COALESCE(oct, 0) oct,
COALESCE(nov, 0) nov,
COALESCE(dec, 0) dec
FROM hour_list h LEFT JOIN
(
SELECT DATEPART(HOUR, logtime) hour,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 1 THEN 1 END) jan,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 2 THEN 1 END) feb,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 3 THEN 1 END) mar,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 4 THEN 1 END) apr,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 5 THEN 1 END) may,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 6 THEN 1 END) jun,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 7 THEN 1 END) jul,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 8 THEN 1 END) aug,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 9 THEN 1 END) sep,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 10 THEN 1 END) oct,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 11 THEN 1 END) nov,
SUM(CASE WHEN DATEPART(MONTH, logtime) = 12 THEN 1 END) dec
FROM somelog (NOLOCK)
GROUP BY DATEPART(HOUR, logtime)
) l
ON h.hour = l.hour
or with PIVOT
WITH hour_list AS (
SELECT 0 hour
UNION ALL
SELECT hour + 1 FROM hour_list WHERE hour < 23
)
SELECT h.hour,
COALESCE([1], 0) jan,
COALESCE([2], 0) feb,
COALESCE([3], 0) mar,
COALESCE([4], 0) apr,
COALESCE([5], 0) may,
COALESCE([6], 0) jun,
COALESCE([7], 0) jul,
COALESCE([8], 0) aug,
COALESCE([9], 0) sep,
COALESCE([10], 0) oct,
COALESCE([11], 0) nov,
COALESCE([12], 0) dec
FROM hour_list h LEFT JOIN
(
SELECT DATEPART(MONTH, logtime) month,
DATEPART(HOUR, logtime) hour,
COUNT(*) log_count
FROM somelog (NOLOCK)
GROUP BY DATEPART(MONTH, logtime), DATEPART(HOUR, logtime)
) s
PIVOT
(
SUM(log_count) FOR month IN([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
) p
ON h.hour = p.hour
Sample output for both queries:
| HOUR | JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC |
|------|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
| 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 3 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
...
Here is SQLFiddle demo (using CASE)
Here is SQLFiddle demo (using PIVOT)

Resources