SQL database - joining, but with nulls - sql

I'm having trouble with the following view (using SQL Server 2008). Basically, I've got three tables - tbl_PhysicalAsset (PA), tbl_Operations (OP) and tbl_Schedules (SC). One record in PA relates to many in OP, and one in OP to many in SC. The PA and OP are irrelevant here really, but the SC one is giving me problems.
I'm writing a query which displays the maximum done date from SC (basically done by grouping on the field which relates back to the OP, and the max of the done date), which is fair enough. I've also had to try and get the "Issues" column (a varchar) from the SC table too, in case there were issues. This is where it's falling down - some of the things in SC will not have a "done date" filled in (ie it will be null), but we still need to display the information.
The following is where I've got to:
SELECT TOP (100) PERCENT
dbo.tbl_PhysicalAsset.FKID_Contract, dbo.tbl_PhysicalAsset.MyLevel,
dbo.tbl_PhysicalAsset.L1_Name, dbo.tbl_PhysicalAsset.L2_Name,
dbo.tbl_PhysicalAsset.L3_Name, s1.FKID_Operation,
dbo.tbl_PhysicalAsset.Deleted AS Del1,
dbo.tbl_Operations.Deleted AS Del2, s1.Deleted AS Del3,
s1.SchedDone, s1.Issues
FROM
dbo.tbl_Schedules AS s1
INNER JOIN
dbo.tbl_Operations
INNER JOIN
dbo.tbl_PhysicalAsset ON dbo.tbl_Operations.FKID_PhysicalAsset = dbo.tbl_PhysicalAsset.PKID_PhysicalAsset
INNER JOIN
(SELECT
MAX(SchedDone) AS SchedDone, FKID_Operation
FROM
dbo.tbl_Schedules
GROUP BY
FKID_Operation) AS s2 ON dbo.tbl_Operations.PKID_Operation = s2.FKID_Operation ON s1.FKID_Operation = s2.FKID_Operation AND s1.SchedDone = s2.SchedDone
WHERE
(dbo.tbl_PhysicalAsset.FKID_Contract = 6)
AND (dbo.tbl_PhysicalAsset.MyLevel = 3)
AND (s1.FKID_Operation IS NOT NULL)
AND (dbo.tbl_PhysicalAsset.Deleted = 0)
AND (dbo.tbl_Operations.Deleted = 0)
AND (s1.Deleted = 0)
ORDER BY
dbo.tbl_PhysicalAsset.L1_Name, dbo.tbl_PhysicalAsset.L2_Name,
dbo.tbl_PhysicalAsset.L3_Name
As I say, if a record is missing a max done date then all information regarding it doesn't appear.
I've tried using left joins (and even right joins) but this makes no difference (and SQL Server normally tries to be helpful and makes them outer joins).

try now ....
SELECT PA.FKID_Contract
, PA.MyLevel
, PA.L1_Name
, PA.L2_Name
, PA.L3_Name
, s1.FKID_Operation
, PA.Deleted AS Del1
, OPS.Deleted AS Del2
, s1.Deleted AS Del3
, s1.SchedDone
, s1.Issues
FROM dbo.tbl_Schedules AS s1
INNER JOIN dbo.tbl_Operations OPS ON OPS.PKID_Operation = s1.FKID_Operation
INNER JOIN dbo.tbl_PhysicalAsset PA ON OPS.FKID_PhysicalAsset = PA.PKID_PhysicalAsset
INNER JOIN
(SELECT MAX(SchedDone) AS SchedDone, FKID_Operation
FROM dbo.tbl_Schedules
GROUP BY FKID_Operation) AS s2
ON s1.FKID_Operation = s2.FKID_Operation
AND s1.SchedDone = s2.SchedDone
WHERE (PA.FKID_Contract = 6)
AND (PA.MyLevel = 3)
AND (s1.FKID_Operation IS NOT NULL)
AND (PA.Deleted = 0)
AND (OPS.Deleted = 0)
AND (s1.Deleted = 0)
ORDER BY PA.L1_Name, PA.L2_Name, PA.L3_Name

