SQL Group by month and join - sql

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)

Related

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

Remove old records based on date SQL

Here is my query
SELECT
cf.CLIENTID, p.Id as ProfileID, t.TITLEDESC as Title,
cf.ClntForenme as Name, cf.CLNTSURNME as Surname,
pm.Lender, pm.Product, pm.LenderReference,
pm.AmountRequested as LoanAmount,
pm.DateCompleted,
CASE
WHEN pm.DateCompleted BETWEEN (SELECT DATEADD(YEAR, -1, GETDATE())) AND GETDATE()
THEN 'Completed under a year ago'
WHEN pm.DateCompleted BETWEEN (SELECT DATEADD(YEAR, -2, GETDATE())) AND (SELECT DATEADD(YEAR, -1, GETDATE()))
THEN 'Backlog WOM 1 Year'
WHEN pm.DateCompleted BETWEEN (SELECT DATEADD(YEAR, -3, GETDATE())) AND (SELECT DATEADD(YEAR, -2, GETDATE()))
THEN 'Backlog WOM 2 Year'
WHEN pm.DateCompleted BETWEEN (SELECT DATEADD(YEAR, -4, GETDATE())) AND (SELECT DATEADD(YEAR, -3, GETDATE()))
THEN 'Backlog WOM 3 Year'
ELSE ''
END Source,
CASE
WHEN pm.Id > 0 THEN 'Check Perspectiove for ERC'
ELSE ''
END ERC,
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ID
FROM
tbl_Profile as p
INNER JOIN
tbl_Profile_Mortgage as pm ON p.id = pm.FK_ProfileId
LEFT JOIN
tbl_ClientFile as cf ON p.ClientId = cf.CLIENTID
LEFT JOIN
[dbo].tbl_DDTitles as t ON cf.CLNTTITLE = t.titleid
WHERE
pm.MortgageStatus = 7
AND p.CaseTypeId = 1
AND pm.DateCompleted BETWEEN (SELECT DATEADD(YEAR, -4, GETDATE())) AND GETDATE()
This query returns 990 records.
Some clients will have multiple profiles (ProfileID) what I want to do is only show me the ProfileID with the latest DateCompleted.
So, for instance, I have a clientID of 5566 this client has 3 profiles each with there own Datecompleted i only want to see the last profiles information based on Datecompleted.
Any help would be much appreciated.
Cheers
One option for you is to partition your data by client, profile, then check which datecompleted is the greatest value (aka whichever ones have a DateRank of 1). Then just select those that have that value as 1.
select * from
(
SELECT cf.CLIENTID ,p.Id as ProfileID,t.TITLEDESC as Title,cf.ClntForenme as Name,cf.CLNTSURNME as Surname,pm.Lender,pm.Product,pm.LenderReference,pm.AmountRequested as LoanAmount,
pm.DateCompleted,
CASE
WHEN pm.DateCompleted BETWEEN (select dateadd(year, -1, getdate())) AND getdate() THEN 'Compelted Under a year ago'
WHEN pm.DateCompleted BETWEEN (select dateadd(year, -2, getdate())) AND (select dateadd(year, -1, getdate())) THEN 'Backlog WOM 1 Year'
WHEN pm.DateCompleted BETWEEN (select dateadd(year, -3, getdate())) AND (select dateadd(year, -2, getdate())) THEN 'Backlog WOM 2 Year'
WHEN pm.DateCompleted BETWEEN (select dateadd(year, -4, getdate())) AND (select dateadd(year, -3, getdate())) THEN 'Backlog WOM 3 Year'
ELSE ''
END Source,
CASE
WHEN pm.Id > 0 THEN 'Check Perspectiove for ERC'
ELSE ''
END ERC,
ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS ID,
ROW_NUMBER() OVER (Partition by CLIENTID, ProfileID order by DateCompleted desc) as DateRank --Changes here
FROM tbl_Profile as p
INNER JOIN tbl_Profile_Mortgage as pm
ON p.id = pm.FK_ProfileId
LEFT JOIN tbl_ClientFile as cf
ON p.ClientId = cf.CLIENTID
LEFT JOIN [dbo].tbl_DDTitles as t on cf.CLNTTITLE = t.titleid
WHERE pm.MortgageStatus = 7 and p.CaseTypeId = 1
AND pm.DateCompleted between (select dateadd(year, -4, getdate())) AND getdate()
) clientinfo
where clientinfo.DateRank = 1

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

