Simply SQL query - sql

I have a SQL script and would like to have multiple counts depending on different where clauses, instead of repeating such as this is there a way I can simplify this?
select
UnverifiedEmails =
(
select count(distinct c.ContactRef)
from ContactEmailAddressVerification c
LEFT JOIN EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID
WHERE DateVerified IS NULL
),
VerifiedEmails =
(
select count(distinct c.ContactRef)
from ContactEmailAddressVerification c
LEFT JOIN EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID
WHERE DateVerified IS NOT NULL
),
LastMonthVerified =
(
select count(distinct c.ContactRef)
from GDPR_ContactEmailAddressVerification c
LEFT JOIN EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID
WHERE DateVerified IS NOT NULL
AND DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, getdate()))
),
LastMonthUnverified =
(
select count(distinct c.ContactRef)
from ContactEmailAddressVerification c
LEFT JOIN EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID
WHERE DateVerified IS NULL
AND DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, getdate()))
)

You can do aggregation with single SELECT statement :
SELECT COUNT(DISTINCT CASE WHEN DateVerified IS NULL THEN c.ContactRef END) UnverifiedEmails,
COUNT(DISTINCT CASE WHEN DateVerified IS NOT NULL THEN c.ContactRef END) VerifiedEmails,
COUNT(DISTINCT CASE WHEN (DateVerified IS NOT NULL AND
DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, getdate()))
)
THEN c.ContactRef
END) LastMonthVerified,
COUNT(DISTINCT CASE WHEN (DateVerified IS NULL AND
DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, getdate()))
)
THEN c.ContactRef
END) LastMonthUnverified
FROM ContactEmailAddressVerification c LEFT JOIN
EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID;

You may use conditional aggregation:
SELECT
COUNT(DISTINCT CASE WHEN DateVerified IS NULL
THEN c.ContactRef END) AS UnverifiedEmails,
COUNT(DISTINCT CASE WHEN DateVerified IS NOT NULL
THEN c.ContactRef END) AS VerifiedEmails,
COUNT(DISTINCT CASE WHEN DateVerified IS NOT NULL AND
DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, GETDATE()))
THEN c.ContactRef END) AS LastMonthVerified,
COUNT(DISTINCT CASE WHEN DateVerified IS NULL AND
DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, GETDATE()))
THEN c.ContactRef END) AS LastMonthUnverified
FROM ContactEmailAddressVerification c
LEFT JOIN EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID;
The idea here is to make a single pass over the joined tables, and then take counts/sums conditionally, depending on the logic in each of the WHERE clauses of your original query.

use case when don't need multiple sub-query
select count(distinct case when DateVerified IS NULL then c.ContactRef end) UnverifiedEmails ,
count(distinct case when DateVerified IS not NULL then c.ContactRef end) VerifiedEmails,
count(distinct case when DateVerified IS NOT NULL
AND DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, getdate()))
then c.ContactRef end ) LastMonthVerified,
count(distinct case when DateVerified IS NULL
AND DATEPART(m, e.DateAdded) = DATEPART(m, DATEADD(m, -1, getdate()))
then c.ContactRef end) LastMonthUnverified
from ContactEmailAddressVerification c
LEFT JOIN EmailAddressVerification e
ON e.EmailAddressVerificationID = c.EmailAddressVerificationID

Related

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 counting based on date comparison