Okay, this was my bad. I made a mistake with some of my deleted fields. Turns out that the original solution was pretty much spot-on and I was looking for anything that contained a False in the Deleted column (in my case, s1). However, I hadn't thought that, if a record can't be found, it will of course not have a False. So I moved which table I was checking for the Deleted schedules to s2 and just used the Schedules table:
SELECT TOP (100) PERCENT dbo.tbl_PhysicalAsset.FKID_Contract, dbo.tbl_PhysicalAsset.MyLevel, dbo.tbl_PhysicalAsset.L1_Name, dbo.tbl_PhysicalAsset.L2_Name,
dbo.tbl_PhysicalAsset.L3_Name, dbo.tbl_PhysicalAsset.Deleted AS Del1, dbo.tbl_Operations.Deleted AS Del2, s2.SchedDone, s2.Deleted, tbl_Schedules_1.Issues,
tbl_Schedules_1.Deleted AS Expr1
FROM dbo.tbl_Operations INNER JOIN
dbo.tbl_PhysicalAsset ON dbo.tbl_Operations.FKID_PhysicalAsset = dbo.tbl_PhysicalAsset.PKID_PhysicalAsset INNER JOIN
(SELECT MAX(SchedDone) AS SchedDone, FKID_Operation, Deleted
FROM dbo.tbl_Schedules
GROUP BY FKID_Operation, Deleted) AS s2 ON dbo.tbl_Operations.PKID_Operation = s2.FKID_Operation LEFT OUTER JOIN
dbo.tbl_Schedules AS tbl_Schedules_1 ON s2.SchedDone = tbl_Schedules_1.SchedDone AND s2.FKID_Operation = tbl_Schedules_1.FKID_Operation
WHERE (dbo.tbl_PhysicalAsset.FKID_Contract = 6) AND (dbo.tbl_PhysicalAsset.MyLevel = 3) AND (dbo.tbl_PhysicalAsset.Deleted = 0) AND (dbo.tbl_Operations.Deleted = 0)
AND (s2.Deleted = 0)
ORDER BY dbo.tbl_PhysicalAsset.L1_Name, dbo.tbl_PhysicalAsset.L2_Name, dbo.tbl_PhysicalAsset.L3_Name

Related

Speed up SQL query performance with nested queries

