SQL query - unique values with multiple condition - sql

I have the following query and I would need to modify that it counts the sums only for unique values in the Unit_Serial_No column (on the count I can easily do that with DISTINCT), I just don't know how to do with SUM. Thanks in advance!
SELECT COUNT(Test_Result) as 'Total'
,SUM(CASE WHEN Test_Result='Pass' THEN 1 END) AS 'Passed'
,SUM(CASE WHEN Test_Result='Fail' THEN 1 END) AS 'Failed'
FROM [Optima_Test_Results].[dbo].[Optima PreChamber Test]
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, Created_Date)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
Solution, with little adjustments, credit to Madhivanan:
SELECT COUNT(DISTINCT Unit_Serial_No) as 'Total'
,COUNT(DISTINCT CASE WHEN Test_Result='Pass' THEN Unit_Serial_No END) AS 'Passed'
,COUNT(DISTINCT CASE WHEN Test_Result='Fail' THEN Unit_Serial_No END) AS 'Failed'
FROM [Optima_Test_Results].[dbo].[Optima PreChamber Test]
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, Created_Date)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

Try this
SELECT COUNT(DISTINCT Test_Result) as 'Total'
,COUNT(DISTINCT CASE WHEN Test_Result='Pass' THEN serial_no END) AS 'Passed'
,COUNT(DISTINCT CASE WHEN Test_Result='Fail' THEN serial_no END) AS 'Failed'
FROM [Optima_Test_Results].[dbo].[Optima PreChamber Test]
WHERE
DATEADD(dd, 0, DATEDIFF(dd, 0, Created_Date)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))

This query can help if you don't have different results for same tests. Otherwise they will be counted twice: once for 'Passed' and once for 'Failed':
;WITH uniquevalues AS
(
SELECT DISTINCT Unit_Serial_No, Test_Result
FROM [Optima_Test_Results].[dbo].[Optima PreChamber Test]
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0, Created_Date)) = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE()))
)
SELECT COUNT(Test_Result) as 'Total'
,SUM(CASE WHEN Test_Result='Pass' THEN 1 END) AS 'Passed'
,SUM(CASE WHEN Test_Result='Fail' THEN 1 END) AS 'Failed'
FROM uniquevalues

Related

Select Distinct Case Query

I have the below query
SELECT Distinct dbo.WSUS_ComputerUpdateStatusWithApprovals.fulldomainname AS [Computer Name]
,dbo.WSUS_ComputerUpdateStatusWithApprovals.title AS [Update Title]
,count((case when (DATEDIFF(day, [ArrivalDate], GetDate())) > '0' and (DATEDIFF(day, [ArrivalDate], GetDate())) < '31' Then '' End)) AS 'Green'
,count((case when (DATEDIFF(day, [ArrivalDate], GetDate())) > '31' and (DATEDIFF(day, [ArrivalDate], GetDate())) < '91' then '' End)) AS 'Yellow'
,count((case when (DATEDIFF(day, [ArrivalDate], GetDate())) > '90' then '' End)) AS 'Red'
,DATEDIFF(day, [ApprovalCreationDate], GetDate()) AS 'DaysOldSinceApproval'
FROM dbo.WSUS_ComputerUpdateStatusWithApprovals
WHERE dbo.WSUS_ComputerUpdateStatusWithApprovals.IsApproved = 1
Group by dbo.WSUS_ComputerUpdateStatusWithApprovals.fulldomainname
,[ArrivalDate]
,dbo.WSUS_ComputerUpdateStatusWithApprovals.ApprovalCreationDate
,dbo.WSUS_ComputerUpdateStatusWithApprovals.title
ORDER BY dbo.WSUS_ComputerUpdateStatusWithApprovals.fulldomainname ASC
The result set comes out like this:
Where I would want it to say Computer Name and a Total count for each Green, Yellow, Red. So in this case, Computer Name, Green = 3, Yellow = 1 and Red = 1. I included the title and days old to show additional information.
If I followed you correctly, you just need to change the group by clause so it generates one row per fulldomainname:
select
fulldomainname AS [Computer Name],
sum(case when datediff(day, [ArrivalDate], GetDate()) between 1 and 30 then 1 else 0 end) AS Green,
sum(case when datediff(day, [ArrivalDate], GetDate()) between 30 and 90 then 1 else 0 end) AS Yellow,
sum(case when datediff(day, [ArrivalDate], GetDate()) > 90 then 1 else 0 end) AS Red
from dbo.WSUS_ComputerUpdateStatusWithApprovals
where IsApproved = 1
group by fulldomainname
order by fulldomainname ASC
Note that I changed the conditional aggregation logic to use sum() rather than count(), because it seems easier to follow.

Divide by Case When

