I have four select statements and I want to join them all to only get the common rows.
In an example, I'm providing 2 select statements:
SELECT
h.userid, 'Activity' as table_name,
h.stamp,
DATEDIFF(dd, kh.LatestDate, GETDATE()) as days_since,
m.group_name
FROM
([Animal].[SYSADM].[activity_history] h
INNER JOIN
(SELECT userid, MAX(stamp) as LatestDate
FROM [Animal].[SYSADM].[activity_history]
GROUP BY userid) kh ON h.userid = kh.userid AND h.stamp = kh.LatestDate)
LEFT OUTER JOIN
[Animal].[SYSADM].secure_member m ON m.user_name = h.userid
WHERE
(DATEDIFF(dd, kh.LatestDate, GETDATE()) > 90)
AND NOT (m.group_name = 'inactive')
ORDER BY
userid
SELECT
h.userid, 'Person' as table_name, h.stamp,
DATEDIFF(dd, kh.LatestDate, GETDATE()) as days_since,
m.group_name
FROM
([Animal].[SYSADM].[person_history] h
INNER JOIN
(SELECT userid, max(stamp) as LatestDate
FROM [Animal].[SYSADM].[person_history]
GROUP BY userid) kh ON h.userid = kh.userid AND h.stamp = kh.LatestDate)
LEFT OUTER JOIN
[Animal].[SYSADM].secure_member m ON m.user_name = h.userid
WHERE
(DATEDIFF(dd, kh.LatestDate, GETDATE()) > 90)
AND NOT (m.group_name = 'inactive')
ORDER BY
userid
I have tried INTERSECT, but it's not returning any rows, I want to see the common rows from both the select statements (actually I have 4 so I believe what works for 2 will work for 4)
Thanks in advance.
Update:
I tried inner join on 2 select statements and it gave me the desired result but now the question is how I can use inner join on 4 select statements.
SELECT DISTINCT t1.userid as A_UserID, t2.userid as P_UserID, t1.stamp as A_stamp, t2.stamp as P_stamp, datediff(dd,t1.stamp,GetDate()) as A_days_since, datediff(dd,t2.stamp,GetDate()) as P_days_since, t1.group_name, t1.table_name, t2.table_name
from
(SELECT h.userid, 'Activity' as table_name, h.stamp, datediff(dd,kh.LatestDate,GetDate()) as days_since, m.group_name
FROM
( [Animal].[SYSADM].[activity_history] h
inner join (
select userid, max(stamp) as LatestDate
from [Animal].[SYSADM].[activity_history]
group by userid
) kh on h.userid = kh.userid and h.stamp = kh.LatestDate
)
left outer join [Animal].[SYSADM].secure_member m on m.user_name = h.userid
where
(datediff(dd,kh.LatestDate, GetDate()) > 90)
and not (m.group_name = 'inactive')) t1
inner join
(SELECT h.userid, 'Person' as table_name, h.stamp, datediff(dd,kh.LatestDate,GetDate()) as days_since, m.group_name
FROM
( [Animal].[SYSADM].[person_history] h
inner join (
select userid, max(stamp) as LatestDate
from [Animal].[SYSADM].[person_history]
group by userid
) kh on h.userid = kh.userid and h.stamp = kh.LatestDate
)
left outer join [Animal].[SYSADM].secure_member m on m.user_name = h.userid
where
(datediff(dd,kh.LatestDate, GetDate()) > 90)
and not (m.group_name = 'inactive')) t2
on
t1.userid = t2.userid
order by T1.userid
Query Result
Forget about the UNION for a moment. Imagine you take that result and insert into Table1
Then depend what you mean the "common rows". If you want exact value but in different tables
SELECT userid, h.stamp, days_since, m.group_name
FROM Table1
GROUP BY userid, h.stamp, days_since, m.group_name
HAVING COUNT( table_name ) = 2 -- in this case 2 because are two types
-- Activity and Persons
After viewing your query result you also need to add DISTINCT to each of the queries on the UNION.
Related
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
I have the following SQL script which returns duplciate values in PIVOT. How do I combine those duplicate records to one row.
Please check the below image for the results set.
SELECT *
FROM (SELECT X.stockcode,
X.description,
X.pack,
X.location,
X.lname,
X.qty,
Y.stockcode AS StockCode2,
y.periodname,
Y.months,
Y.saleqty
FROM (SELECT dbo.stock_items.stockcode,
dbo.stock_items.description,
dbo.stock_items.pack,
dbo.stock_loc_info.location,
dbo.stock_locations.lname,
dbo.stock_loc_info.qty
FROM dbo.stock_locations
INNER JOIN dbo.stock_loc_info
ON dbo.stock_locations.locno = dbo.stock_loc_info.location
LEFT OUTER JOIN dbo.stock_items
ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
WHERE ( dbo.stock_items.status = 's' )) AS X
LEFT OUTER JOIN (SELECT dbo.dr_invlines.stockcode,
( 12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate) ) % 12 + 1 AS Months,
Sum(dbo.dr_invlines.quantity) AS SaleQty,
dbo.period_status.periodname
FROM dbo.dr_trans
INNER JOIN dbo.period_status
ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
RIGHT OUTER JOIN dbo.dr_invlines
ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode
ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno
WHERE ( STOCK_ITEMS_1.status = 'S' )
AND ( dbo.dr_trans.transtype IN ( 1, 2 ) )
AND ( dbo.dr_trans.transdate >= Dateadd(m, -6, Getdate()) )
GROUP BY dbo.dr_invlines.stockcode,
Datepart(month, dbo.dr_trans.transdate),
dbo.period_status.periodname) AS Y
ON X.stockcode = Y.stockcode) z
PIVOT (Sum(saleqty) FOR [months] IN ([1],[2],[3],[4],[5],[6])) AS pivoted
EDIT: I missed the root-cause of your issue being the inclusion of the periodname column causing the percieved duplication. I am leaving this in place as general solution showing CTE usage, because it could still be useful if you then want to do extra filtering/transformation of your pivot results
One way is to take the results of the pivot query and run it through a SELECT DISTINCT query.
An example of wrapping your pivot query as a CTE and using it to feed a SELECT DISTINCT below (please note: untested, but parses as valid in my SSMS)
WITH PivotResults_CTE (
stockcode,
description,
pack,
location,
lname,
qty,
StockCode2,
periodname,
months,
saleqty
)
AS (
SELECT *
FROM (
SELECT X.stockcode
,X.description
,X.pack
,X.location
,X.lname
,X.qty
,Y.stockcode AS StockCode2
,y.periodname
,Y.months
,Y.saleqty
FROM (
SELECT dbo.stock_items.stockcode
,dbo.stock_items.description
,dbo.stock_items.pack
,dbo.stock_loc_info.location
,dbo.stock_locations.lname
,dbo.stock_loc_info.qty
FROM dbo.stock_locations
INNER JOIN dbo.stock_loc_info ON dbo.stock_locations.locno = dbo.stock_loc_info.location
LEFT OUTER JOIN dbo.stock_items ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
WHERE (dbo.stock_items.STATUS = 's')
) AS X
LEFT OUTER JOIN (
SELECT dbo.dr_invlines.stockcode
,(12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate)) % 12 + 1 AS Months
,Sum(dbo.dr_invlines.quantity) AS SaleQty
,dbo.period_status.periodname
FROM dbo.dr_trans
INNER JOIN dbo.period_status ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
RIGHT OUTER JOIN dbo.dr_invlines ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno WHERE (STOCK_ITEMS_1.STATUS = 'S')
AND (
dbo.dr_trans.transtype IN (
1
,2
)
)
AND (dbo.dr_trans.transdate >= Dateadd(m, - 6, Getdate()))
GROUP BY dbo.dr_invlines.stockcode
,Datepart(month, dbo.dr_trans.transdate)
,dbo.period_status.periodname
) AS Y ON X.stockcode = Y.stockcode
) z
PIVOT(Sum(saleqty) FOR [months] IN (
[1]
,[2]
,[3]
,[4]
,[5]
,[6]
)) AS pivoted
)
SELECT DISTINCT *
FROM
PivotResults_CTE
;
Also note, your sql included in the above may look slightly different to your original but that is only because i ran it through a reformatter to ensure i understood the structure of it.
In other words, the basic CTE wrapper for your pivot query is:
WITH PivotResults_CTE (
Field1,
Field2,
...
)
AS (
YOUR_PIVOT_QUERY_HERE
)
SELECT DISTINCT *
FROM
PivotResults_CTE
;
I have a query
SELECT *
FROM Stops
WHERE CustomerID IN (SELECT ID FROM Customers WHERE Active = 1)
AND DriverID IS NOT NULL
AND TripID IN (SELECT ID
FROM Trips
WHERE ManagerID IN (SELECT ID FROM Users WHERE Active = 1)
AND AssignedToID IN (SELECT ID FROM Users WHERE Active = 1)
AND Modified > DATEADD(day, -60, GETDATE()))
I tried to convert to Join but I am stuck
SELECT *
FROM Stops S
JOIN Customers C ON C.ID = S.CustomerID
JOIN Trips T ON S.TripID = T.ID
WHERE C.ACTIVE = 1
AND S.DriverID IS NOT NULL
AND T.Modified > DATEADD(day, -60, GETDATE())
Using all joins, no nested queries
SELECT * FROM Stops A
INNER JOIN Customers B ON A.CustomerID = B.ID
INNER JOIN Trips C ON A.TripID = C.ID
INNER JOIN Users D ON C.ManagerID = D.ID
INNER JOIN Users E ON C.AssignedToID = E.ID
WHERE A.DriverID IS NOT NULL AND
B.Active = 1 AND
D.Active = 1 AND
E.Active = 1 AND
C.Modified > DATEADD(day, -60, GETDATE());
If you want unique data of stops you can also add "DISTINCT" to the select.
you can try like below subquery and join
SELECT S.* FROM Stops S
JOIN Customers C ON C.ID=S.CustomerID
join (SELECT ID FROM Trips where
ManagerID IN (SELECT ID FROM Users WHERE Active = 1) AND
AssignedToID IN (SELECT ID FROM Users WHERE Active = 1) AND
Modified > DATEADD(day, -60, GETDATE())
) t on S.TripID=t.ID
I'm trying your second code on my end until I came up on the below code. You might try
SELECT *
FROM Stops S
JOIN Customers C ON C.ID = S.CustomerID AND C.ACTIVE = 1
JOIN Trips T ON S.TripID = T.ID AND T.Modified > DATEADD(day, -60, GETDATE())
LEFT JOIN Users U ON T.ManagerID = U.ID AND T.AssignedToID = U.ID
WHERE S.DriverID IS NOT NULL
What I usually do is to draw squares as tables and link them based on the requirements.
Though, still not sure if my answer would work since I have no idea with what you are trying to achieve on your code aside from using JOIN.
I am trying to convert the following T-SQL Select query to exclude "Exists" Clause and Include "Join" Clause. but i am ending up not getting the right result. can some one from this expert team help me with some tips.
select *
FROM HRData
INNER JOIN (
SELECT eeceeid, MIN(eecdateoftermination) eTermDate
FROM dbo.empcomp
INNER JOIN
(
SELECT xeeid FROM HRData_EEList
INNER JOIN dbo.empcomp t ON xeeid = eeceeid AND xcoid = eeccoid
WHERE eecemplstatus = 'T' AND eectermreason <> 'TRO' AND eeccoid <> 'WAON6'
AND EXISTS ( SELECT 1 FROM dbo.empded
INNER JOIN dbo.dedcode on deddedcode = eeddedcode AND deddedtype = 'MED' AND (eedbenstopdate IS NULL OR eedbenstopdate > '12/31/2005')
WHERE eedeeid = xeeid AND eedcoid = xcoid )
GROUP BY xeeid
HAVING COUNT(*) > 1) Term ON xeeid = eeceeid
group by eeceeid
) Terms ON eeid = eeceeid AND Termdate = eTermDate
The algorithm to convert EXISTS to JOIN is very simple.
Instead of
FROM A
WHERE EXISTS (SELECT *
FROM B
WHERE A.Foo = B.Foo)
Use
FROM A
INNER JOIN (SELECT DISTINCT Foo
FROM B) AS B
ON A.Foo = B.Foo
But the first one probably will be optimised better
Interesting request.
select *
FROM HRData
INNER JOIN (
SELECT eeceeid, MIN(eecdateoftermination) eTermDate
FROM dbo.empcomp
INNER JOIN
(
SELECT xeeid FROM HRData_EEList
INNER JOIN dbo.empcomp t ON xeeid = eeceeid AND xcoid = eeccoid
INNER JOIN
( SELECT DISTINCT xeeid, xcoid FROM dbo.empded
INNER JOIN dbo.dedcode on deddedcode = eeddedcode AND deddedtype = 'MED' AND (eedbenstopdate IS NULL OR eedbenstopdate > '12/31/2005')
-- WHERE eedeeid = xeeid AND eedcoid = xcoid
) AS A ON xeeid = A.xeeid AND eedcoid = A.eedcoid
WHERE eecemplstatus = 'T' AND eectermreason <> 'TRO' AND eeccoid <> 'WAON6'
GROUP BY xeeid
HAVING COUNT(*) > 1) Term ON xeeid = eeceeid
group by eeceeid
) Terms ON eeid = eeceeid AND Termdate = eTermDate
Another method of converting an exists to a join is to use a ROW_NUMBER() in the subselect to assist in removing duplicates.
EXISTS:
FROM A
WHERE EXISTS (SELECT *
FROM B
WHERE B.Condition = 'true' AND A.Foo = B.Foo)
JOIN:
FROM A
JOIN (SELECT B.Foo, ROW_NUMBER() OVER (PARTITION BY B.Foo ORDER BY B.Foo) RN
FROM B
WHERE B.Condition = 'true') DT
ON A.Foo = DT.Foo AND DT.RN = 1
The ORDER BY is totally arbitrary since you don't care which record it selects, but it's required. You may be able to use (SELECT NULL) instead.
What is the best way to join the following three select and to get non duplicated contact.id ?
Any idea ?
SELECT distinct ct.id
FROM [Customer].[dbo].[Contact] ct
left join [Customer].[dbo].[HN_Customer_ids] hnids
on ct.id = hnids.contact_id
left join [CustomerTransactions].[dbo].[Transaction_Header] trh
on trh.Customer_ID = hnids.HN_customer_id
where trh.actual_transaction_date > '20120218'
Result: 231360
SELECT count(distinct(contact_id))
FROM [Customer].[dbo].[Restaurant_Attendance]
where ( created > '2012-02-18 00:00:00.000' or modified > '2012-02-18 00:00:00.000')
AND
Result: 167128
SELECT distinct aaa.id
FROM [Customer].[dbo].[Contact] aaa
left join [Customer].[dbo].[Wifinity_Devices] bbb
on aaa.wifinity_uniqueID = bbb.[CustomerUniqueID]
and startconnection > '2012-02-17'
Result: 77290
Use union. So:
SELECT ct.id
FROM [Customer].[dbo].[Contact] ct join
[Customer].[dbo].[HN_Customer_ids] hnids
on ct.id = hnids.contact_id join
[CustomerTransactions].[dbo].[Transaction_Header] trh
on trh.Customer_ID = hnids.HN_customer_id
WHERE trh.actual_transaction_date > '20120218'
UNION
SELECT contact_id
FROM [Customer].[dbo].[Restaurant_Attendance]
WHERE (created > '2012-02-18 00:00:00.000' or
modified > '2012-02-18 00:00:00.000')
UNION
SELECT aaa.id
FROM [Customer].[dbo].[Contact] aaa ;
The left joins are unnecessary in the first and third queries. In the first, the where undoes the left join anyway. In the third, you are choosing an id from the first table, and the left join does no filtering.
use union
SELECT ct.id
FROM [Customer].[dbo].[Contact] ct
left join [Customer].[dbo].[HN_Customer_ids] hnids on ct.id = hnids.contact_id
left join [CustomerTransactions].[dbo].[Transaction_Header] trh on trh.Customer_ID = hnids.HN_customer_id
where trh.actual_transaction_date > '20120218'
union
SELECT contact_id
FROM [Customer].[dbo].[Restaurant_Attendance]
where ( created > '2012-02-18 00:00:00.000' or modified > '2012-02-18 00:00:00.000')
union
SELECT aaa.id
FROM [Customer].[dbo].[Contact] aaa left join [Customer].[dbo].[Wifinity_Devices] bbb on aaa.wifinity_uniqueID = bbb.[CustomerUniqueID]
and startconnection > '2012-02-17'
Assuming all queries run against the same Contact table, your use of left outer join is effectively causing the third query to return all the contacts. Unless the second query can add contact_ids not found in the Contact table, the end result is equivalent to:
select /* distinct, if not a pk */ contact_id from Customer.dbo.Contact
Your row counts suggest that maybe these are actually tables from different databases. Is that the case?