Joining 5 tables in Access 2010 - sql

So here's a challenge. I have a webpage that needs to show data from 5 different tables in a database. Here's the query:
'SELECT ORGANIZATIONS.ORG_NAME, ORG_SECTIONS.SectionName, ATTORNEYS.NAME, ATTORNEYS.LASTNAME, ATTORNEYS.EMAIL, ATTORNEYS.TEL, ATTY_TITLES.ATT_TITLE, FIRM_PRACTICE_GRPS.PRACTICE_GRP
FROM (ORGANIZATIONS INNER JOIN (Org_Sec_Atty INNER JOIN ATTORNEYS ON Org_Sec_Atty.Atty_ID = ATTORNEYS.ATTY_ID) ON ORGANIZATIONS.ID = Org_Sec_Atty.OrgID) INNER JOIN ORG_SECTIONS ON Org_Sec_Atty.SecID = ORG_SECTIONS.ID
WHERE ATTORNEYS.LASTNAME LIKE #LASTNAME;'
The 5 tables are Org_Sec_Atty, ORGANIZATIONS, ORG_SECTIONS, ATTORNEYS, ATTY_TITLES, and FIRM_PRACTICE_GRPS. First, I didn't come up with the table names, lol.
Second, ATTORNEYS is the table that has ATTY_ID, TITLE_ID, PRACTICE_GRP_ID, which is what I'm sure I need to join to FIRM_PRACTICE_GRPS and ATTY_TITLE, and then it needs to connect with the Org_Sec_Atty and ORG_SECTIONS table.
I already have a page where the three tables ATTORNEYS, Org_Sec_Atty, and ORG_SECTIONS are joined by the JOIN statement you see up there. I'm trying to figure out where the other INNER JOIN statements would go and in what order.
It seems like I need to replace "ATTORNEYS" in the "Org_Sec_Atty INNER JOIN ATTORNEYS" with the subordinate INNER JOIN statements, but, again, I'm not sure of the order. Is this possible?

You didn't specified foreign keys on last two tables. Change appropriately if necessary:
SELECT ORGANIZATIONS.ORG_NAME ,
ORG_SECTIONS.SectionName ,
ATTORNEYS.NAME ,
ATTORNEYS.LASTNAME ,
ATTORNEYS.EMAIL ,
ATTORNEYS.TEL ,
ATTY_TITLES.ATT_TITLE ,
FIRM_PRACTICE_GRPS.PRACTICE_GRP
FROM (((( ORGANIZATIONS
INNER JOIN Org_Sec_Atty ON ORGANIZATIONS.ID = Org_Sec_Atty.OrgID)
INNER JOIN ATTORNEYS ON Org_Sec_Atty.Atty_ID = ATTORNEYS.ATTY_ID)
INNER JOIN ORG_SECTIONS ON Org_Sec_Atty.SecID = ORG_SECTIONS.ID)
INNER JOIN ATTY_TITLES ON ORG_SECTIONS.ATTY_ID = ATTY_TITLES.ID)
INNER JOIN FIRM_PRACTICE_GRPS ON ATTY_TITLES.FIRM_ID = FIRM_PRACTICE_GRPS.ID
WHERE ATTORNEYS.LASTNAME LIKE #LASTNAME;

Related

Join two SQL Queries to produce one table without headings