I'm currently doing some work on a 6 month rolling report, but i seem to be a little bit stuck on one area.
I have one column Liveatcutoff_PC it will be populated by 1 for live or 0 for not live. If it's 0 it means it's cancelled. I want to work out the cancellation % for the date range in my code but I'm not having much luck.
SELECT
UserID
,Agent
,COUNT(CASE WHEN SaleDate>=DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-6, 0)
AND SaleDate < DATEADD(MONTH, DATEDIFF(MONTH, -6, GETDATE())-6, 0)
AND LiveAtCutOff_PC='0' THEN LiveAtCutOff_PC END)
FROM PDS_SALES_PMI
WHERE SaleDate>='2019-01-01'
AND Leaver='0'
GROUP BY UserID, Agent
Help much appreciated.
If I understand correctly, you can use AVG():
AVG(CASE WHEN SaleDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-6, 0) AND
SaleDate < DATEADD(MONTH, DATEDIFF(MONTH, -6, GETDATE())-6, 0) THEN LiveAtCutOff_PC * 1.0
END) as LiveAtCutoff_PC_ratio
Your question specifies that LiveAtCutOff_PC has values of 0 and 1, which implies that the field is a number. However, the code compares it to a string, which suggests otherwise. If the values are only 0 and 1 then the above should work for both numbers and strings (although for bit you would need to convert the value).
So since you requirement is to find out the percentage of canceled sales then you don't have to do it in one query. Case will just calculate everything, including nulls(that will come up because you don't have 'else')
you might want to try subquery instead or use CTE.
CTE example
with CTE as (
Select UserID
,Agent
,COUNT(*) as Canceled
from PDS_SALES_PMI
where SaleDate >=DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-6, 0)
AND SaleDate < DATEADD(MONTH, DATEDIFF(MONTH, -6, GETDATE())-6, 0)
AND LiveAtCutOff_PC='0'
AND SaleDate >='2019-01-01'
AND Leaver = 0
group by UserID, AgentID)
Select a.UserID
,a.AgentID
,Canceled/COUNT(*) * 100.0 as Canceled_Percent
From PDS_SALES_PMI a INNER JOIN CTE
on a.AgentID = CTE.AgentID
and a.UserID = CTE.UserID
Where SaleDate >=DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-6, 0)
AND SaleDate < DATEADD(MONTH, DATEDIFF(MONTH, -6, GETDATE())-6, 0)
AND SaleDate >='2019-01-01'
AND Leaver = 0
Group by a.UserID, a.AgentID
Subquery Example
Select a.UserID
,a.AgentID
,Canceled/COUNT(*) * 100.0 as Canceled_Percent
From PDS_SALES_PMI a INNER JOIN (
Select UserID
,Agent
,COUNT(*) as Canceled
from PDS_SALES_PMI
where SaleDate >=DATEADD(MONTH, DATEDIFF(MONTH, 0,GETDATE())-6, 0)
AND SaleDate < DATEADD(MONTH, DATEDIFF(MONTH, -6, GETDATE())-6, 0)
AND LiveAtCutOff_PC='0'
AND SaleDate >='2019-01-01'
AND Leaver = 0
group by UserID, AgentID) as Tmp
on a.AgentID = Tmp.AgentID
and a.UserID = Tmp.UserID
Where SaleDate >=DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())-6, 0)
AND SaleDate < DATEADD(MONTH, DATEDIFF(MONTH, -6, GETDATE())-6, 0)
AND SaleDate >='2019-01-01'
AND Leaver = 0
Group by a.UserID, a.AgentID

Use a date based on field value

I need to find a way to relate two sets of orders. Essentially, and inbound versus outbound analysis for a report. A load balance to see when I need to organize more pickups or deliveries.
I need to pull the delivery_date when billing_group = 3
I need to pull the origin_date when billing_group = 4
Hope this made some sense. Thank you all!
select convert(varchar,Delivery_Date,101) as 'Delivery_Date',
convert(varchar,Origin_Date,101) as 'Origin_Date',
sum(case when billing_group = '3' then 1 else 0 end) as 'OR to WA',
sum(case when billing_group = '4' then 1 else 0 end) as 'WA to OR',
count(*) as Total_Orders
from orders
where Date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0) and
billing_group in ('3','4')
group by Date
order by date desc
Would it be possible to combine these two separate queries into one to provide a the following columns? date, OR to WA, and WA to OR (like in the example above) where the date (regardless of origin or delivery date is used
select convert(varchar,Delivery_Date,101) as 'Date',
sum(case when billing_group = '3' and delivery_date >= dateadd(day,datediff(day, 0, GetDate()) - 30, 0) then 1 else 0 end) as 'OR to WA'
from orders
where delivery_Date >= dateadd(day, datediff(day, 0, GetDate()) - 20, 0) and billing_group in ('3')
group by delivery_date
order by date desc
select convert(varchar,Origin_Date,101) as 'Date',
sum(case when billing_group = '4' and origin_date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0)then 1 else 0 end) as 'WA to OR'
from orders
where origin_Date >= dateadd(day, datediff(day, 0, GetDate()) - 20, 0) and billing_group in ('4')
group by origin_Date
order by date desc
I think you need to group by convert(varchar,Delivery_Date,101) instead of date.
When you use aggregate function you need to add non-aggregate colunms in group by.
select convert(varchar,Delivery_Date,101) as 'Delivery_Date',
sum(case when billing_group = '3' then 1 else 0 end) as 'OR to WA',
sum(case when billing_group = '4' then 1 else 0 end) as 'WA to OR',
count(*) as Total_Orders
from orders
where Date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0) and
billing_group in ('3','4')
group by convert(varchar,Delivery_Date,101)
order by date desc
EDIT
I saw you edit your question, you can try to use UNION ALL
SELECT * FROM (
select convert(varchar,Delivery_Date,101) as 'Date',
sum(case when billing_group = '3' and delivery_date >= dateadd(day,datediff(day, 0, GetDate()) - 30, 0) then 1 else 0 end) as 'OR to WA'
from orders
where delivery_Date >= dateadd(day, datediff(day, 0, GetDate()) - 20, 0) and billing_group in ('3')
group by delivery_date
UNION ALL
select convert(varchar,Origin_Date,101) as 'Date',
sum(case when billing_group = '4' and origin_date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0)then 1 else 0 end) as 'WA to OR'
from orders
where origin_Date >= dateadd(day, datediff(day, 0, GetDate()) - 20, 0) and billing_group in ('4')
group by origin_Date
) t1
ORDER BY Date desc

