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?
Related
I am trying to output result from 2 queries in one table but no luck. Tried with UNION and with this template
SELECT x.a, y.b FROM (SELECT * from a) as x, (SELECT * FROM b) as y
with no luck. My queries are:
Select
Sum('.MAIN_DB_PREFIX.'facturedet.qty) As qty_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid,
'.MAIN_DB_PREFIX.'facture.datef,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facturedet
Inner Join
'.MAIN_DB_PREFIX.'facture On '.MAIN_DB_PREFIX.'facturedet.fk_facture = '.MAIN_DB_PREFIX.'facture.rowid Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
ORDER BY
qty_sum DESC
and
Select
Sum('.MAIN_DB_PREFIX.'facture.total) As total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid,
'.MAIN_DB_PREFIX.'facture.datef,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facture Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
ORDER BY
total_sum DESC
With both UNION or combined query as mentioned above, I get blank result and no errors.
Also, I cannot wrap the select in brackets and use an alias like (query) a UNION (query2) b as this also brings blank output.
I can output first name + last name in column one of a table, sum_qty on second, some calculation is made based on the qty and it goes in the third column. In the fourth column, I need to output total_sum
Digged here like 20 threads and tried different solutions but no result.
Full code: https://pastebin.com/bie0LXH9
This should achieve the desired result (ie. the resultset that you need to output your table) using the UNION that you were attempting (although a more efficient query could possibly be achieved using a Common Table Expression - which may or may not be available to you, depending on your RDBMS, and the version thereof).
SELECT
firstname,
lastname,
rowid,
SUM(IFNULL(qty_sum, 0)) AS qty_sum,
SUM(IFNULL(total_sum, 0)) AS total_sum
FROM
(
Select
Sum('.MAIN_DB_PREFIX.'facturedet.qty) As qty_sum,
0 AS total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facturedet
Inner Join
'.MAIN_DB_PREFIX.'facture On '.MAIN_DB_PREFIX.'facturedet.fk_facture = '.MAIN_DB_PREFIX.'facture.rowid Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
UNION ALL
Select
0 AS qty_sum,
Sum('.MAIN_DB_PREFIX.'facture.total) As total_sum,
'.MAIN_DB_PREFIX.'user.firstname,
'.MAIN_DB_PREFIX.'user.lastname,
'.MAIN_DB_PREFIX.'user.rowid
From
'.MAIN_DB_PREFIX.'facture Inner Join
'.MAIN_DB_PREFIX.'societe_commerciaux On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_soc = '.MAIN_DB_PREFIX.'facture.fk_soc Inner Join
'.MAIN_DB_PREFIX.'user On '.MAIN_DB_PREFIX.'societe_commerciaux.fk_user = '.MAIN_DB_PREFIX.'user.rowid
Where
".MAIN_DB_PREFIX."facture.datef Between Date_Format(Now(), '%Y-%m-01') And CurDate()
GROUP BY
'.MAIN_DB_PREFIX.'user.rowid
) AS tbl_all
GROUP BY rowid
ORDER BY
total_sum DESC
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.
I am working with the below query
SELECT * FROM
(SELECT DISTINCT
a.Number
,a.Description
,ISNULL(temp.Quantity,0) Quantity
,LastReceived
,LastIssued
FROM Article a
LEFT JOIN (
select ss.ArticleId
, ss.Quantity
, max(lastreceiveddate) as LastReceived
, max(lastissueddate) as LastIssued
from StockSummary ss
where ss.UnitId = 8
group by ss.ArticleId, ss.StockQuantity
having (MAX(ss.LastReceivedDate) < '2014-09-01' or MAX(ss.LastReceivedDate) is NULL)
AND (MAX(ss.LastIssuedDate) < '2014-09-01' or MAX(ss.LastIssuedDate) is NULL)
) temp on a.Id = temp.ArticleId
WHERE a.UnitId = 8
) main
ORDER BY main.Number
What i want to achieve is to select the articles only with the MAX(ss.LastReceivedDate) and MAX(ss.LastIssuedDate) condition in the Left join query and then do the Quantity Select in the main query.
Note: the quantity column can be 0 or NULL.
Kindly help
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.
I have tried a lot to figure how to get the count from two tables with respect to master table
I have three tables
Using these table values I need to get this output..
Tried but could get the desired result
http://en.wikipedia.org/wiki/Join_(SQL)
SQL - LEFT OUTER JOIN and WHERE clause
http://forums.devshed.com/oracle-development-96/combination-of-left-outer-join-and-where-clause-383248.html
You have to first GROUP BY in subqueries, then JOIN to the main table:
SELECT
a.AttributeId
, COALECSE(cntE, 0) AS cntE
, COALECSE(cntM, 0) AS cntM
FROM
AttributeMaster AS a
LEFT JOIN
( SELECT
AttributeId
, COUNT(*) AS cntE
FROM
EmployeeMaster
GROUP BY
AttributeId
) em
ON em.AttributeId = a.AttributeId
LEFT JOIN
( SELECT
AttributeId
, COUNT(*) AS cntM
FROM
MonthlyDerivedMaster
GROUP BY
AttributeId
) mdm
ON mdm.AttributeId = a.AttributeId
SELECT AttributeId,
(SELECT COUNT(Eid) FROM EmployeeMaster WHERE AttributeMaster.AttributeId = EmployeeMaster.AttributeId) as master_eid,
(SELECT COUNT(Eid) FROM MonthnlyDerivedMaster WHERE AttributeMaster.AttributeId = MonthnlyDerivedMaster.AttributeId) as monthly_eid
FROM AttributeMaster