Use a date based on field value - sql

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

Related

How can I include more columns other than just percentage column in my sql query result?

When I use the below query I only get percentage column but I want the (buyer_id, buyer_name, created_date,total_work_orders_with_gtv_first_60_days, total_gtv_first_60_days, total_net_amount_first_60_days) to show as columns too. Would really appreciate your help please.
WITH results_cte AS (
SELECT
b.buyer_id,
b.buyer_name,
CAST(b.created_date AS DATE) AS created_date,
COALESCE(wo.total_work_orders_with_gtv_first_60_days, 0) AS total_work_orders_with_gtv_first_60_days,
COALESCE(wo.total_gtv_first_60_days, 0) AS total_gtv_first_60_days,
COALESCE(wo.total_net_amount_first_60_days, 0) AS total_net_amount_first_60_days
FROM dw.buyer b
LEFT JOIN (SELECT wo.buyer_id,
COUNT(CASE WHEN wo.gtv_date < DATEADD(DAY, 60, b.created_date) THEN wo.work_order_id ELSE NULL END) AS total_work_orders_with_gtv_first_60_days,
SUM(CASE WHEN wo.gtv_date < DATEADD(DAY, 60, b.created_date) THEN wo.gtv ELSE NULL END) AS total_gtv_first_60_days,
SUM(CASE WHEN wo.gtv_date < DATEADD(DAY, 60, b.created_date) THEN wo.net_amount ELSE NULL END) AS total_net_amount_first_60_days
FROM dw.work_order wo
JOIN dw.buyer b
ON wo.buyer_id = b.buyer_id
WHERE wo.gtv > 0
GROUP BY wo.buyer_id) wo
ON b.buyer_id = wo.buyer_id
WHERE b.buyer_segmentation = 'S - Self-Service'
AND b.status = 'Active'
AND b.created_date >= DATEADD(YEAR, -1, GETDATE())
)
SELECT (SELECT CAST(count(DISTINCT buyer_id) AS float) FROM results_cte WHERE total_work_orders_with_gtv_first_60_days > 0)
/ (SELECT CAST(count(DISTINCT buyer_id) AS float) FROM results_cte ) AS percentage

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.

SQL Server issue with select and group by with calculated columns

I have this SQL I am trying to build:
select
a.Name,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate < GETDATE()) AS Due,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate = GETDATE()) AS Today,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate = DATEADD(DAY, 1, GETDATE())) AS Expected,
(SELECT COUNT(b.PlannedCollectionDate) WHERE b.PlannedCollectionDate > DATEADD(DAY, 1, GETDATE())) AS Planned
from Centers AS a
INNER JOIN Collections AS b
ON a.Id = b.CenterId
GROUP BY a.Name
But I get an error:
Column 'Collections.PlannedCollectionDate' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I know I could do something like this:
select
a.Name,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate < GETDATE()) AS Due,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate = GETDATE()) AS Today,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate = DATEADD(DAY, 1, GETDATE())) AS Expected,
(SELECT COUNT(Id) FROM Collections WHERE CenterId = a.Id AND PlannedCollectionDate > DATEADD(DAY, 1, GETDATE())) AS Planned
from Centers AS a
But I assume that is slower because I have to do multiple selects from the same table (Collections).
So, my question is, what can I do to make my first query work? I don't think grouping by PlannedCollectionDate is right, because it will mess up my count
I think you want conditional aggregation:
select ce.Name,
SUM(CASE WHEN co.PlannedCollectionDate < GETDATE() THEN 1 ELSE 0 END) AS Due,
SUM(CASE WHEN co.PlannedCollectionDate = GETDATE() THEN 1 ELSE 0 END) AS Today,
SUM(CASE WHEN co.PlannedCollectionDate = DATEADD(DAY, 1, GETDATE()) THEN 1 ELSE 0 END) AS Expected,
SUM(CASE WHEN co.PlannedCollectionDate > DATEADD(DAY, 1, GETDATE()) THEN 1 ELSE 0 END) AS Planned
from Centers ce join
Collections co
on ce.Id = co.CenterId
group by ce.Name;
This implements what you have written. Do note the use of meaningful table aliases.
However, it will not do what you want, because GETDATE() has a time component. To fix that, convert it to a date:
select ce.Name,
SUM(CASE WHEN co.PlannedCollectionDate < CONVERT(DATE, GETDATE()) THEN 1 ELSE 0 END) AS Due,
SUM(CASE WHEN co.PlannedCollectionDate = CONVERT(DATE, GETDATE()) THEN 1 ELSE 0 END) AS Today,
SUM(CASE WHEN co.PlannedCollectionDate = DATEADD(DAY, 1, CONVERT(DATE, GETDATE())) THEN 1 ELSE 0 END) AS Expected,
SUM(CASE WHEN co.PlannedCollectionDate > DATEADD(DAY, 1, CONVERT(DATE, GETDATE())) THEN 1 ELSE 0 END) AS Planned
from Centers ce join
Collections co
on ce.Id = co.CenterId
group by ce.Name;
Note that this assumes that PlannedCollectionDate does not have a time component.

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 query - unique values with multiple condition

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