Could anyone help me speed this query up? It currently take 17 minutes to run but does return the correct data and it populates a subform in MS Access. Functions in the rest of the VBA are declared as long to try to speed up more.
Here's the full query:
SELECT lots of things
FROM (((((((((((((((ngstest
INNER JOIN patients
ON ngstest.internalpatientid = patients.internalpatientid)
INNER JOIN referral
ON ngstest.referralid = referral.referralid)
INNER JOIN checker
ON ngstest.bookby = checker.check1id)
INNER JOIN ngspanel
ON ngstest.ngspanelid = ngspanel.ngspanelid)
LEFT JOIN ngspanel AS ngspanel_1
ON ngstest.ngspanelid_b = ngspanel_1.ngspanelid)
INNER JOIN status
ON ngstest.statusid = status.statusid)
INNER JOIN dbo_patient_table
ON patients.patientid = dbo_patient_table.patienttrustid)
LEFT JOIN dna
ON ngstest.dna = dna.dnanumber)
INNER JOIN status AS status_1
ON patients.s_statusoverall = status_1.statusid)
LEFT JOIN gw_gendertable
ON dbo_patient_table.genderid = gw_gendertable.genderid)
LEFT JOIN ngswesbatch
ON ngstest.wesbatch = ngswesbatch.ngswesbatchid)
LEFT JOIN checker AS checker_1
ON ngstest.check1id = checker_1.check1id)
LEFT JOIN checker AS checker_2
ON ngstest.check2id = checker_2.check1id)
LEFT JOIN checker AS checker_3
ON ngstest.check3id = checker_3.check1id)
LEFT JOIN ngspanel AS ngspanel_2
ON ngstest.ngspanelid_c = ngspanel_2.ngspanelid)
LEFT JOIN checker AS checker_4
ON ngstest.check4id = checker_4.check1id
WHERE ((ngstest.referralid IN
(SELECT referralid FROM referral
WHERE grouptypeid = 14)
AND ngstest.ngstestid IN
(SELECT ngstest.ngstestid
FROM ngsanalysis
INNER JOIN ngstest
ON ngsanalysis.ngstestid = ngstest.ngstestid
WHERE ngsanalysis.pedigree = 3302) )
AND status.statusid = 1202218800)
ORDER BY ngstest.priority,
ngstest.daterequested;
The two nested queries are strings from elsewhere in the code so are called in the vba as " & includereferralls & " And " & ParentsStatusesFilter & "
They are:
ParentsStatusesFilter = "NGSTest.NGSTestID in
(SELECT NGSTest.NGSTestID
FROM NGSAnalysis
INNER JOIN NGSTest
ON NGSAnalysis.NGSTestID = NGSTest.NGSTestID
WHERE NGSAnalysis.Pedigree IN (3302,3303,3304)"
And
includereferrals = "NGSTest.ReferralID
(SELECT referralid FROM referral WHERE referral.grouptypeid = 14)"
The query needs to remain readable (and therefore editable) so can't use things like Distinct, Group By or contain any Unions. Have tried Exists instead of In for the nested queries but that stops it from actually filtering the results.
WHERE EXISTS (SELECT NGSTest.NGSTestID
FROM NGSAnalysis
INNER JOIN NGSTest
ON NGSAnalysis.NGSTestID = NGSTest.NGSTestID
WHERE NGSAnalysis.Pedigree IN (3302,3303,3304)
So the exist clause you have there isn't tied to the outer query which would run similar to just added 1 = 1 to the where clause. I took your where clause and converted it. It should look something like this...
WHERE EXISTS (
SELECT referralid
FROM referral
WHERE grouptypeid = 14 AND ngstest.referralid = referral.referralid)
AND EXISTS (
SELECT ngsanalysis.ngstestid
FROM ngsanalysis
WHERE ngsanalysis.pedigree IN (3302,3303,3304) AND ngstest.ngstestid = ngsanalysis.ngstestid
)
AND status.statusid = 1202218800
Adding exists will speed it up a bit, but the the bulk of the slowness is the left joins. Access does not handle the left joins as well as SQL Server does. Change all your joins to inner joins and you will see the query runs very fast. This is obviously not ideal since some relationships are optional. What I have done to get around this is add a default record that replaces a null relationship.
Here is what that looks like for you: In the checker table you could add a record that represents a null value. So put a record into the checker table with check1id of -1 or 0. Then default check1id, check2id, check3id on ngstest to -1 or 0. You will need to do that type of thing for all tables you need to left join on.

NOT EXIST in a subquery, joined back to separate table

Running a report to figure out which parts in our system have not had an order within a certain period of time. Other minor aspects to this report, this is the main area I'm struggling. Best I could figure out is getting a list of parts that HAVE had orders during this time then comparing it back against the other table, but either my joins or subqueries are working correctly.
Does NOT EXIST work like this?
SELECT i.customer_no AS CustNumber,
i.part_no AS PartNumber,
p.cpt_prog_mat
FROM fit_part_info i
INNER JOIN fit_part_forecast f ON f.part_info_id = i.id
INNER JOIN orrcpt_rec p ON i.part_no = p.cpt_cus_part_no
WHERE (accounting_period = "201911" AND cpt_prog_mat = "Y") OR
(accounting_period = "201912" AND cpt_prog_mat = "Y") OR
(accounting_period = "202001" AND cpt_prog_mat = "Y") OR
(accounting_period = "202002" AND cpt_prog_mat = "Y") AND
NOT EXISTS (SELECT DISTINCT(i.part_no)
FROM INNER JOIN ortord_rec o ON i.part_no = o.ord_cus_part_no
WHERE (o.ord_comp_dt < 20191126 AND o.ord_comp_dt > 20190925 AND o.ord_cus_part_no <> ""))
GROUP BY i.part_no, i.customer_no, p.cpt_prog_mat
ORDER BY i.part_no;
it looks like you are missing the initial table name in the subselect.
try
NOT EXISTS (
SELECT 1
FROM fit_part_info i
INNER JOIN ortord_rec o ON i.part_no = o.ord_cus_part_no
WHERE
o.ord_comp_dt < 20191126
AND o.ord_comp_dt > 20190925
AND o.ord_cus_part_no <> ""
)
btw, you can use select 1 bc you don't actually need to select something if you are just checking for its existence

SQL Query with counts only returning equivalent counts

I have a query that consists of 1 table and 2 sub queries. The table being a listing of all customers, 1 sub query is a listing all of the quotes given over a period of time for customers and the other sub query is a listing of all of the orders booked for a customer over the same period of time. What I am trying to do is return a result set that is a customer, the number of quotes given, and the number of orders booked over a given period of time. However what I am returning is only a listening of customers over the period of time that have an equivalent quote and order count. I feel like I am missing something obvious within the context of the query but I am unable to figure it out. Any help would be appreciated. Thank you.
Result Set should look like this
Customer-------Quotes-------Orders Placed
aaa----------------4----------------4
bbb----------------9----------------18
ccc----------------18----------------9
select
[Customer2].[Name] as [Customer2_Name],
(count( Quotes.UD03_Key3 )) as [Calculated_CustomerQuotes],
(count( Customer_Bookings.OrderHed_OrderNum )) as [Calculated_CustomerBookings]
from Erp.Customer as Customer2
left join (select
[UD03].[Key3] as [UD03_Key3],
[UD03].[Key4] as [UD03_Key4],
[UD03].[Key1] as [UD03_Key1],
[UD03].[Date02] as [UD03_Date02]
from Ice.UD03 as UD03
inner join Ice.UD02 as UD02 on
UD03.Company = UD02.Company
And
CAST(CAST(UD03.Number09 AS INT) AS VARCHAR(30)) = UD02.Key1
left outer join Erp.Customer as Customer on
UD03.Company = Customer.Company
And
UD03.Key1 = Customer.Name
left outer join Erp.SalesTer as SalesTer on
Customer.Company = SalesTer.Company
And
Customer.TerritoryID = SalesTer.TerritoryID
left outer join Erp.CustGrup as CustGrup on
Customer.Company = CustGrup.Company
And
Customer.GroupCode = CustGrup.GroupCode
where (UD03.Key3 <> '0')) as Quotes on
Customer2.Name = Quotes.UD03_Key1
left join (select
[Customer1].[Name] as [Customer1_Name],
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderDtl].[OrderLine] as [OrderDtl_OrderLine],
[OrderHed].[OrderDate] as [OrderHed_OrderDate]
from Erp.OrderHed as OrderHed
inner join Erp.Customer as Customer1 on
OrderHed.Company = Customer1.Company
And
OrderHed.BTCustNum = Customer1.CustNum
inner join Erp.OrderDtl as OrderDtl on
OrderHed.Company = OrderDtl.Company
And
OrderHed.OrderNum = OrderDtl.OrderNum) as Customer_Bookings on
Customer2.Name = Customer_Bookings.Customer1_Name
where Quotes.UD03_Date02 >= '5/15/2018' and Quotes.UD03_Date02 <= '5/15/2018' and Customer_Bookings.OrderHed_OrderDate >='5/15/2018' and Customer_Bookings.OrderHed_OrderDate <= '5/15/2018'
group by [Customer2].[Name]
You have several problems going on here. The first problem is your code is so poorly formatted it is user hostile to look at. Then you have left joins being logically treated an inner joins because of the where clause. You also have date literal strings in language specific format. This should always be the ANSI format YYYYMMDD. But in your case your two predicates are contradicting each other. You have where UD03_Date02 is simultaneously greater than and less than the same date. Thankfully you have =. But if your column is a datetime you have prevented any rows from being returned again (the first being your where clause). You have this same incorrect date logic and join in the second subquery as well.
Here is what your query might look like with some formatting so you can see what is going on. Please note I fixed the logical join issue. You still have the date problems because I don't know what you are trying to accomplish there.
select
[Customer2].[Name] as [Customer2_Name],
count(Quotes.UD03_Key3) as [Calculated_CustomerQuotes],
count(Customer_Bookings.OrderHed_OrderNum) as [Calculated_CustomerBookings]
from Erp.Customer as Customer2
left join
(
select
[UD03].[Key3] as [UD03_Key3],
[UD03].[Key4] as [UD03_Key4],
[UD03].[Key1] as [UD03_Key1],
[UD03].[Date02] as [UD03_Date02]
from Ice.UD03 as UD03
inner join Ice.UD02 as UD02 on UD03.Company = UD02.Company
And CAST(CAST(UD03.Number09 AS INT) AS VARCHAR(30)) = UD02.Key1
left outer join Erp.Customer as Customer on UD03.Company = Customer.Company
And UD03.Key1 = Customer.Name
left outer join Erp.SalesTer as SalesTer on Customer.Company = SalesTer.Company
And Customer.TerritoryID = SalesTer.TerritoryID
left outer join Erp.CustGrup as CustGrup on Customer.Company = CustGrup.Company
And Customer.GroupCode = CustGrup.GroupCode
where UD03.Key3 <> '0'
) as Quotes on Customer2.Name = Quotes.UD03_Key1
and Quotes.UD03_Date02 >= '20180515'
and Quotes.UD03_Date02 <= '20180515'
left join
(
select
[Customer1].[Name] as [Customer1_Name],
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderDtl].[OrderLine] as [OrderDtl_OrderLine],
[OrderHed].[OrderDate] as [OrderHed_OrderDate]
from Erp.OrderHed as OrderHed
inner join Erp.Customer as Customer1 on OrderHed.Company = Customer1.Company
And OrderHed.BTCustNum = Customer1.CustNum
inner join Erp.OrderDtl as OrderDtl on OrderHed.Company = OrderDtl.Company
And OrderHed.OrderNum = OrderDtl.OrderNum
) as Customer_Bookings on Customer2.Name = Customer_Bookings.Customer1_Name
and Customer_Bookings.OrderHed_OrderDate >= '20180515'
and Customer_Bookings.OrderHed_OrderDate <= '20180515'
group by [Customer2].[Name]
COUNT() will just give you the number of records. You'd expect this two result columns to be equal. Try structuring it like this:
SUM(CASE WHEN Quote.UD03_Key1 IS NOT NULL THEN 1 ELSE 0 END) AS QuoteCount,
SUM(CASE WHEN Customer_Bookings.Customer1_Name IS NOT NULL THEN 1 ELSE 0 END) AS custBookingCount