I have made two SQL queries both bring back the information i want which is great, i was wondering if i could combine the result into one instead of 2 separate results , i don't know if this can be done but either show without headings or new custom headings.
the SQL code i am using is below
SELECT T_PRODUCT_NUTRITIONALINFORMATION.C_ENERGY_KJ ,T_PRODUCT_NUTRITIONALINFORMATION.C_PROTEIN, T_PRODUCT_SELLING_PRICEDEFINITION.C_NETPRICE
FROM ((T_PRODUCT
INNER JOIN T_PRODUCT_NUTRITIONALINFORMATION ON T_PRODUCT.C_NUTRITIONALINFORMATION = T_PRODUCT_NUTRITIONALINFORMATION.C_ID)
INNER JOIN T_PRODUCT_SELLING_PRICEDEFINITION ON T_PRODUCT.C_SELLING = T_PRODUCT_SELLING_PRICEDEFINITION.C__OWNER_)
WHERE C_CODE LIKE 'STK000832';
SELECT T_PRODUCT_NUTRITIONALINFORMATION.C_ENERGY_KJ ,T_PRODUCT_NUTRITIONALINFORMATION.C_CARBOHYDRATESOFWHICHARESUGAR, T_PRODUCT_SELLING_PRICEDEFINITION.C_NETPRICE
FROM ((T_PRODUCT
INNER JOIN T_PRODUCT_NUTRITIONALINFORMATION ON T_PRODUCT.C_NUTRITIONALINFORMATION = T_PRODUCT_NUTRITIONALINFORMATION.C_ID)
INNER JOIN T_PRODUCT_SELLING_PRICEDEFINITION ON T_PRODUCT.C_SELLING = T_PRODUCT_SELLING_PRICEDEFINITION.C__OWNER_)
WHERE C_CODE LIKE 'STK000832';
the result is below
below is the result i am trying to achieve
Sure, you can use UNION ALL
SELECT T_PRODUCT_NUTRITIONALINFORMATION.C_ENERGY_KJ AS NewHeading1,
T_PRODUCT_NUTRITIONALINFORMATION.C_PROTEIN AS NewHeading2,
T_PRODUCT_SELLING_PRICEDEFINITION.C_NETPRICE AS NewHeading3
FROM ((T_PRODUCT
INNER JOIN T_PRODUCT_NUTRITIONALINFORMATION ON T_PRODUCT.C_NUTRITIONALINFORMATION = T_PRODUCT_NUTRITIONALINFORMATION.C_ID)
INNER JOIN T_PRODUCT_SELLING_PRICEDEFINITION ON T_PRODUCT.C_SELLING = T_PRODUCT_SELLING_PRICEDEFINITION.C__OWNER_)
WHERE C_CODE LIKE 'STK000832'
UNION ALL
SELECT T_PRODUCT_NUTRITIONALINFORMATION.C_ENERGY_KJ AS NewHeading1,
T_PRODUCT_NUTRITIONALINFORMATION.C_CARBOHYDRATESOFWHICHARESUGAR AS NewHeading2,
T_PRODUCT_SELLING_PRICEDEFINITION.C_NETPRICE AS NewHeading3
FROM ((T_PRODUCT
INNER JOIN T_PRODUCT_NUTRITIONALINFORMATION ON T_PRODUCT.C_NUTRITIONALINFORMATION = T_PRODUCT_NUTRITIONALINFORMATION.C_ID)
INNER JOIN T_PRODUCT_SELLING_PRICEDEFINITION ON T_PRODUCT.C_SELLING = T_PRODUCT_SELLING_PRICEDEFINITION.C__OWNER_)
WHERE C_CODE LIKE 'STK000832';

Problem with the joining of SQL tables via relationships