How to improve the performance of this query that spans across multiple databases?

here is my query taking nearly 20 mins. pls suggest me changes to increase performance
SELECT DISTINCT
CONVERT(varchar(10),x.notice_date,120) Date,
Y.branch_name,
count(case when x.status='broken' and x.branch_name=y.branch_name then 1 end)
Broken,
count(case when x.type='Lote' and x.branch_name=y.branch_name then 1 end)
Lost,
( SELECT COUNT(A.car_no)
FROM DB2.dbo.z_mat A
WHERE DateAdd(Day, DateDiff(Day, 0,a.notice_date), 0)
= DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
AND a.branch_name=y.branch_name
) mat,
( SELECT COUNT(B.car_no)
FROM DB2.dbo.z_cat B
WHERE DateAdd(Day, DateDiff(Day, 0,b.notice_date), 0)
= DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
AND b.branch_name=y.branch_name
) cat,
( SELECT COUNT(C.car_no)
FROM DB2.dbo.z_pat C
WHERE DateAdd(Day, DateDiff(Day, 0,c.notice_date), 0)
= DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
AND c.branch_name=y.branch_name
) pat
FROM DB1.dbo.Cars x
, DB2.dbo.Branch Y
WHERE DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
> '2011-01-01'
GROUP BY CONVERT(varchar(10),x.notice_date,120)
, DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)
, y.branch_name
This might help. Give it a try.
SELECT
DISTINCT CONVERT(VARCHAR(10), car.notice_date, 120) AS NoticeDate
, brc.branch_name
, COUNT(CASE WHEN car.status = 'broken' AND car.branch_name = brc.branch_name THEN 1 END) Broken
, COUNT(CASE WHEN car.status = 'Lote' AND car.branch_name = brc.branch_name THEN 1 END) Lost
, mat.mat_count
, cat.cat_count
, pat.pat_count
FROM DB1.dbo.Cars car
, DB2.dbo.Branch brc
CROSS APPLY (
SELECT COUNT(mat.car_no) mat_count
FROM DB2.dbo.z_mat mat
WHERE DATEDIFF(d, mat.notice_date, car.notice_date) = 0
AND mat.branch_name = brc.branch_name
) mat
CROSS APPLY (
SELECT COUNT(cat.car_no) cat_count
FROM DB2.dbo.z_cat cat
WHERE DATEDIFF(d, cat.notice_date, car.notice_date) = 0
AND cat.branch_name = brc.branch_name
) cat
CROSS APPLY (
SELECT COUNT(pat.car_no) pat_count
FROM DB2.dbo.z_pat pat
WHERE DATEDIFF(d, pat.notice_date, car.notice_date) = 0
AND pat.branch_name = brc.branch_name
) pat
WHERE car.notice_date > '2011-01-01'
GROUP BY CONVERT(VARCHAR(10), car.notice_date, 120)
, brc.branch_name
SELECT CONVERT(varchar(10),x.notice_date,120) Date,Y.branch_name,
COUNT(case when x.status='broken' then 1 end) Broken,
COUNT(case when x.type='Lote' then 1 end) Lost,
SUM(mat) mat, SUM(cat) cat,SUM(pat) pat
FROM DB1.dbo.Cars x
JOIN DB2.dbo.Branch Y ON x.branch_name=y.branch_name
-- group by date and branch name for z_mat table
LEFT JOIN (select COUNT(car_no) mat,branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) notice_date from DB2.dbo.z_mat GROUP BY branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) AS a
ON a.branch_name = y.branch_name AND DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) = a.notice_date
-- group by date and branch name for z_cat table
LEFT JOIN (select COUNT(car_no) cat,branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) notice_date from DB2.dbo.z_cat GROUP BY branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) AS b
ON b.branch_name = y.branch_name AND DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) = b.notice_date
-- group by date and branch name for z_pat table
LEFT JOIN (select COUNT(car_no) pat,branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) notice_date from DB2.dbo.z_pat GROUP BY branch_name,DateAdd(Day, DateDiff(Day,notice_date), 0)) AS c
ON c.branch_name = y.branch_name AND DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0) = c.notice_date
WHERE DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0)>'2011-01-01'
GROUP BY CONVERT(varchar(10),x.notice_date,120),DateAdd(Day, DateDiff(Day, 0,x.notice_date), 0),y.branch_name