JOIN syntax and order for multiple tables

SQL Gurus,
I have a query that uses the "old" style of join syntax as follows using 7 tables (table and column names changed to protect the innocent), as shown below:
SELECT v1_col, p1_col
FROM p1_tbl, p_tbl, p2_tbl, p3_tbl, v1_tbl, v2_tbl, v3_tbl
WHERE p1_code = 1
AND v1_code = 1
AND p1_date >= v1_date
AND p_uid = p1_uid
AND p2_uid = p1_uid AND p2_id = v2_id
AND p3_uid = p1_uid AND p3_id = v3_id
AND v2_uid = v1_uid
AND v3_uid = v1_uid
The query works just fine and produces the results it is supposed to, but as an academic exercise, I tried to rewrite the query using the more standard JOIN syntax, for example, below is one version I tried:
SELECT V1.v1_col, P1.p1_col
FROM p1_tbl P1, v1_tbl V1
JOIN p_tbl P ON ( P.p_uid = P1.p1_uid )
JOIN p2_tbl P2 ON ( P2.p2_uid = P1.p1_uid AND P2.p2_id = V2.v2_id )
JOIN p3_tbl P3 ON ( P3.p3_uid = P1.p1_uid AND P3.p3_id = V3.v3_id )
JOIN v2_tbl V2 ON ( V2.v2_uid = V1.v1_uid )
JOIN v3_tbl V3 ON ( V3.v3_uid = V1.v1_uid )
WHERE P1.p1_code = 1
AND V1.v1_code = 1
AND P1.p1_date >= V1.v1_date
But, no matter how I arrange the JOINs (using MS SQL 2008 R2), I keep running into the error:
The Multi-part identifier "col-name" could not be bound,
where "col-name" varies depending on the order of the JOINs I am attempting...
Does anyone have any good examples on how use the JOIN syntax with this number of tables??
Thanks in advance!
When you use JOIN-syntax you can only access columns from tables in your current join or previous joins. In fact it's easier to write the old syntax, but it's more error-prone, e.g. you can easily forget a join-condition.
This should be what you want.
SELECT v1_col, p1_col
FROM p1_tbl
JOIN v1_tbl ON p1_date >= v1_date
JOIN v2_tbl ON v2_uid = v1_uid
JOIN v3_tbl ON v3_uid = v1_uid
JOIN p_tbl ON p_uid = p1_uid
JOIN p2_tbl ON p2_uid = p1_uid AND p2_id = v2_id
JOIN p3_tbl ON p3_uid = p1_uid AND p3_id = v3_id
WHERE p1_code = 1
AND v1_code = 1
You are not naming the tables in your join such that it doesn't know which column is from which table. Try something like:
SELECT a.v1_col, b.p1_col
FROM p1_tbl b
JOIN p_tbl a ON b.p_uid = a.p1_uid
WHERE b.p1_code = 1
From your query above, I am assuming a naming convention of p2_uid comes from p2_tbl. Below id my best interpretation of WHERE joins to using INNER joins.
SELECT
v1_col, p1_col
FROM
p1_tbl
INNER JOIN p1_tbl
ON p1_tbl.p1_date >= v1_tbl.v1_date
INNER JOIN p_tbl
ON p_tbl.p_uid = p1_tbl.p1_uid
INNER JOIN p2_tbl
ON p2_tbl.p2_uid = p1_tbl.p1_uid
INNER JOIN v2_tbl
ON p2_tbl.p2_id = v2_tbl.v2_id
INNER JOIN p3_tbl
ON p3_tbl.p3_uid = p1_tbl.p1_uid
INNER JOIN v3_tbl
ON p3_tbl.p3_id = v3_tbl.v3_id
INNER JOIN v1_tbl
ON v1_tbl.v1_uid = v2_tbl.v2_uid
AND v1_tbl.v1_uid = v3_tbl.v2_uid
WHERE
p1_code = 1
AND
v1_code = 1
Some general points I have found useful in SQL statements with many joins.
Always fully qualify the names. I.e dont use ID , rahter use
TableName.ID
Dont use aliases unless there is meaning. (I.e. joining a table to
its self where aliasing is needed.)