I am currently having problems trying the run a query for some tables.
Below is what I am trying to do, I just can't seem to get it to work.
I have also duplicated constituent and gifts to show you the relations between soft credit and gifts/constituents
Link to Table Relations Image
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
INNER JOIN dbo.Constituent Constituent
ON Constituent.id = Gifts.constituent_id
INNER JOIN dbo.SplitGifts SplitGifts
ON SplitGifts.giftid = Gifts.id
LEFT JOIN dbo.SoftCredit SoftCredit
ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Constituent Constituent_1
ON Constituent_1.id = SoftCredit.constituentid
INNER JOIN dbo.Gifts Gifts_1
ON Gifts_1.id = SoftCredit.giftid
INNER JOIN dbo.Package Package
ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
Basically, I want the
amount and gift_aid_amount from [SplitGifts]
Constituent Name & lookup_id from [constituent] to show up for all Gifts however if a soft credit exists for that gift I need it to get the same fields via the [SoftCredit] table -> Gifts -> SplitGifts -> Fields
You could try if the query below works.
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
LEFT JOIN dbo.SoftCredit SoftCredit ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Gifts Gifts_1 ON
Gifts_1.id = SoftCredit.giftid OR
(SoftCredit.giftid IS NULL AND Gifts_1.id = Gifts.id)
INNER JOIN dbo.Constituent Constituent ON
Constituent.id = SoftCredit.constituentid OR
(SoftCredit.constituentid IS NULL AND Constituent.id = Gifts_1.constituent_id)
INNER JOIN dbo.SplitGifts SplitGifts ON SplitGifts.giftid = Gifts_1.id
INNER JOIN dbo.Package Package ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
It joins back to table Gifts (using alias Gifts_1) on the gift reference in SoftCredit or to itself if there is no SoftCredit.
Table Constituent is joined in a similar fashion: it joins on the value of SoftCredit.constituentid and when NULL, it falls back to Gifts_1.constituent_id.
All next joins regarding the gift should refer to Gifts_1 then.
I have not tested it though. But it might give you a hint in a possible solution direction.

How to combine 2 sql statements

I am trying to retrieve data for a client from an old database that they have. The data I need is a mix of these 2 sql statements. How would I combine them to get all the data from the enrol_stud table and Stud_Haddress table in the second statement.
Statement 1 - I want all the data from Enrol_Stud and Stud_Haddress included in statement 2
select enrol_stud.*, stud_haddress.*
from enrol_stud_forms
inner join enrol_stud on enrol_stud_forms.student_id = enrol_stud.student_id
Statement 2 I want the data from the 2 tables above included in the statement below.
SELECT contact.*, vsmc.*, concarer1.*, salcarer2.*, contact.firstname ||'
'||contact.surname as STUDENT, salcarer1.salutation as CARER1_TITLE, concarer1.firstname as CARER1_FIRSTNAME, concarer1.surname as CARER1_SURNAME, concarer1.email_address as CARER1_EMAIL, salcarer2.salutation as CARER2_TITLE, concarer2.firstname as CARER2_FIRSTNAME, concarer2.surname as CARER2_SURNAME, concarer2.email_address as CARER2_EMAIL
FROM get_currently_enroled_students ('now') gces
INNER JOIN student on gces.student_id = student.student_id
INNER JOIN contact on student.contact_id=contact.contact_id
INNER JOIN view_Student_mail_carers vsmc on student.student_id=vsmc.student_id
INNER JOIN contact concarer1 on vsmc.carer1_contact_id=concarer1.contact_id
INNER JOIN contact concarer2 on vsmc.carer2_contact_id=concarer2.contact_id
INNER JOIN salutation salcarer1 on concarer1.salutation_id=salcarer1.salutation_id
INNER JOIN salutation salcarer2 on concarer2.salutation_id=salcarer2.salutation_id
ORDER BY contact.surname, contact.firstname
I know it is in the joins, I just can't work out how to include them.
You can try like below, include the columns from first statement per post as well include the joins as pointed below
SELECT contact.*,
vsmc.*,
enrol_stud.*, <- here
stud_haddress.*, <-here
concarer1.*,
salcarer2.*,
contact.firstname ||' '||contact.surname as STUDENT,
salcarer1.salutation as CARER1_TITLE,
concarer1.firstname as CARER1_FIRSTNAME,
concarer1.surname as CARER1_SURNAME,
concarer1.email_address as CARER1_EMAIL,
salcarer2.salutation as CARER2_TITLE,
concarer2.firstname as CARER2_FIRSTNAME,
concarer2.surname as CARER2_SURNAME,
concarer2.email_address as CARER2_EMAIL
FROM get_currently_enroled_students ('now') gces
INNER JOIN enrol_stud_forms on gces.student_id = enrol_stud_forms.student_id <- here
INNER JOIN enrol_stud on enrol_stud.student_id = gces.student_id <- here
INNER JOIN student on gces.student_id = student.student_id
INNER JOIN contact on student.contact_id=contact.contact_id
INNER JOIN view_Student_mail_carers vsmc on student.student_id=vsmc.student_id
INNER JOIN contact concarer1 on vsmc.carer1_contact_id=concarer1.contact_id
INNER JOIN contact concarer2 on vsmc.carer2_contact_id=concarer2.contact_id
INNER JOIN salutation salcarer1
on concarer1.salutation_id=salcarer1.salutation_id
INNER JOIN salutation salcarer2
on concarer2.salutation_id=salcarer2.salutation_id
ORDER BY contact.surname, contact.firstname

