Join CTE Tables SQL Sever - sql

I have the below CTE table that I am joining to various employee data using clockin dates and times for each employee in the table. I need to join this table TACLO onto the CTE so that the query returns the data matched to the dates on the CTE table, however when I try inner, outer, left or right joins only the records which have a clockin on the matched days appear, but I need to see both.
How can I get this?
DECLARE #Start DATE = '2018-1-1', #End DATE = GETDATE()
;WITH
dates AS
( SELECT thedate = #Start
UNION ALL
SELECT dateadd(day,1,dates.thedate)
FROM dates
WHERE dateadd(day,1,dates.thedate) <= #End)
select distinct cast(a.DET_NUMBER as varchar) as 'Frontier ID',
e.CDN_CARD_ID,
CONCAT (a.DET_G1_NAME1,' ',a.DET_SURNAME) as 'Name',
c.POS_TITLE as 'Position',
c.POS_L3_CD as 'Department',
c.POS_L4_CD as 'Department 2',
cast(a.DET_DATE_JND as date) as 'Start Date',
cast(b.TER_DATE as date) as 'Leaving Date',
CONCAT (d.DET_G1_NAME1,' ',d.DET_SURNAME) as 'Team Manager',
f.CLO_DATE2,
min(f.CLO_TIME2) over (partition by f.CLO_DATE2,e.CDN_CARD_ID) as earliest_time,
max(f.CLO_TIME2) over (partition by f.CLO_DATE2,e.CDN_CARD_ID) as latiest_time, q.thedate
from EMDET a
left outer join EMTER b on a.DET_NUMBER = b.DET_NUMBER
left outer join EMPOS c on a.DET_NUMBER = c.DET_NUMBER
left outer join EMDET d on c.POS_MANEMPNO = d.DET_NUMBER
left outer join TACDN e on a.DET_NUMBER = e.DET_NUMBER
left outer join TACLO f on e.CDN_CARD_ID = f.CLO_CARD_NO
left outer join dates q on f.CLO_DATE2 = q.thedate
Where (b.TER_DATE is null or c.POS_END>=GETDATE()) and
c.POS_TITLE is not null and
(c.POS_END<=Cast('1992-01-01' as datetime) or c.POS_END>=GETDATE()) and q.thedate = '2019-02-13'
order by [Team Manager] asc, e.CDN_CARD_ID asc, f.CLO_DATE2 asc
OPTION (maxrecursion 0)

Related

Converting NOT in into LEFT join giving incorrect results

Please help me in converting following NOT in query to Left join as I want a date column in select clause. I have to use this query as source to Amazon quicksight. Quicksight cannot pass date paramters created in report to my source query. So I have to get date filtering condition in WHERE clause.
Not in:
SELECT DISTINCT Date(h.Created_Date) DATE, ( h.Vehicle_ID)Decline
FROM awsdatacatalog.waves.Recurring_Transaction_History h
Left JOIN awsdatacatalog.waves.Wash_Invoice wi on h.invoice_id=wi.invoice_id
WHERE Date(h.Created_Date) BETWEEN date('2021-05-01') AND date('2021-05-01')
AND h.Status IN ('Declined','DECLINED')
AND h.Vehicle_ID NOT IN (
SELECT Distinct ut.vehicle_Id
FROM awsdatacatalog.waves.Unlimited_Wash_Transaction ut
WHERE (Is_Refunded IS NULL OR CAST(Is_Refunded AS INTEGER) =0)
AND (Status ='RECURRING' or Status ='RESIGNUP')
AND DATE(DATE) BETWEEN date('2021-05-01') AND date('2021-05-01')
)
Left join query:
SELECT DISTINCT Date(h.Created_Date) DATE, ( h.Vehicle_ID)Decline
FROM awsdatacatalog.waves.Recurring_Transaction_History h
Left JOIN awsdatacatalog.waves.Wash_Invoice wi on h.invoice_id=wi.invoice_id
LEFT JOIN (
SELECT Distinct ut.vehicle_Id, DATE(DATE) DATE
FROM awsdatacatalog.waves.Unlimited_Wash_Transaction ut
WHERE (Is_Refunded IS NULL OR CAST(Is_Refunded AS INTEGER) =0)
AND (Status ='RECURRING' or Status ='RESIGNUP')
) A
ON H.Vehicle_ID = A.Vehicle_ID
AND DATE(h.Created_Date) <= A.DATE
WHERE Date(h.Created_Date) BETWEEN date('2021-05-01') AND date('2021-05-01')
AND A.Vehicle_ID IS NULL
AND A.DATE IS NULL
AND h.Status IN ('Declined','DECLINED')
ORDER BY Date(h.Created_Date) , ( h.Vehicle_ID)

Order by on a nested query

Is their a way to order this by the Time column? I am not sure how to do this. The time is the schedule and I just need it to go from the morning to the evening.
Can I just nest another select statement and use that?
Thank you.
SELECT
DoseLevel,
LastName,
FirstName,
DOB,
EMPLID,
Time,
(
SELECT v.ColorCode
FROM ABCDocumentation cd1
LEFT JOIN ABCDocumentation cd2ON cd1.ABCDocumentationID = cd2.PairID
LEFT JOIN Medicine v ON v.MedicineID = cd1.MedicineID
LEFT JOIN Manufacturers mfg ON v.MFG_Seq = mfg.MFG_Seq
WHERE cd2.ABCDocumentationID = dt.ABCDocumentationID
) AS ParentColorCode,
(
SELECT mfg.Description
FROM ABCDocumentation cd1
LEFT JOIN ABCDocumentation cd2 ON cd1.ABCDocumentationID = cd2.PairID
LEFT JOIN Medicine v ON v.MedicineID = cd1.MedicineID
LEFT JOIN Manufacturers mfg ON v.MFG_Seq = mfg.MFG_Seq
WHERE cd2.ABCDocumentationID = dt.ABCDocumentationID
) AS ParentManuDesc
FROM
(
SELECT
cd.DoseLevel,
e.LastName,
e.FirstName,
e.DOB,
cvse.EMPLID,
cvse.AdminScheduleSlotsEmployeeID,
cd.ABCDocumentationID,
cvss.Time,
cd.ModifyDate AS 'StartTime'
FROM ABCAdminSchedule cvs
LEFT JOIN ABCAdminScheduleSlots cvss ON cvs.AdminScheduleID = cvss.AdminScheduleID
LEFT JOIN ABCAdminScheduleSlotsEmployee cvse ON cvss.AdminScheduleSlotsID = cvse.AdminScheduleSlotsID
LEFT JOIN ABCDocumentation cd ON cvse.AdminScheduleSlotsEmployeeID = cd.AdminScheduleSlotsEmployeeID
LEFT JOIN Employee e ON cvse.EmplID = e.EMPLID
WHERE CAST(TIME AS Date) = CAST(GETDATE() AS Date) AND CampusID = '06'
AND cvse.AdminScheduleSlotsEmployeeID IS NOT NULL
) dt
First off, there is no need for the derived table dt, as you are not doing any further processing.
Secondly, you can combine the two correlated subqueries into one with an APPLY.
Thirdly, conversions on columns can cause performance issues, so you can change the date check to a half-open interval, converting just GETDATE().
Finally you can add at the end an ORDER BY clause to sort.
SELECT
cd.DoseLevel,
e.LastName,
e.FirstName,
e.DOB,
cvse.EMPLID,
cvss.Time,
Parent.ColorCode,
Parent.Description
FROM ABCAdminSchedule cvs
LEFT JOIN ABCAdminScheduleSlots cvss ON cvs.AdminScheduleID = cvss.AdminScheduleID
LEFT JOIN ABCAdminScheduleSlotsEmployee cvse ON cvss.AdminScheduleSlotsID = cvse.AdminScheduleSlotsID
LEFT JOIN ABCDocumentation cd ON cvse.AdminScheduleSlotsEmployeeID = cd.AdminScheduleSlotsEmployeeID
LEFT JOIN Employee e ON cvse.EmplID = e.EMPLID
OUTER APPLY
(
SELECT v.ColorCode, mfg.Description
FROM ABCDocumentation cd1
LEFT JOIN ABCDocumentation cd2ON cd1.ABCDocumentationID = cd2.PairID
LEFT JOIN Medicine v ON v.MedicineID = cd1.MedicineID
LEFT JOIN Manufacturers mfg ON v.MFG_Seq = mfg.MFG_Seq
WHERE cd2.ABCDocumentationID = dt.ABCDocumentationID
) AS Parent
WHERE TIME >= CAST(GETDATE() AS Date) AND TIME < CAST(DATEADD(day, 1, GETDATE()) AS DATE)
AND CampusID = '06'
AND cvse.AdminScheduleSlotsEmployeeID IS NOT NULL
ORDER BY TIME
please
declare #tm table (id int identity, timee time(7))
insert into #tm (timee) values ('01:05:45'),
('10:15:18'),
('14:18:59'),
('09:15:10'),
('18:19:21'),
('21:05:17')
this is a default
select * from #tm order by id
this is a, what do you need
select tm.*,
iif(tm.part_time = 1, 'morning', 'evening') m_e from (select
case
when timee between '09:00:00' and '19:00:00' then 1
else 2 end part_time,
*
from #tm) tm
order by part_time, timee

Count with row_number function SQL CTE

I have the below CTEs that work perfectly, but I want to count the "cl.memb_dim_id" by "cl.post_date" but I am not sure how to do that? When adding in the count function I get an error that highlights the ' row number' so I am assuming I cant have both order and group together ????
WITH
DATES AS
(
select to_date('01-jan-2017') as startdate,to_date('02-jan-2017') as enddate
from dual
),
Claims as (select distinct
cl.memb_dim_id,
row_number () over (partition by cl.Claim_number order by cl.post_date desc) as uniquerow,
cl.Claim_number,
cl.post_date,
ct.claim_type,
ap.claim_status_desc,
dc.company_desc,
dff.io_flag_desc,
pr.product_desc,
cl.prov_dim_id,
cl.prov_type_dim_id
from dw.fact_claim cl
inner join dates d
on 1=1
and cl.post_date >= d.startdate
and cl.post_date <= d.enddate
and cl.provider_par_dim_id in ('2')
and cl.processing_status_dim_id = '1'
and cl.company_dim_id in ('581','585','586','589','590','591','588','592','594','601','602','603','606','596','598','597','579','599','578','577','573','574','576','575')
left join dw.DIM_CLAIM_STATUS ap
on cl.claim_status_dim_id = ap.claim_status_dim_id
left join dw.dim_claim_type ct
on cl.claim_type_dim_id = ct.claim_type_dim_id
and cl.claim_type_dim_id in ('1','2','6','7')
left join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
left join dw.DIM_IO_FLAG dff
on cl.io_flag_dim_id = dff.io_flag_dim_id
left join dw.dim_product pr
on cl.product_dim_id = pr.product_dim_id
)
Select * from claims where uniquerow ='1'
First, does this work?
count(cl.memb_dim_id) over (partition by cl.Claim_number, cl.post_date) as cnt,
Second, it is strange to be using analytic functions with select distinct.

Selecting top result of each category of product

Below query is pulling back the data below.
I am trying to only return one single result for each product number, with only the highest orddate, and it related order total (ordttl) and unit cost (ucost).
Ideas on implementing? Thanks for any responses.
SELECT
ordln.pnum as 'Product Number',
prod.name as 'Product Name',
ordhd.snum,
sup.name,
ordhd.ordttl,
ORDHD.onum,
ORDHD.orddate,
ordln.ucost
FROM
scmdb.dbo.cksprodm prod (NOLOCK)
INNER JOIN scmdb.dbo.cksordln ordln (NOLOCK) on prod.pnum = ordln.pnum
INNER JOIN scmdb.dbo.cksordhd ordhd (NOLOCK) on ordhd.onum = ordln.onum
LEFT JOIN scmdb.dbo.ckssuplr sup (NOLOCK) on ordhd.snum = coalesce(sup.snum,
sup.asnum)
WHERE ordhd.orddate BETWEEN
DATEADD(month,-6,dateadd(day,datediff(day,0,getdate()),0) + '06:00') AND
GETDATE() -- order date is between 6 months ago and today.
AND ordln.pnum NOT IN (SELECT distinct PNUM
FROM scmdb.dbo.cksquohd qhd
inner join scmdb.dbo.cksquoln qln on qhd.quote = qln.quote
where qhd.qedate > GETDATE()
)
You can use row_number to rank by date and get latest date's row:
SELECT *
FROM
(
SELECT
ordln.pnum as 'Product Number',
prod.name as 'Product Name',
ordhd.snum,
sup.name,
ordhd.ordttl,
ORDHD.onum,
ORDHD.orddate,
ordln.ucost,
row_number() over (partition by ordln.pnum order by ORDHD.orddate desc) as ranking
FROM
scmdb.dbo.cksprodm prod (NOLOCK)
INNER JOIN scmdb.dbo.cksordln ordln (NOLOCK) on prod.pnum = ordln.pnum
INNER JOIN scmdb.dbo.cksordhd ordhd (NOLOCK) on ordhd.onum = ordln.onum
LEFT JOIN scmdb.dbo.ckssuplr sup (NOLOCK) on ordhd.snum = coalesce(sup.snum,
sup.asnum)
WHERE ordhd.orddate BETWEEN
DATEADD(month,-6,dateadd(day,datediff(day,0,getdate()),0) + '06:00') AND
GETDATE() -- order date is between 6 months ago and today.
AND ordln.pnum NOT IN (SELECT distinct PNUM
FROM scmdb.dbo.cksquohd qhd
inner join scmdb.dbo.cksquoln qln on qhd.quote = qln.quote
where qhd.qedate > GETDATE()
)
) t
where ranking = 1

Inner join that ignore singlets

I have to do an self join on a table. I am trying to return a list of several columns to see how many of each type of drug test was performed on same day (MM/DD/YYYY) in which there were at least two tests done and at least one of which resulted in a result code of 'UN'.
I am joining other tables to get the information as below. The problem is I do not quite understand how to exclude someone who has a single result row in which they did have a 'UN' result on a day but did not have any other tests that day.
Query Results (Columns)
County, DrugTestID, ID, Name, CollectionDate, DrugTestType, Results, Count(DrugTestType)
I have several rows for ID 12345 which are correct. But ID 12346 is a single row of which is showing they had a row result of count (1). They had a result of 'UN' on this day but they did not have any other tests that day. I want to exclude this.
I tried the following query
select
c.desc as 'County',
dt.pid as 'PID',
dt.id as 'DrugTestID',
p.id as 'ID',
bio.FullName as 'Participant',
CONVERT(varchar, dt.CollectionDate, 101) as 'CollectionDate',
dtt.desc as 'Drug Test Type',
dt.result as Result,
COUNT(dt.dru_drug_test_type) as 'Count Of Test Type'
from
dbo.Test as dt with (nolock)
join dbo.History as h on dt.pid = h.id
join dbo.Participant as p on h.pid = p.id
join BioData as bio on bio.id = p.id
join County as c with (nolock) on p.CountyCode = c.code
join DrugTestType as dtt with (nolock) on dt.DrugTestType = dtt.code
inner join
(
select distinct
dt2.pid,
CONVERT(varchar, dt2.CollectionDate, 101) as 'CollectionDate'
from
dbo.DrugTest as dt2 with (nolock)
join dbo.History as h2 on dt2.pid = h2.id
join dbo.Participant as p2 on h2.pid = p2.id
where
dt2.result = 'UN'
and dt2.CollectionDate between '11-01-2011' and '10-31-2012'
and p2.DrugCourtType = 'AD'
) as derived
on dt.pid = derived.pid
and convert(varchar, dt.CollectionDate, 101) = convert(varchar, derived.CollectionDate, 101)
group by
c.desc, dt.pid, p.id, dt.id, bio.fullname, dt.CollectionDate, dtt.desc, dt.result
order by
c.desc ASC, Participant ASC, dt.CollectionDate ASC
This is a little complicated because the your query has a separate row for each test. You need to use window/analytic functions to get the information you want. These allow you to do calculate aggregation functions, but to put the values on each line.
The following query starts with your query. It then calculates the number of UN results on each date for each participant and the total number of tests. It applies the appropriate filter to get what you want:
with base as (<your query here>)
select b.*
from (select b.*,
sum(isUN) over (partition by Participant, CollectionDate) as NumUNs,
count(*) over (partition by Partitipant, CollectionDate) as NumTests
from (select b.*,
(case when result = 'UN' then 1 else 0 end) as IsUN
from base
) b
) b
where NumUNs <> 1 or NumTests <> 1
Without the with clause or window functions, you can create a particularly ugly query to do the same thing:
select b.*
from (<your query>) b join
(select Participant, CollectionDate, count(*) as NumTests,
sum(case when result = 'UN' then 1 else 0 end) as NumUNs
from (<your query>) b
group by Participant, CollectionDate
) bsum
on b.Participant = bsum.Participant and
b.CollectionDate = bsum.CollectionDate
where NumUNs <> 1 or NumTests <> 1
If I understand the problem, the basic pattern for this sort of query is simply to include negating or exclusionary conditions in your join. I.E., self-join where columnA matches, but columns B and C do not:
select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
and t1.PkId != t2.PkId
and t1.category != t2.category
)
Put the conditions in the WHERE clause if it benchmarks better:
select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
)
where
t1.PkId != t2.PkId
and t1.category != t2.category
And it's often easiest to start with the self-join, treating it as a "base table" on which to join all related information:
select
[columns]
from
(select
[columns]
from
table t1
join table t2 on (
t1.NonPkId = t2.NonPkId
)
where
t1.PkId != t2.PkId
and t1.category != t2.category
) bt
join [othertable] on (<whatever>)
join [othertable] on (<whatever>)
join [othertable] on (<whatever>)
This can allow you to focus on getting that self-join right, without interference from other tables.