what is this code doing can not understand it

I am trying to figure out what a query is doing and I just do not understand why it would join its self to its self on multiple occassions highlighted bit is the piece i am talking about?
its the part that starts with the [SupplyStatusUpdated] = COALESCE( gas supply and gas supply history
USE [CRM];
SELECT gs.GasSupplyID,
[Account ID] = acc.AccountID,
[GMSReference] = cast(gms.SiteRefNum as varchar),
[AccountNumber] = cast(gms.AccountNum as varchar),
[Organisation Name] = prf.[Name] ,
con.DeclaredDate,
[Contract Date] = CAST(con.ContractDate AS DATE),
[Contract Version] = cv.Name,
[Contract Status] = cs.Name,
loa.ContractEndDate [LOA CED],
gs.CurrentSupplierEndDate [PrevSupplierEndDate],
loa.ContractEndDate,
con.StartDate,
[Supply Status] = gss.Name,
[SupplyStatusUpdated] = COALESCE(
(
SELECT TOP 1 MAX(gsh2.CreatedDate)
FROM GasSupply gs2
INNER JOIN GasSupplyHistory gsh2
ON gsh2.GasSupplyFK = gs2.GasSupplyID
WHERE gsh2.EventFK = 2
AND gsh2.Notes LIKE '%Gas Supply Status (%'
AND gsh2.GasSupplyFK = gs.GasSupplyID
GROUP BY gsh2.GasSupplyFK
),
(
SELECT TOP 1 MAX(gsh3.CreatedDate)
FROM GasSupplyHistory gsh3
INNER JOIN (
SELECT gsh4.GasSupplyFK, MAX(gsh4.EventFK) AS [MaxEvent]
FROM GasSupplyHistory gsh4
WHERE gsh4.GasSupplyFK = gs.GasSupplyID
GROUP BY gsh4.GasSupplyFK
HAVING MAX(gsh4.EventFK) = 1
) dt
ON dt.GasSupplyFK = gsh3.GasSupplyFK
)
),
[EAC] = gs.EstimatedAnnualConsumption,
[PreviousSupplier] = r.name,
[Branch] = b.name,
[LeadSource] = ls.name,
gs.UnitPrice,
gs.StandingCharge,
gs.WholesalePrice,
COALESCE(deal.weeknumber,DATEPART(ISOWK, con.[ContractDate])) AS [Week]
FROM acc.Account acc
INNER JOIN [Profile] prf
ON acc.ProfileFK = prf.ProfileID
INNER JOIN [Contract] con
ON acc.AccountID = con.AccountFK
INNER JOIN [loacontract] lo
ON lo.ContractFK = con.ContractID
LEFT join [LeadSource] ls
ON ls.LeadSourceID = con.LeadSourceFK
INNER JOIN [ContractStatus] cs
ON cs.ContractStatusID = con.ContractStatusFK
INNER JOIN [ContractVersion] cv
ON cv.ContractVersionID = con.ContractVersionFK
INNER JOIN GasSupply gs
ON gs.ContractFK = con.ContractID
INNER JOIN GasSupplyStatus gss
ON gss.GasSupplyStatusID = gs.GasSupplyStatusFK
LEFT JOIN Deal deal
ON deal.ContractFK = con.ContractID
OUTER APPLY GetGMSReferenceNumbers(con.ContractID) gms
LEFT JOIN Branch b
ON b.BranchID = deal.BranchFK
LEFT JOIN DealBroker bro
ON bro.DealFK = deal.DealID
AND bro.BrokerTypeFK = 36
LEFT JOIN Person p
ON p.PersonID = bro.EmployeeFK
LEFT JOIN Reseller r
ON r.ResellerID = gs.ResellerFK
LEFT JOIN (
SELECT l.contractfk,
MIN(l.contractenddate)[ContractEndDate]
FROM CRM.[contract].LOAContract l
GROUP BY l.ContractFK
) loa
ON loa.ContractFK = con.ContractID
WHERE acc.AccountID not in (
select AccountFK
from AccountOption
where OptionFK=9
)
AND cast(gms.SiteRefNum as varchar) IS NULL
COALESCE(Something, SomethingElse) says if the first argument is NULL, return the second argument (note that you can have more than 2 args and it'll just keep going down the list).
As such it's running the first sub-query, and if the result is NULL, returning the result of the second query. Why exactly is your business logic, which we can't answer :-)
(MSDN link on Coalesce)
COALESCE returns the first non-null value it finds, so if the GasSupply query returns a result it will use that: if that returns null it will see if the GasSupplyHistory query returns a result, and if so use that. If both queries return null then SupplyStatusUpdated will be null.
It joins to itself to get historical records from the same source as where it gets the current record.
Representation of historical data is is one common reason for using a BigData/NoSQL database instead of a SQL/Relational database.