Super Slow Query - sped up, but not perfect... Please help

I posted a query yesterday (see here) that was horrible (took over a minute to run, resulting in 18,215 records):
SELECT DISTINCT
dbo.contacts_link_emails.Email, dbo.contacts.ContactID, dbo.contacts.First AS ContactFirstName, dbo.contacts.Last AS ContactLastName, dbo.contacts.InstitutionID,
dbo.institutionswithzipcodesadditional.CountyID, dbo.institutionswithzipcodesadditional.StateID, dbo.institutionswithzipcodesadditional.DistrictID
FROM
dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_3
INNER JOIN
dbo.contacts
INNER JOIN
dbo.contacts_link_emails
ON dbo.contacts.ContactID = dbo.contacts_link_emails.ContactID
ON contacts_def_jobfunctions_3.JobID = dbo.contacts.JobTitle
INNER JOIN
dbo.institutionswithzipcodesadditional
ON dbo.contacts.InstitutionID = dbo.institutionswithzipcodesadditional.InstitutionID
LEFT OUTER JOIN
dbo.contacts_def_jobfunctions
INNER JOIN
dbo.contacts_link_jobfunctions
ON dbo.contacts_def_jobfunctions.JobID = dbo.contacts_link_jobfunctions.JobID
ON dbo.contacts.ContactID = dbo.contacts_link_jobfunctions.ContactID
WHERE
(dbo.contacts.JobTitle IN
(SELECT JobID
FROM dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_1
WHERE (ParentJobID <> '1841')))
AND
(dbo.contacts_link_emails.Email NOT IN
(SELECT EmailAddress
FROM dbo.newsletterremovelist))
OR
(dbo.contacts_link_jobfunctions.JobID IN
(SELECT JobID
FROM dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_2
WHERE (ParentJobID <> '1841')))
AND
(dbo.contacts_link_emails.Email NOT IN
(SELECT EmailAddress
FROM dbo.newsletterremovelist AS newsletterremovelist))
ORDER BY EMAIL
With a lot of coaching and research, I've tuned it up to the following:
SELECT contacts.ContactID,
contacts.InstitutionID,
contacts.First,
contacts.Last,
institutionswithzipcodesadditional.CountyID,
institutionswithzipcodesadditional.StateID,
institutionswithzipcodesadditional.DistrictID
FROM contacts
INNER JOIN contacts_link_emails ON
contacts.ContactID = contacts_link_emails.ContactID
INNER JOIN institutionswithzipcodesadditional ON
contacts.InstitutionID = institutionswithzipcodesadditional.InstitutionID
WHERE
(contacts.ContactID IN
(SELECT contacts_2.ContactID
FROM contacts AS contacts_2
INNER JOIN contacts_link_emails AS contacts_link_emails_2 ON
contacts_2.ContactID = contacts_link_emails_2.ContactID
LEFT OUTER JOIN contacts_def_jobfunctions ON
contacts_2.JobTitle = contacts_def_jobfunctions.JobID
RIGHT OUTER JOIN newsletterremovelist ON
contacts_link_emails_2.Email = newsletterremovelist.EmailAddress
WHERE (contacts_def_jobfunctions.ParentJobID <> 1841)
GROUP BY contacts_2.ContactID
UNION
SELECT contacts_1.ContactID
FROM contacts_link_jobfunctions
INNER JOIN contacts_def_jobfunctions AS contacts_def_jobfunctions_1 ON
contacts_link_jobfunctions.JobID = contacts_def_jobfunctions_1.JobID
AND contacts_def_jobfunctions_1.ParentJobID <> 1841
INNER JOIN contacts AS contacts_1 ON
contacts_link_jobfunctions.ContactID = contacts_1.ContactID
INNER JOIN contacts_link_emails AS contacts_link_emails_1 ON
contacts_link_emails_1.ContactID = contacts_1.ContactID
LEFT OUTER JOIN newsletterremovelist AS newsletterremovelist_1 ON
contacts_link_emails_1.Email = newsletterremovelist_1.EmailAddress
GROUP BY contacts_1.ContactID))
While this query is now super fast (about 3 seconds), I've blown part of the logic somewhere - it only returns 14,863 rows (instead of the 18,215 rows that I believe is accurate).
The results seem near correct. I'm working to discover what data might be missing in the result set.
Can you please coach me through whatever I've done wrong here?
Thanks,
Russell Schutte
The main problem with your original query was that you had two extra joins just to introduce duplicates and then a DISTINCT to get rid of them.
Use this:
SELECT cle.Email,
c.ContactID,
c.First AS ContactFirstName,
c.Last AS ContactLastName,
c.InstitutionID,
izip.CountyID,
izip.StateID,
izip.DistrictID
FROM dbo.contacts c
INNER JOIN
dbo.institutionswithzipcodesadditional izip
ON izip.InstitutionID = c.InstitutionID
INNER JOIN
dbo.contacts_link_emails cle
ON cle.ContactID = c.ContactID
WHERE cle.Email NOT IN
(
SELECT EmailAddress
FROM dbo.newsletterremovelist
)
AND EXISTS
(
SELECT NULL
FROM dbo.contacts_def_jobfunctions cdj
WHERE cdj.JobId = c.JobTitle
AND cdj.ParentJobId <> '1841'
UNION ALL
SELECT NULL
FROM dbo.contacts_link_jobfunctions clj
JOIN dbo.contacts_def_jobfunctions cdj
ON cdj.JobID = clj.JobID
WHERE clj.ContactID = c.ContactID
AND cdj.ParentJobId <> '1841'
)
ORDER BY
email
Create the following indexes:
newsletterremovelist (EmailAddress)
contacts_link_jobfunctions (ContactID, JobID)
contacts_def_jobfunctions (JobID)
Do you get the same results when you do:
SELECT count(*)
FROM
dbo.contacts_def_jobfunctions AS contacts_def_jobfunctions_3
INNER JOIN
dbo.contacts
INNER JOIN
dbo.contacts_link_emails
ON dbo.contacts.ContactID = dbo.contacts_link_emails.ContactID
ON contacts_def_jobfunctions_3.JobID = dbo.contacts.JobTitle
SELECT COUNT(*)
FROM
contacts
INNER JOIN contacts_link_jobfunctions
ON contacts.ContactID = contacts_link_jobfunctions.ContactID
INNER JOIN contacts_link_emails
ON contacts.ContactID = contacts_link_emails.ContactID
If so keep adding each join conditon on until you don't get the same results and you will see where your mistake was. If all the joins are the same, then look at the where clauses. But I will be surprised if it isn't in the first join because the syntax you have orginally won't even work on SQL Server and it is pretty nonstandard SQL and may have been incorrect all along but no one knew.
Alternatively, pick a few of the records that are returned in the orginal but not the revised. Track them through the tables one at a time to see if you can find why the second query filters them out.
I'm not directly sure what is wrong, but when I run in to this situation, the first thing I do is start removing variables.
So, comment out the where clause. How many rows are returned?
If you get back the 11,604 rows then you've isolated the problems to the joins. Work though the joins, commenting each one out (remove the associated columns too) and figure out how many rows are eliminated.
As you do this, aim to find what is causing the desired rows to be eliminated. Once isolated, consider the join differences between the first query and the second query.
In looking at the first query, you could probably just modify that to eliminate any INs and instead do a EXISTS instead.
Consider your indexes as well. Any thing in the where or join clauses should probably be indexed.