I've got the following SQL query which gives me all of my assets which are older than two years, broken down by organization. Then I have to run it again and just remove the date comparison part in the WHERE clause to find out my total number of assets, so I can give a count of old, a count of total, and then a % old.
Is there a way to do this all as a single query? I'm thinking some type of case statement in the query maybe?
SELECT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, COUNT(DISTINCT a.LabAssetSerialNbr) TotalAssets
FROM vw_DimLabAsset a
INNER JOIN vw_DimWorker w ON w.WorkerKey = a.LabAssetAssignedToWorkerKey
INNER JOIN vw_DimOrganizationHierarchy o ON o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
WHERE a.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0)
AND a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
AND a.LabAssetHardwareStatus <> 'retired'
AND (a.LabAssetHardwareSubStatus IS NULL OR a.LabAssetHardwareSubStatus <> 'archive')
GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm
ORDER BY 1, 2
I tried adding this to the select: `
SUM(CASE WHEN a.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END)
but that doesn't return the same count as the TotalAssets value.
Update
Here's the final query I ended up with:
DECLARE #date DateTime
SELECT #date = DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0);
WITH pphw AS
(
SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr, MIN(a.SystemCreatedOnDtm) MinCreated
FROM vw_DimLabAsset a
INNER JOIN vw_DimWorker w ON a.LabAssetAssignedToWorkerKey = w.WorkerKey
INNER JOIN vw_DimOrganizationHierarchy o ON w.WorkerOrganizationUnitCd = o.OrganizationHierarchyUnitCd
AND o.OrganizationHierarchyUnitLevelThreeNm IS NOT NULL
AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
WHERE LabAssetHardwareStatus <> 'Retired'
AND (LabAssetHardwareSubStatus IS NULL OR LabAssetHardwareSubStatus <> 'Archive')
AND a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
)
SELECT OrganizationHierarchyUnitLevelThreeNm, OrganizationHierarchyUnitLevelFourNm,
SUM(CASE WHEN MinCreated < #date THEN 1 ELSE 0 END) AssetsOverTwoYears,
COUNT(DISTINCT LabAssetSerialNbr) TotalAssets
FROM pphw
GROUP BY OrganizationHierarchyUnitLevelThreeNm, OrganizationHierarchyUnitLevelFourNm
HAVING SUM(CASE WHEN MinCreated < #date THEN 1 ELSE 0 END) > 0
ORDER BY 1, 2
My answer is similar to tysonwright, but I think the GROUP BY clause should be outside of the sub-select. But, I would want sample data to validate this. The bottom line is that you should first gather all of the records that you want calculate metrics on via a sub-select. From there, you can perform your SUMs and COUNTs.
SELECT TMP1.OrganizationHierarchyUnitLevelThreeNm
,TMP1.OrganizationHierarchyUnitLevelFourNm
,TotalAssets = COUNT(TMP1.LabAssetSerialNbr)
,AssetsOver2YearsOld = SUM(TMP1.AssetOver2YearsOldInd)
,PercAssetsOver2YearsOld = SUM(TMP1.AssetOver2YearsOldInd) / COUNT(TMP1.LabAssetSerialNbr)
FROM (SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
,AssetOver2YearsOldInd = CASE WHEN a.SystemCreatedOnDtm < DATEADD(d, DATEDIFF(d, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END
FROM vw_DimLabAsset a
INNER JOIN vw_DimWorker w
ON w.WorkerKey = a.LabAssetAssignedToWorkerKey
INNER JOIN vw_DimOrganizationHierarchy o
ON o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
WHERE a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
AND a.LabAssetHardwareStatus <> 'retired'
AND (a.LabAssetHardwareSubStatus IS NULL
OR a.LabAssetHardwareSubStatus <> 'archive')
) TMP1
GROUP BY TMP1.OrganizationHierarchyUnitLevelThreeNm, TMP1.OrganizationHierarchyUnitLevelFourNm
ORDER BY 1, 2
Update:
To remove the duplicates by date time, you can use either the MIN or MAX function, depending one what your requirement is:
SELECT TMP1.OrganizationHierarchyUnitLevelThreeNm
,TMP1.OrganizationHierarchyUnitLevelFourNm
,TotalAssets = COUNT(TMP1.LabAssetSerialNbr)
,AssetsOver2YearsOld = SUM(CASE WHEN TMP1.MaxSystemCreatedOnDtm < DATEADD(d, DATEDIFF(d, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END)
,PercAssetsOver2YearsOld = SUM(CASE WHEN TMP1.MaxSystemCreatedOnDtm < DATEADD(d, DATEDIFF(d, 0, DATEADD(yy, -2, GETDATE())), 0) THEN 1 ELSE 0 END) / COUNT(TMP1.LabAssetSerialNbr)
FROM (SELECT DISTINCT o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr, MaxSystemCreatedOnDtm = MAX(a.SystemCreatedOnDtm)
FROM vw_DimLabAsset a
INNER JOIN vw_DimWorker w
ON w.WorkerKey = a.LabAssetAssignedToWorkerKey
INNER JOIN vw_DimOrganizationHierarchy o
ON o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
AND o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
WHERE a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
AND a.LabAssetHardwareStatus <> 'retired'
AND (a.LabAssetHardwareSubStatus IS NULL
OR a.LabAssetHardwareSubStatus <> 'archive')
GROUP BY o.OrganizationHierarchyUnitLevelThreeNm, o.OrganizationHierarchyUnitLevelFourNm, a.LabAssetSerialNbr
) TMP1
GROUP BY TMP1.OrganizationHierarchyUnitLevelThreeNm, TMP1.OrganizationHierarchyUnitLevelFourNm
ORDER BY 1, 2
I think this will get you what you need:
SELECT
s.OrganizationHierarchyUnitLevelThreeNm,
s.OrganizationHierarchyUnitLevelFourNm,
COUNT(*) TotalAssets,
SUM(CASE WHEN s.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0)
THEN 1 ELSE 0 END) AssetsOver2YearsOld,
SUM(CASE WHEN s.SystemCreatedOnDtm < DATEADD(day, DATEDIFF(day, 0, DATEADD(yy, -2, GETDATE())), 0)
THEN 1 ELSE 0 END) / COUNT(*) PercAssetsOver2YearsOld
FROM
(
SELECT
o.OrganizationHierarchyUnitLevelThreeNm,
o.OrganizationHierarchyUnitLevelFourNm
a.LabAssetSerialNbr,
a.SystemCreatedOnDtm
FROM
vw_DimLabAsset a
INNER JOIN
vw_DimWorker w
ON
w.WorkerKey = a.LabAssetAssignedToWorkerKey
INNER JOIN
vw_DimOrganizationHierarchy o
ON
o.OrganizationHierarchyUnitCd = w.WorkerOrganizationUnitCd
AND
o.OrganizationHierarchyUnitLevelFourNm IS NOT NULL
WHERE
a.LabAssetTypeNm IN ('u_cmdb_ci_prototype_system', 'u_cmdb_ci_silicon')
AND
a.LabAssetHardwareStatus <> 'retired'
AND
(a.LabAssetHardwareSubStatus IS NULL OR a.LabAssetHardwareSubStatus <> 'archive')
GROUP BY
o.OrganizationHierarchyUnitLevelThreeNm,
o.OrganizationHierarchyUnitLevelFourNm
a.LabAssetSerialNbr,
a.SystemCreatedOnDtm
) AS s

Average in SSRS

I am having some issues with an avg subquery in my report. I am trying to get the count(distinct(d.orderno)) value AND the avg(count(distinct(d.orderno))) value so that way I can get a comparison into a percentage between the count and the average, but it is simply not working. Please take a look at my code:
SELECT
d.packingoperator,
d.packingunit,
datepart(hh, d.datetimepacked) as hourPacked,
avg(count(distinct(d.orderno))) as targetrate,
count(distinct(d.orderno)) as orderspacked,
(select count(distinct(d1.orderno))
from mck_hvs.oldorderdetails d1 with (nolock)
where d1.refrigerate != 'N'
and convert(date, d1.datetimepacked) = convert(date, #date)
and d1.packingoperator = d.packingoperator
and datepart(hh, d1.datetimepacked) = datepart(hh,d.datetimepacked)) as coldcount
FROM
mck_hvs.oldorderdetails d with (nolock)
WHERE
convert(date, d.datetimepacked) = convert(date, #date)
GROUP BY
d.packingoperator,
datepart(hh, d.datetimepacked),
d.packingunit
ORDER BY
d.packingoperator,
datepart(hh, d.datetimepacked)
I have also tried this option as well:
SELECT
d.packingoperator,
d.packingunit,
datepart(hh, d.datetimepacked) as hourPacked,
count(distinct(d.orderno)) as orderspacked,
(select count(distinct(d1.orderno))
from mck_hvs.oldorderdetails d1 with (nolock)
where d1.refrigerate != 'N'
and convert(date, d1.datetimepacked) = convert(date, #date)
and d1.packingoperator = d.packingoperator
and datepart(hh, d1.datetimepacked) = datepart(hh,d.datetimepacked)) as coldcount,
(select avg(target) from (
select count(distinct(d2.orderno)) as target
from mck_hvs.oldorderdetails d2 with( nolock )
where convert(date, d2.datetimepacked) = convert(date, #date)
and d2.packingoperator = d.packingoperator
and datepart(hh, d2.datetimepacked) = datepart(hh, d.datetimepacked)) as targetrate
FROM
mck_hvs.oldorderdetails d with (nolock)
WHERE
convert(date, d.datetimepacked) = convert(date, #date)
GROUP BY
d.packingoperator,
datepart(hh, d.datetimepacked),
d.packingunit
ORDER BY
d.packingoperator,
datepart(hh, d.datetimepacked)
Have you thought about breaking out some of your sub-aggregations into cross-applies? Please see below. This is very very inelegant code, however it might be able to get you on the right track.
SELECT
d.packingoperator,
d.packingunit,
DATEPART(hh, d.datetimepacked) as hourPacked,
AVG(ct.orderNoCt) as targetrate,
COUNT(dt.orderNoDt) as orderspacked,
(
SELECT
COUNT(DISTINCT(d1.orderno))
FROM mck_hvs.oldorderdetails d1 with (NOLOCK)
where d1.refrigerate != 'N'
and CONVERT(date, d1.datetimepacked) = CONVERT(date, #date)
and d1.packingoperator = d.packingoperator
and DATEPART(hh, d1.datetimepacked) = DATEPART(hh,d.datetimepacked)
) as coldcount
FROM
mck_hvs.oldorderdetails d with (nolock)
CROSS APPLY
(
SELECT
COUNT(DISTINCT d2.orderNo) as orderNoCt
FROM mck_hvs.oldorderdetails d2 with (nolock)
WHERE
d2.packingoperator = d.packingoperator
AND d2.packingunit = d.packingunit
and DATEPART(hh, d2.datetimepacked) = DATEPART(hh, d.datetimepacked)
) ct
CROSS APPLY
(
SELECT
DISTINCT d3.orderNo as orderNoDt
FROM mck_hvs.oldorderdetails d3 with (nolock)
WHERE
d3.packingoperator = d.packingoperator
AND d3.packingunit = d.packingunit
and DATEPART(hh, d3.datetimepacked) = DATEPART(hh, d.datetimepacked)
) dt
WHERE
CONVERT(DATE, d.datetimepacked) = CONVERT(DATE, #date)
GROUP BY
d.packingoperator
,DATEPART(hh, d.datetimepacked)
,d.packingunit
ORDER BY
d.packingoperator
,DATEPART(hh, d.datetimepacked)

Finding the difference in dates in a single field

So I have the following columns in a table in our database here is an example.....
Transaction_Date | Trans_Code
1/1/2015 | JR
1/15/2015 | CP01
So I am trying to find the difference between the invoice date (JR) and the payment date (CP01). What is the best way to go about this? I tried to do a sub select but that didn't work.
Here is something else I tried with the below suggestion
Select
INVC_NUMB,
CUST_NUMB,
DATEDIFF (
DAY,
MAX(CASE WHEN TRANS_CODE = 'JR' THEN CONVERT(CHAR(10), DATEADD(d, TRANS_RDAT +5843, 0), 101) END),
MAX(CASE WHEN TRANS_CODE = 'CP01' THEN CONVERT(CHAR(10), DATEADD(d, TRANS_RDAT +5843, 0), 101) END)
) AS DAYDIFF
FROM AR20
WHERE CONVERT(CHAR(10), DATEADD(d, TRANS_RDAT +5843, 0), 112) > 20141231
GROUP BY
INVC_NUMB,
CUST_NUMB,
CONVERT(CHAR(10), DATEADD(d, TRANS_RDAT +5843, 0), 1)
ORDER BY
CONVERT(CHAR(10), DATEADD(d, TRANS_RDAT +5843, 0), 1)
One method is conditional aggregation:
select datediff(day,
max(case when trans_code = 'JR' then transaction_date end),
max(case when trans_code = 'CP01' then transaction_date end)
) as diff
from t;

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