Combine queries to show one set of results

I have two separate queries where I need to match up and combine together based on a date value.
select convert(varchar,Delivery_Date,101) as 'Date',
sum(case when billing_group = '3' and delivery_date >= dateadd(day,datediff(day, 0, GetDate()) - 30, 0) then 1 else 0 end) as 'OR to WA'
from orders
where delivery_Date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0) and billing_group in ('3')
group by delivery_date
order by date desc
select convert(varchar,Origin_Date,101) as 'Date',
sum(case when billing_group = '4' and origin_date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0)then 1 else 0 end) as 'WA to OR'
from orders
where origin_Date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0) and billing_group in ('4')
group by origin_Date
order by date desc
Please note that I am using a different date value (delivery_date) in the first query and a different for the second (origin_date)
Thanks for the help!!
I think you just want conditional aggregation, but your query offers other room for improvement:
select convert(varchar(255), v.thedate, 101) as [Date],
sum(case when o.billing_group = 3 then 1 else 0 end) as [OR to WA],
sum(case when o.billing_group = 4 then 1 else 0 end) as [WA to OR]
from orders o cross apply
(values (case when o.billing_group = 3 then delivery_date else o.origin_date end)
) v(the_date)
where v.thedate >= dateadd(day, -30, cast(getdate() as date)) and
o.billing_group in (3, 4)
group by convert(varchar(255), v.thedate, 101)
order by v.thedate desc
Notes:
Never use varchar() without a length parameter. The length varies by context and it might not do what you expect.
I am guessing that billing_group is a number. If so, don't use single quotes. Do use single quotes if I'm wrong.
I cannot tell what the data type of delivery_date is. It is safer to aggregate by the full expression, rather than just the column.
Do not use single quotes for column aliases. Only use single quotes for string and date constants.
There is no reason to use the "trick" of adding days to 0 to remove a time component. Instead, just convert to date.
The condition on delivery_date does not have to appear in both the case expression and the where clause.
Try using UNION and adding the missing columns
then do group by and ordering
select * from (
convert(varchar,Delivery_Date,101) as 'Date',
sum(case when billing_group = '3' and delivery_date >= dateadd(day,datediff(day, 0, GetDate()) - 30, 0) then 1 else 0 end) as 'OR to WA',
0 as 'WA to OR'
from orders
where delivery_Date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0) and billing_group in ('3')
-- group by delivery_date
--- order by date desc
UNION
select convert(varchar,Origin_Date,101) as 'Date',
0 as 'OR to WA'
sum(case when billing_group = '4' and origin_date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0)then 1 else 0 end) as 'WA to OR'
from orders
where origin_Date >= dateadd(day, datediff(day, 0, GetDate()) - 30, 0) and billing_group in ('4')
--group by origin_Date
--order by date desc
) group by [Date]
order by [Date] desc

SQL Group by month and join

I have 3 different queries and need to find a way to display results in a single gridview, but this way is creating 3 different grids.
My code is this and try to find a way to join in a sinlge one with rows showing months and columns showing "Laptop", "Pc" and "Total".
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0) AS MyMonth, COUNT(stb_group) AS Laptop
FROM inventary
WHERE (activation_date > '10-01-2013') AND (stb_group = 'Laptop')
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0)
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0) AS MyMonth, COUNT(stb_group) AS PC
FROM inventary
WHERE (activation_date > '10-01-2013') AND (stb_group = 'PC')
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0)
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0) AS MyMonth, COUNT(stb_group) AS Units
FROM inventary
WHERE (activation_date > '10-01-2013')
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0)
Try this
SELECT DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0) AS MyMonth,
COUNT(case when stb_group = 'Laptop' then stb_group end) AS Laptop,
COUNT(case when stb_group = 'PC' then stb_group end) AS PC,
COUNT(stb_group) AS Units
FROM inventary
WHERE (activation_date > '10-01-2013')
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, activation_date), 0)