Top 1 on Left Join SubQuery

I am trying to take a person and display their current insurance along with their former insurance. I guess one could say that I'm trying to flaten my view of customers or people. I'm running into an issue where I'm getting multiple records back due to multiple records existing within my left join subqueries. I had hoped I could solve this by adding "TOP 1" to the subquery, but that actually returns nothing...
Any ideas?
SELECT
p.person_id AS 'MIRID'
, p.firstname AS 'FIRST'
, p.lastname AS 'LAST'
, pg.name AS 'GROUP'
, e.name AS 'AOR'
, p.leaddate AS 'CONTACT DATE'
, [dbo].[GetPICampaignDisp](p.person_id, '2009') AS 'PI - 2009'
, [dbo].[GetPICampaignDisp](p.person_id, '2008') AS 'PI - 2008'
, [dbo].[GetPICampaignDisp](p.person_id, '2007') AS 'PI - 2007'
, a_disp.name AS 'CURR DISP'
, a_ins.name AS 'CURR INS'
, a_prodtype.name AS 'CURR INS TYPE'
, a_t.date AS 'CURR INS APP DATE'
, a_t.effdate AS 'CURR INS EFF DATE'
, b_disp.name AS 'PREV DISP'
, b_ins.name AS 'PREV INS'
, b_prodtype.name AS 'PREV INS TYPE'
, b_t.date AS 'PREV INS APP DATE'
, b_t.effdate AS 'PREV INS EFF DATE'
, b_t.termdate AS 'PREV INS TERM DATE'
FROM
[person] p
LEFT OUTER JOIN
[employee] e
ON
e.employee_id = p.agentofrecord_id
INNER JOIN
[dbo].[person_physician] pp
ON
p.person_id = pp.person_id
INNER JOIN
[dbo].[physician] ph
ON
ph.physician_id = pp.physician_id
INNER JOIN
[dbo].[clinic] c
ON
c.clinic_id = ph.clinic_id
INNER JOIN
[dbo].[d_Physgroup] pg
ON
pg.d_physgroup_id = c.physgroup_id
LEFT OUTER JOIN
(
SELECT
tr1.*
FROM
[transaction] tr1
LEFT OUTER JOIN
[d_vendor] ins1
ON
ins1.d_vendor_id = tr1.d_vendor_id
LEFT OUTER JOIN
[d_product_type] prodtype1
ON
prodtype1.d_product_type_id = tr1.d_product_type_id
LEFT OUTER JOIN
[d_commission_type] ctype1
ON
ctype1.d_commission_type_id = tr1.d_commission_type_id
WHERE
prodtype1.name <> 'Medicare Part D'
AND tr1.termdate IS NULL
) AS a_t
ON
a_t.person_id = p.person_id
LEFT OUTER JOIN
[d_vendor] a_ins
ON
a_ins.d_vendor_id = a_t.d_vendor_id
LEFT OUTER JOIN
[d_product_type] a_prodtype
ON
a_prodtype.d_product_type_id = a_t.d_product_type_id
LEFT OUTER JOIN
[d_commission_type] a_ctype
ON
a_ctype.d_commission_type_id = a_t.d_commission_type_id
LEFT OUTER JOIN
[d_disposition] a_disp
ON
a_disp.d_disposition_id = a_t.d_disposition_id
LEFT OUTER JOIN
(
SELECT
tr2.*
FROM
[transaction] tr2
LEFT OUTER JOIN
[d_vendor] ins2
ON
ins2.d_vendor_id = tr2.d_vendor_id
LEFT OUTER JOIN
[d_product_type] prodtype2
ON
prodtype2.d_product_type_id = tr2.d_product_type_id
LEFT OUTER JOIN
[d_commission_type] ctype2
ON
ctype2.d_commission_type_id = tr2.d_commission_type_id
WHERE
prodtype2.name <> 'Medicare Part D'
AND tr2.termdate IS NOT NULL
) AS b_t
ON
b_t.person_id = p.person_id
LEFT OUTER JOIN
[d_vendor] b_ins
ON
b_ins.d_vendor_id = b_t.d_vendor_id
LEFT OUTER JOIN
[d_product_type] b_prodtype
ON
b_prodtype.d_product_type_id = b_t.d_product_type_id
LEFT OUTER JOIN
[d_commission_type] b_ctype
ON
b_ctype.d_commission_type_id = b_t.d_commission_type_id
LEFT OUTER JOIN
[d_disposition] b_disp
ON
b_disp.d_disposition_id = b_t.d_disposition_id
WHERE
pg.d_physgroup_id = #PhysGroupID
In Sql server 2005 you can use OUTER APPLY
SELECT p.person_id, s.e.employee_id
FROM person p
OUTER APPLY (SELECT TOP 1 *
FROM Employee
WHERE /*JOINCONDITION*/
ORDER BY /*Something*/ DESC) s
http://technet.microsoft.com/en-us/library/ms175156.aspx
The pattern I normally use for this is:
SELECT whatever
FROM person
LEFT JOIN subtable AS s1
ON s1.personid = person.personid
...
WHERE NOT EXISTS
( SELECT 1 FROM subtable
WHERE personid = person.personid
AND orderbydate > s1.orderbydate
)
Which avoids the TOP 1 clause and maybe makes it a little clearer.
BTW, I like the way you've put this query together in general, except I'd leave out the brackets, assuming you have rationally named tables and columns; and you might even gain some performance (but at least elegance) by listing columns for tr1 and tr2, rather than "tr1.*" and "tr2.*".
Thanks for all of the feedback and ideas...
In the simplest of terms, I have a person table that stores contact information like name, email, etc. I have another table that stores transactions. Each transaction is really an insurance policy that would contain information on the provider, product type, product name, etc.
I want to avoid giving the user duplicate person records since this causes them to look for the duplicates prior to running mail merges, etc. I'm getting duplicates when there is more than 1 transaction that has not been terminated, and when there is more than 1 transaction that has been terminated.
Someone else suggested that I consider a cursor to grab my distinct contact records and then perform the sub selects to get the current and previous insurance information. I don't know if I want to head down that path though.
It's difficult to understand your question so first I'll throw this out there: does changing your SELECT to SELECT DISTINCT do what you want?
Otherwise, let me get this straight, you're trying to get your customers' current insurance and previous insurance, but they may actually have many insurances before that, recorded in the [transactions] table? I looked at your SQL for quite a few minutes but can't figure out what it all means, so could you please reduce it down to only the parts that are necessary? Then I'll think about it some more. It sounds to me like you need a GROUP BY somehow, but I can't work it out exactly yet.
Couldn't take the time to dig through all your SQL (what a beast!), here's an idea that might make things easier to handle:
select
p.person_id, p.name <and other person columns>,
(select <current policy columns>
from pol <and other tables for policy>
where pol.<columns for join> = p.person_id
and <restrictions for current policy>),
(select <previous policy columns>
from pol <and other tables for policy>
where pol.<columns for join> = p.person_id
and <restrictions for previouspolicy>),
<other columns>
from person p <and "directly related" tables>
This makes the statement easier to read by separating the different parts into their own subselects, and it also makes it easier to add a "Top 1" in without affecting the rest of the statement. Hope that helps.