December 11, 2013 at 8:01 am
I am looking to perform a UNION join between 3 select queries, this is what I think I need to do to get the desired result set. The SQL Query is for a report which displays emergency/next of kin contact information. I have added 'IsNextOfKin' flags to the three static tables; StaticAddressType, StaticPhoneType and StaticEmailType. For each of these tables, the desired types are 'Emergency' and 'Next Of Kin' ONLY. I cannot use 'hard coding' i.e where staticaddresstype = 'Emergency' or where staticaddresstype in ('Emergency', 'Next Of Kin') etc. I am using the flags StaticAddressType.IsNextOfKin=1, StaticEmailType.IsNextOfKin=1, StaticPhoneType.IsNextOfKin=1.
I ONLY want to return values which contain Emergency or Next Of Kin. I think i might need to make this three seperate queries and join them? a trimmed down version of my SQL query is below. I have tried to take as much of the irrelevant logic out as possible.
SELECT st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(em.Email, '') as [Email],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number],
isnull(ea.Address3, '') as [Flat Number],
isnull(ea.Address4, '') as [Address Line 1],
isnull(ea.Address5, '') as [Address Line 2],
isnull(ea.City,'') as [City],
isnull(ea.Region, '') as [Region],
isnull(ea.Postcode,'') as [Postcode],
FROM Employee e
Left Join StaticTitle st on e.title = st.id and st.IsActive=1
left Join
(SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROMEmployeePayHistory as eph
inner Join EmployeeJob as ej on ej.Employee = eph.EmployeeID and ej.position = eph.EmployeePosition
and eph.IsActive=1 and eph.IsCurrent=1 and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on PAP.Country = sn2.IDand sn2.IsActive=1
left Join StaticRelation sr on e.NextOfKinRelation = sr.ID and sr.IsActive=1
left Join EmployeePhone emph on e.EmployeeID = emph.Employee and emph.IsActive=1
left Join EmployeeEmail em on e.EmployeeID = em.employee and em.IsActive=1
left Join EmployeeAddress ea on e.EmployeeID = ea.Employee and ea.IsActive=1
left Join StaticPhoneType spt on emph.PhoneType = spt.PhoneTypeID and spt.IsActive=1
inner Join StaticEmailType [set] on em.EmailType = [set].EmailTypeID and [set].IsActive=1
inner Join StaticAddressType sat on ea.AddressTypeID = sat.AddressTypeID and sat.IsActive=1
WHERE(e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and (spt.IsNextOfKin=1)or /* using OR as not ALL employees meet the three conditions */
([set].IsNextOfKin=1)or
(sat.IsNextOfKin=1)
ORDER BY e.LastName asc
December 11, 2013 at 8:55 am
Hi and welcome to the forums!!! In order to help we will need a few things:
1. Sample DDL in the form of CREATE TABLE statements
2. Sample data in the form of INSERT INTO statements
3. Expected results based on the sample data
Please take a few minutes and read the first article in my signature for best practices when posting questions.
_______________________________________________________________
Need help? Help us help you.
Read the article at http://www.sqlservercentral.com/articles/Best+Practices/61537/ for best practices on asking questions.
Need to split a string? Try Jeff Modens splitter http://www.sqlservercentral.com/articles/Tally+Table/72993/.
Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - http://www.sqlservercentral.com/articles/T-SQL/63681/
Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - http://www.sqlservercentral.com/articles/Crosstab/65048/
Understanding and Using APPLY (Part 1) - http://www.sqlservercentral.com/articles/APPLY/69953/
Understanding and Using APPLY (Part 2) - http://www.sqlservercentral.com/articles/APPLY/69954/
December 11, 2013 at 8:56 am
I would look at this part of your where clauseand (spt.IsNextOfKin=1)or /* using OR as not ALL employees meet the three conditions */
([set].IsNextOfKin=1)or
(sat.IsNextOfKin=1)
If you want one of those three to be true and the rest of the where to be true you need to enclose these inside of parentheses
and (
(spt.IsNextOfKin=1)or /* using OR as not ALL employees meet the three conditions */
([set].IsNextOfKin=1)or
(sat.IsNextOfKin=1)
)
December 11, 2013 at 9:06 am
Keith Tate (12/11/2013)
I would look at this part of your where clauseand (spt.IsNextOfKin=1)or /* using OR as not ALL employees meet the three conditions */
([set].IsNextOfKin=1)or
(sat.IsNextOfKin=1)
If you want one of those three to be true and the rest of the where to be true you need to enclose these inside of parentheses
and (
(spt.IsNextOfKin=1)or /* using OR as not ALL employees meet the three conditions */
([set].IsNextOfKin=1)or
(sat.IsNextOfKin=1)
)
ORs without appropriate parentheses is one of the most common logic flaws I see in WHERE clauses at clients. They can be VERY sneaky, and difficult to "see" too!
Best,
Kevin G. Boles
SQL Server Consultant
SQL MVP 2007-2012
TheSQLGuru on googles mail service
December 12, 2013 at 7:05 am
If the columns are all 1 or 0, if a + b + c > 0, one of the columns is populated.
December 12, 2013 at 7:16 am
Take care with your join types. Referencing a column from an outer-joined table will convert the join to an IJ (except the special case of checking a column for NULL).
SELECT
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(em.Email, '') as [Email],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number],
isnull(ea.Address3, '') as [Flat Number],
isnull(ea.Address4, '') as [Address Line 1],
isnull(ea.Address5, '') as [Address Line 2],
isnull(ea.City,'') as [City],
isnull(ea.Region, '') as [Region],
isnull(ea.Postcode,'') as [Postcode] --,
FROM Employee e
Left Join StaticTitle st on e.title = st.id and st.IsActive=1
left Join (
SELECT
eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROM EmployeePayHistory as eph
inner Join EmployeeJob as ej on ej.Employee = eph.EmployeeID and ej.position = eph.EmployeePosition
and eph.IsActive=1 and eph.IsCurrent=1 and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom
) as PAP on e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on PAP.Country = sn2.ID and sn2.IsActive=1
left Join StaticRelation sr on e.NextOfKinRelation = sr.ID and sr.IsActive=1
left Join EmployeePhone emph on e.EmployeeID = emph.Employee and emph.IsActive=1
left Join EmployeeEmail em on e.EmployeeID = em.employee and em.IsActive=1
left Join EmployeeAddress ea on e.EmployeeID = ea.Employee and ea.IsActive=1
left Join StaticPhoneType spt on emph.PhoneType = spt.PhoneTypeID and spt.IsActive=1
inner Join StaticEmailType [set] on em.EmailType = [set].EmailTypeID and [set].IsActive=1
inner Join StaticAddressType sat on ea.AddressTypeID = sat.AddressTypeID and sat.IsActive=1
CROSS APPLY (
SELECT ValidRow = CASE WHEN spt.IsNextOfKin = 1 OR [set].IsNextOfKin = 1 OR sat.IsNextOfKin = 1 THEN 1 ELSE 0 END
) x
WHERE e.IsActive = 1
and sr.IsActive = 1 -- converted [sr] from outer to inner join
and pap.EJIsCurrent = 1 -- converted [pap] from outer to inner join
and PAP.IsCurrent = 1 -- converted [pap] from outer to inner join
and x.ValidRow = 1
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
December 12, 2013 at 7:36 am
I recently worked on a process that had about 10 different fields I needed to check, all were had 'Y' or 'N' as the value. If any one of these were set to 'N' then that record didn't qualify. My first thought went to one big nested case statement checking each field one at a time. No one likes to deal with that and it's hard to read and to follow at times.
casewhen field1 = 'Y'
then casewhen field2 = 'Y'
thencasewhen field3 = 'Y'
So I decided to turn my thinking around:
casewhen 'N' in (field1, field2, field3, ...)
This is so simple but I had never thought about it that way. Just wanted to share, maybe just me but I get stuck thinking one way, and just stepping back for a minute to look at it differently made a huge difference to me.
For what you want and your fields being 1 or 0, I think the adding and checking for greater than zero is an easy way to do that if only one has to be 'true'.
-------------------------------------------------------------
we travel not to escape life but for life not to escape us
Don't fear failure, fear regret.
December 12, 2013 at 8:42 am
Hi, thanks for your replies.
Apologies if I wasn't being clear in my explanation.
So I need to retrieve all employees who have emergency/next of kin contact details in the system.
eg
John Smith could have emergency phone number, emergency address, next of kin email
Joan smith might only have emergency phone number
Joe Bloggs might have emergency phone number and emergency address.
Note: these employees also have work, person, other phone/email/address types, which are currently showing and do not want. This is why i have a flag on each of the static tables.
StaticAddressType.IsNextOfKin
StaticEmailType.IsNextOfKin
StaticPhoneType.IsNextOfKin
These are set to 'IsNextOfKin=1', the other types (work, personal, business, other are set to '0'
So, i want to retrieve all records where the three contact types are EMERGENCY or IS NEXT OF KIN, but cannot search for the types themselves in the where clause as this would be hard coding.
My question is, should I take the query, turn it into 3 queries, have StaticAddressType.IsNextOfKin=1 in the first query, StaticEmailType.IsNextOfKin=1 in the next query, and StaticPhoneType.IsNextOfKin=1 in the last query, and join the three queries using UNION, which i have done with no luck. See below.
(
SELECTe.EmployeeReference as [Employee Reference],
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number],
FROM Employee e
Left Join StaticTitle st on e.title = st.idand st.IsActive=1
left Join
(SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROMEmployeePayHistory as eph
inner Join EmployeeJob as ej on ej.Employee = eph.EmployeeID and ej.position = eph.EmployeePosition
and eph.IsActive=1 and eph.IsCurrent=1 and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on PAP.Country = sn2.IDand sn2.IsActive=1
left Join StaticRelation sr on e.NextOfKinRelation = sr.ID and sr.IsActive=1
left Join EmployeePhone emph on e.EmployeeID = emph.Employee and emph.IsActive=1
left Join EmployeeEmail em on e.EmployeeID = em.employee and em.IsActive=1
left Join EmployeeAddress ea on e.EmployeeID = ea.Employee and ea.IsActive=1
inner Join StaticPhoneType spt on emph.PhoneType = spt.PhoneTypeID and spt.IsActive=1
inner Join StaticEmailType [set] on em.EmailType = [set].EmailTypeID and [set].IsActive=1
inner Join StaticAddressType sat on ea.AddressTypeID = sat.AddressTypeID and sat.IsActive=1
WHERE(e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and (spt.IsNextOfKin=1)
)
union
(
SELECTe.EmployeeReference as [Employee Reference],
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number],
FROM Employee e
Left Join StaticTitle st on e.title = st.idand st.IsActive=1
left Join
(SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROMEmployeePayHistory as eph
inner Join EmployeeJob as ej on ej.Employee = eph.EmployeeID and ej.position = eph.EmployeePosition
and eph.IsActive=1 and eph.IsCurrent=1 and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on PAP.Country = sn2.IDand sn2.IsActive=1
left Join StaticRelation sr on e.NextOfKinRelation = sr.ID and sr.IsActive=1
left Join EmployeePhone emph on e.EmployeeID = emph.Employee and emph.IsActive=1
left Join EmployeeEmail em on e.EmployeeID = em.employee and em.IsActive=1
left Join EmployeeAddress ea on e.EmployeeID = ea.Employee and ea.IsActive=1
inner Join StaticPhoneType spt on emph.PhoneType = spt.PhoneTypeID and spt.IsActive=1
inner Join StaticEmailType [set] on em.EmailType = [set].EmailTypeID and [set].IsActive=1
inner Join StaticAddressType sat on ea.AddressTypeID = sat.AddressTypeID and sat.IsActive=1
WHERE(e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and ([set].IsNextOfKin=1)
)
union
(
SELECTe.EmployeeReference as [Employee Reference],
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number],
FROM Employee e
Left Join StaticTitle st on e.title = st.idand st.IsActive=1
left Join
(SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROMEmployeePayHistory as eph
inner Join EmployeeJob as ej on ej.Employee = eph.EmployeeID and ej.position = eph.EmployeePosition
and eph.IsActive=1 and eph.IsCurrent=1 and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on PAP.Country = sn2.IDand sn2.IsActive=1
left Join StaticRelation sr on e.NextOfKinRelation = sr.ID and sr.IsActive=1
left Join EmployeePhone emph on e.EmployeeID = emph.Employee and emph.IsActive=1
left Join EmployeeEmail em on e.EmployeeID = em.employee and em.IsActive=1
left Join EmployeeAddress ea on e.EmployeeID = ea.Employee and ea.IsActive=1
inner Join StaticPhoneType spt on emph.PhoneType = spt.PhoneTypeID and spt.IsActive=1
inner Join StaticEmailType [set] on em.EmailType = [set].EmailTypeID and [set].IsActive=1
inner Join StaticAddressType sat on ea.AddressTypeID = sat.AddressTypeID and sat.IsActive=1
WHERE(e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and (sat.IsNextOfKin=1)
)
ORDER BY e.LastName asc
December 12, 2013 at 9:14 am
What results are you getting? There is syntax errors in your posted SQL, commas before the from, I assume you removed some fields for the post.
Formatting the SQL will help us better understand what you are doing. Like this:
SELECT e.EmployeeReference as [Employee Reference],
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number]
FROM Employee e
Left Join StaticTitle st on
e.title = st.id
and st.IsActive=1
left Join (SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROM EmployeePayHistory as eph
inner Join EmployeeJob as ej on
ej.Employee = eph.EmployeeID
and ej.position = eph.EmployeePosition
and eph.IsActive=1
and eph.IsCurrent=1
and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on
e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on
PAP.Country = sn2.ID
and sn2.IsActive=1
left Join StaticRelation sr on
e.NextOfKinRelation = sr.ID
and sr.IsActive=1
left Join EmployeePhone emph on
e.EmployeeID = emph.Employee
and emph.IsActive=1
left Join EmployeeEmail em on
e.EmployeeID = em.employee
and em.IsActive=1
left Join EmployeeAddress ea on
e.EmployeeID = ea.Employee
and ea.IsActive=1
inner Join StaticPhoneType spt on
emph.PhoneType = spt.PhoneTypeID
and spt.IsActive=1
inner Join StaticEmailType [set] on
em.EmailType = [set].EmailTypeID
and [set].IsActive=1
inner Join StaticAddressType sat on
ea.AddressTypeID = sat.AddressTypeID
and sat.IsActive=1
WHERE (e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and (spt.IsNextOfKin=1)
union
SELECT e.EmployeeReference as [Employee Reference],
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number]
FROM Employee e
Left Join StaticTitle st on
e.title = st.id
and st.IsActive=1
left Join (SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROM EmployeePayHistory as eph
inner Join EmployeeJob as ej on
ej.Employee = eph.EmployeeID
and ej.position = eph.EmployeePosition
and eph.IsActive=1
and eph.IsCurrent=1
and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on
e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on
PAP.Country = sn2.ID
and sn2.IsActive=1
left Join StaticRelation sr on
e.NextOfKinRelation = sr.ID
and sr.IsActive=1
left Join EmployeePhone emph on
e.EmployeeID = emph.Employee
and emph.IsActive=1
left Join EmployeeEmail em on
e.EmployeeID = em.employee
and em.IsActive=1
left Join EmployeeAddress ea on
e.EmployeeID = ea.Employee
and ea.IsActive=1
inner Join StaticPhoneType spt on
emph.PhoneType = spt.PhoneTypeID
and spt.IsActive=1
inner Join StaticEmailType [set] on
em.EmailType = [set].EmailTypeID
and [set].IsActive=1
inner Join StaticAddressType sat on
ea.AddressTypeID = sat.AddressTypeID
and sat.IsActive=1
WHERE (e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and ([set].IsNextOfKin=1)
union
SELECT e.EmployeeReference as [Employee Reference],
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number]
FROM Employee e
Left Join StaticTitle st on
e.title = st.id
and st.IsActive=1
left Join (SELECT eph.EmployeeID, eph.DateFrom as DateFrom1, eph.DateTo as DateTo1, eph.Pay,
eph.EmployeePosition, eph.ForeignCurrencyCode, eph.TotalSalaryPackage,
eph.SalaryCategory, eph.Frequency, eph.FTEEquivalentAmount, eph.IsBasicSalary,
eph.IsCurrent, eph.IncludeInPayroll, eph.IsoneOff, eph.IsPegged, ej.DateFrom as DateFrom2,
ej.DateTo as DateTo2, ej.position, ej.Notes, ej.ChangeReason, ej.SalaryBand, ej.HoursPerWeek,
ej.Country, ej.PositionLocation, ej.IsCurrent as EJIsCurrent
FROM EmployeePayHistory as eph
inner Join EmployeeJob as ej on
ej.Employee = eph.EmployeeID
and ej.position = eph.EmployeePosition
and eph.IsActive=1
and eph.IsCurrent=1
and eph.IncludeInPayroll=1
and eph.DateFrom = ej.DateFrom) as PAP on
e.EmployeeID = PAP.EmployeeID
Left Join StaticNationality sn2 on
PAP.Country = sn2.ID
and sn2.IsActive=1
left Join StaticRelation sr on
e.NextOfKinRelation = sr.ID
and sr.IsActive=1
left Join EmployeePhone emph on
e.EmployeeID = emph.Employee
and emph.IsActive=1
left Join EmployeeEmail em on
e.EmployeeID = em.employee
and em.IsActive=1
left Join EmployeeAddress ea on
e.EmployeeID = ea.Employee
and ea.IsActive=1
inner Join StaticPhoneType spt on
emph.PhoneType = spt.PhoneTypeID
and spt.IsActive=1
inner Join StaticEmailType [set] on
em.EmailType = [set].EmailTypeID
and [set].IsActive=1
inner Join StaticAddressType sat on
ea.AddressTypeID = sat.AddressTypeID
and sat.IsActive=1
WHERE (e.IsActive=1)
and (sr.IsActive=1)
and (pap.EJIsCurrent=1)
and (PAP.IsCurrent=1)
and (sat.IsNextOfKin=1)
ORDER BY e.LastName asc
Without seeing your data I would think this would work, doing the union would eliminate any duplicate entries.
Test data would be needed for each table to better know, and what you are getting compared to what you are expecting.
-------------------------------------------------------------
we travel not to escape life but for life not to escape us
Don't fear failure, fear regret.
December 12, 2013 at 9:17 am
Hi, Sorry - ignore the commas. these aren't in the query. Just trimmed the select statement down to the most important fields
December 12, 2013 at 10:05 am
Without more detail it is hard to help, see Sean's post.
As I said I would think the union's would work but without data to test it I can't be sure. Let us know what results you are getting.
And I think Greg's response would work if you don't want to do the union. May need to add ISNULL to each in case there isn't a record. Something like (ISNULL(sat.IsNextOfKin, 0) + ISNULL(set].IsNextOfKin, 0) + ISNULL(spt.IsNextOfKin, 0)) > 0
-------------------------------------------------------------
we travel not to escape life but for life not to escape us
Don't fear failure, fear regret.
December 12, 2013 at 4:21 pm
I created a real quick sample of a few tables.
The problem I see, is in doing an outer join and selecting any next of kin records that have information without getting duplicates.
Yes, some sample tables with sample data would go a long ways towards an answer vs. guessing.
And a better description of what the poster is actually seeing would be helpful too.
A view against each of the tables with only the next of kin records selected, a view using having to select a distinct list of the keys, and then a view using this to select those keys, the employee, and outer join to the next of kin views for address, phone, and email can return what it appears the poster wants to see.
No record for an employee with no additional contact info, a record where such info exists (null if not in any field).
Not sure if there is any option to do any work to rearchitect the tables.
That could simplify things considerably.
December 13, 2013 at 2:04 am
Why read ALL OF THOSE TABLES three times when you can get your results by reading them only once?
Why include tons of columns in your subquery - then throw them away?
Why use LEFT JOIN for tables which are referenced in your WHERE clause?
Why left join tables which aren't referenced anywhere else in your query?
Why overcomplicate something so simple?
Accounting for these, this is what I think your query should look like:
SELECT
st.keyfield as [Title],
e.FirstName as [First Name],
e.LastName as [Last Name],
isnull(spt.PhoneType, '') as [Phone Type],
isnull(emph.Phone, '') as [Phone],
isnull([set].EmailType, '') as [Email Type],
isnull(em.Email, '') as [Email],
isnull(sat.AddressType, '') as [Address Type],
isnull(ea.Address1, '') as [Property Name],
isnull(ea.Address2, '') as [Property Number],
isnull(ea.Address3, '') as [Flat Number],
isnull(ea.Address4, '') as [Address Line 1],
isnull(ea.Address5, '') as [Address Line 2],
isnull(ea.City,'') as [City],
isnull(ea.Region, '') as [Region],
isnull(ea.Postcode,'') as [Postcode]
FROM Employee e -- output/WHERE
Left Join StaticTitle st
on e.title = st.id and st.IsActive = 1 -- output
INNER JOIN EmployeePayHistory as eph
on e.EmployeeID = eph.EmployeeID -- WHERE
and eph.IsActive=1
and eph.IsCurrent=1
and eph.IncludeInPayroll=1
inner Join EmployeeJob as ej
on ej.Employee = eph.EmployeeID
and ej.position = eph.EmployeePosition
and eph.DateFrom = ej.DateFrom
AND EJ.IsCurrent=1
-- Left Join StaticNationality sn2 on PAP.Country = sn2.ID and sn2.IsActive=1 -- NOT USED
INNER Join StaticRelation sr on e.NextOfKinRelation = sr.ID and sr.IsActive=1 -- WHERE
left Join EmployeePhone emph on e.EmployeeID = emph.Employee and emph.IsActive=1 -- output
-- left Join EmployeeEmail em on e.EmployeeID = em.employee and em.IsActive=1 -- NOT USED
left Join EmployeeAddress ea on e.EmployeeID = ea.Employee and ea.IsActive=1 -- output
left Join StaticPhoneType spt on emph.PhoneType = spt.PhoneTypeID and spt.IsActive=1 -- output/conditional WHERE
left Join StaticEmailType [set] on em.EmailType = [set].EmailTypeID and [set].IsActive=1 -- output/conditional WHERE
left Join StaticAddressType sat on ea.AddressTypeID = sat.AddressTypeID and sat.IsActive=1 -- conditional WHERE
WHERE e.IsActive=1
--and sr.IsActive=1 -- REDUNDANT FILTER
--and pap.EJIsCurrent=1 -- REDUNDANT FILTER
--and PAP.IsCurrent=1 -- REDUNDANT FILTER
and (
spt.IsNextOfKin = 1 OR /* using OR as not ALL employees meet the three conditions */
[set].IsNextOfKin = 1 OR
sat.IsNextOfKin = 1
)
ORDER BY e.LastName asc
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
December 13, 2013 at 6:58 am
Chris -
I agree with a lot of your Why's. See this all the time.
If you could look at this, run the view for next of kin info, and tell me a better way, I'd appreciate it.
Not exactly the same as what the poster has, but I think close enough in concept.
Thanks.
USE [Test2]
GO
/****** Object: Table [dbo].[Employee] Script Date: 12/12/2013 13:42:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Employee](
[EKey] [smallint] NOT NULL,
[Emp_First] [nchar](10) NOT NULL,
[Emp_Last] [nchar](20) NOT NULL
) ON [PRIMARY]
GO
INSERT INTO [Test2].[dbo].[Employee]
([EKey]
,[Emp_First]
,[Emp_Last])
VALUES
(1,'Greg','Johnson'),
(2,'Fred','Flintstone'),
(3,'Jenny','May'),
(4,'Joe','Horn'),
(5,'Cathy','French')
GO
/****** Object: Table [dbo].[Email] Script Date: 12/12/2013 13:43:26 ******/
CREATE TABLE [dbo].[Email](
[EKey] [smallint] NOT NULL,
[Next_of_Kin] [bit] NULL,
[Email] [nchar](40) NULL
) ON [PRIMARY]
GO
INSERT INTO [Test2].[dbo].[Email]
([EKey]
,[Next_of_Kin]
,[Email])
VALUES
(1,'','greg.johnson@gmail.com'),
(3,'','jenny.may@gmail.com'),
(5,'','cathy.french@yahoo.com'),
(1,'True','johndoe@gmail.com'),
(2,'True','bettyflintstone@yahoo.com'),
(5,'True','jerrycan@gmail.com')
GO
CREATE TABLE [dbo].[Phone](
[EKey] [smallint] NOT NULL,
[Phone] [numeric](18, 0) NULL,
[Next_of_Kin] [bit] NULL
) ON [PRIMARY]
GO
INSERT INTO [Test2].[dbo].[Phone]
([EKey]
,[Phone]
,[Next_of_Kin])
VALUES
(1,7637531111,''),
(1,7637532222,'True'),
(2,7637533333,''),
(3,7637551234,''),
(4,7635551245,''),
(5,7639998888,''),
(5,6127775555,'True')
GO
/****** Object: Table [dbo].[Address] Script Date: 12/12/2013 13:44:22 ******/
CREATE TABLE [dbo].[Address](
[EKey] [smallint] NOT NULL,
[Address] [nchar](50) NULL,
[Next_of_Kin] [bit] NULL
) ON [PRIMARY]
GO
INSERT INTO [Test2].[dbo].[Address]
([EKey]
,[Address]
,[Next_of_Kin])
VALUES
(1,'111 south St',''),
(2,'222 North St',''),
(3,'333 West Ave',''),
(4,'555 10th St',''),
(5,'1313 Mockingbird Lane',''),
(1,'123 South St','True'),
(4,'487 Xerxes Ave So','True')
GO
/****** Object: View [dbo].[v_Next_of_Kin_Keys] Script Date: 12/12/2013 13:44:56 ******/
CREATE VIEW [dbo].[v_Next_of_Kin_Keys]
AS
SELECT DISTINCT a.EKey
FROM dbo.Employee AS a LEFT OUTER JOIN
dbo.Email AS b ON a.EKey = b.EKey LEFT OUTER JOIN
dbo.Phone AS c ON a.EKey = c.EKey LEFT OUTER JOIN
dbo.Address AS d ON a.EKey = d.EKey
GROUP BY a.EKey
HAVING (SUM(CASE b.Next_of_Kin WHEN 'TRUE' THEN 1 ELSE 0 END + CASE c.Next_of_Kin WHEN 'TRUE' THEN 1 ELSE 0 END + CASE d .Next_of_Kin WHEN 'TRUE' THEN 1
ELSE 0 END) > 0)
GO
/****** Object: View [dbo].[v_Next_of_Kin_Address] Script Date: 12/12/2013 13:45:17 ******/
CREATE VIEW [dbo].[v_Next_of_Kin_Address]
AS
SELECT a.EKey, b.Address
FROM dbo.Employee AS a INNER JOIN
dbo.Address AS b ON a.EKey = b.EKey
WHERE (b.Next_of_Kin = 'true')
GO
/****** Object: View [dbo].[v_Next_of_Kin_Phone] Script Date: 12/12/2013 13:45:28 ******/
CREATE VIEW [dbo].[v_Next_of_Kin_Phone]
AS
SELECT a.EKey, b.Phone
FROM dbo.Employee AS a INNER JOIN
dbo.Phone AS b ON a.EKey = b.EKey
WHERE (b.Next_of_Kin = 'true')
GO
/****** Object: View [dbo].[v_Next_of_Kin_Email] Script Date: 12/12/2013 13:46:22 ******/
CREATE VIEW [dbo].[v_Next_of_Kin_Email]
AS
SELECT a.EKey, b.Email
FROM dbo.Employee AS a INNER JOIN
dbo.Email AS b ON a.EKey = b.EKey
WHERE (b.Next_of_Kin = 'true')
GO
/****** Object: View [dbo].[v_Next_of_Kin_Info] Script Date: 12/12/2013 13:46:34 ******/
CREATE VIEW [dbo].[v_Next_of_Kin_Info]
AS
SELECT a.EKey, b.Emp_First, b.Emp_Last, c.Address, d.Phone, e.Email
FROM dbo.v_Next_of_Kin_Keys AS a LEFT OUTER JOIN
dbo.Employee AS b ON a.EKey = b.EKey LEFT OUTER JOIN
dbo.v_Next_of_Kin_Address AS c ON a.EKey = c.EKey LEFT OUTER JOIN
dbo.v_Next_of_Kin_Phone AS d ON a.EKey = d.EKey LEFT OUTER JOIN
dbo.v_Next_of_Kin_Email AS e ON a.EKey = e.EKey
GO
December 13, 2013 at 7:25 am
Greg Edwards-268690 (12/13/2013)
Chris -I agree with a lot of your Why's. See this all the time.
If you could look at this, run the view for next of kin info, and tell me a better way, I'd appreciate it.
Not exactly the same as what the poster has, but I think close enough in concept.
Thanks.
I've never been a big fan of views Greg, a device designed to simplify coding almost always ends up doing the exact opposite through overuse -mostly ignorance. Your approach is nice though. The views could easily fit into a query which visibly models the business case. Here's the other side of that coin:
"What are you trying to do in this crazy 12,000 line stored procedure?"
"This and this and that and that and then something else then back to the beginning and repeat for each branch, and then go on to the next month, and that's only this year! It's really really complicated and it's taking like 48 nested cursors to process each piece!"
"What are you really trying to do?"
"Get last year's gross and net sales figures aggregated by branch and month and compare with what we've got so far for this year".
😀
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
Viewing 15 posts - 1 through 15 (of 19 total)
You must be logged in to reply to this topic. Login to reply