Using Count() and Sum() correctly in SQL? - sql

Ok, so I hope I can explain this question well enough, because I feel like this is going to be a tough one.
I have two tables I'm working with today. These look like:
#pset table (PersonID int, SystemID int, EntitlementID int, TargetID int)
#Connector table (TargetName varchar(10), fConnector bit)
The first table stores records that tell me, oh this person has this system, which is composed of these entitlements, whom have these targets. A little complicated, but stay with me. The second stores the TargetName and then whether or not that target has a connector in my not-so-theoretical system.
What I'm trying to do is merge these two tables so that I can see the target flag for each row in #pset. This will help me later as you'll see.
If each entitlement in a system has a connector to the target (the flag is true for all of them), then I'd like to know.
All the others should go into a different table.
This is what I tried to do, but it didn't work. I need to know where I went wrong. Hopefully someone with more experience than me will be able to answer.
-- If the count(123) = 10 (ten rows with SystemID = 123) and the sum = 10, cool.
select pset.*, conn.fConnector from #pset pset
inner join vuTargets vt
on vt.TargetID = pset.TargetID
inner join #conn conn
on conn.TargetName = vt.TargetName
group by ProfileID, SystemRoleID, EntitlementID, TargetID, fConnector
having count(SystemID) = sum(cast(fConnector as int))
order by ProfileID
and
-- If the count(123) = 10 (ten rows with SystemID = 123) and the sum <> 10
select pset.*, conn.fConnector from #pset pset
inner join vuTargets vt
on vt.TargetID = pset.TargetID
inner join #conn conn
on conn.TargetName = vt.TargetName
group by ProfileID, SystemRoleID, EntitlementID, TargetID, fConnector
having count(SystemID) <> sum(cast(fConnector as int))
order by ProfileID
Unfortunately, these do not work :(
Edit
Here is a screenshot showing the problem. Notice ProfileID 1599 has a SystemID of 1126567, but one of the entitlements doesn't have a connector! How can I get both of these rows into the second query? (above)

Your basic problem is that you're trying to roll up to two different record sets.
The initial set (the SELECT and GROUP BY clauses) is saying that you want one record for every difference in the set [ProfileId, SystemId, EntitlementId, TargetId, fConnector].
The second set (the HAVING clause) is saying that you want, for every row in the inital set, to compare it's COUNT of records with the SUM of the connections. However, because you've asked for grouping down to the individual flag, this has the effect of getting a single row for each flag (assuming 1-to-1 relationships). Effectively, you're saying - 'Hey, if this target has a connection? Yeah, I want it'.
What you appear to want is a roll up to the SystemId value. To do that, you will need to change your SELECT and GROUP BY clauses to only include the set [ProfileId, SystemId]. This will return only those rows (keyed from profile and system) who has all targets 'connected'. You will not be able to see the individual entitlements, targets, and whether they are connected (you will be able to infer that they will all be/not be connected, however).
EDIT:
In the interests of full disclosure, here is how you'd get something similar to your original results set, where it lists all EntitlementIds and TargetIds:
WITH all_connections as (SELECT pset.ProfileId, pset.SystemRoleId
FROM #pset pset
INNER JOIN vuTargets vt
ON vt.TargetId = pset.TargetId
INNER JOIN #conn conn
ON conn.TargetName = vt.TargetName
GROUP BY pset.ProfileId, pset.SystemRoleId
HAVING COUNT(pset.SystemRoleId)
= SUM(CAST(fConnector as INT)))
SELECT pset.*
FROM #pset pset
JOIN all_connections conn
ON conn.ProfileId = pset.ProfileId
AND conn.SystemRoleId = pset.SystemRoleId
This should get you a listing, down to the TargetId, of ProfileId/SystemRoleId keys where all EntitlementIds and TargetIds have a connection (or, flip the CTE = to <> for those where not all do).

Edit: fixed my original queries, updated the description as well
You can split this up: first find the TargetIDs that have an fConnector of 0. Then find the PersonID, SystemID pairs that have any target equal to the ones you found. Then select the relevant data: (this finds the PersonID, SystemID pair where at least one entitlement does not have a connector to the target)
with abc as (
select PersonID, SystemID
from pset P
where TargetID in (
select TargetID
from vuTargets V join connector C on V.TargetName = C.TargetName
where C.fConnector = 0
)
)
select P.PersonID, P.SystemID, P.EntitlementID, P.TargetID, C.fConnector
from pset P
join abc on ((P.PersonID = abc.PersonID) and (P.SystemID = abc.SystemID))
join vuTargets V on P.TargetID = V.TargetID
join connector C on V.TargetName = C.TargetName
The query to find the PersonID, SystemID pairs where all entitlements have a connector to the target is similar:
with abc as (
select PersonID, SystemID
from pset P
where TargetID in (
select TargetID
from vuTargets V join connector C on V.TargetName = C.TargetName
where C.fConnector = 0
)
)
select P.PersonID, P.SystemID, P.EntitlementID, P.TargetID, C.fConnector
from
pset P
join abc on ((P.PersonID <> abc.PersonID) or (P.SystemID <> abc.SystemID))
join vuTargets V on P.TargetID = V.TargetID
join connector C on V.TargetName = C.TargetName
The difference is in the join with the temp table (<> vs =). This is very similar to zero's answer, but doesn't use counts or sums.

Related

Find a Subset of Records or Find All

I'm working on a similar problem to check if a column contains ALL the values of another column - Mysql
This CTE is part of a bigger query. CTE_ProjekteRollen contains a subset of ProjektParamRolle and can contain zero or more records. I want a list of ProjektParam where the items in CTE_ProjekteRollen are all present (when joined with ProjektParamRolle). My solution works in all cases where CTE_ProjektRollen is not empty.
CTE_FilteredByRolle as (
select pp.ID_ProjektParam
from Basis.ProjektParam pp
join Basis.ProjektParamRolle ppr
on pp.ID_ProjektParam = ppr.ID_ProjektParam
join CTE_ProjektRollen pr
on ppr.Rolle = pr.Rolle
group by pp.ID_ProjektParam
having Count(pp.ID_ProjektParam) = (
select Count(Rolle)
from CTE_ProjektRollen))
What do I have to change to get all ProjektParam (joined with ProjektParamRolle), if CTE_ProjektRollen is empty?
Edit: I think I phrased my question wrong, because I didn't understand it fully. #Kendle's solution works for what I described, but I actually needed all ID_ProjektParam (not joined with ProjektParamRolle).
The actual CTE that worked for me was
CTE_FilteredByRolle as (
select pp.ID_ProjektParam
from Basis.ProjektParam pp
where (
select Count(ppr.Rolle)
from Basis.ProjektParamRolle ppr
join CTE_ProjektRollen pr
on ppr.Rolle = pr.Rolle
where ppr.ID_ProjektParam = pp.ID_ProjektParam) = (
select Count(Rolle)
from CTE_ProjektRollen))
We can use a CASE to check whether the table is empty. If it is empty we return the number to which we are comparing, so it will always be true.
CTE_FilteredByRolle as (
select pp.ID_ProjektParam
from Basis.ProjektParam pp
join Basis.ProjektParamRolle ppr
on pp.ID_ProjektParam = ppr.ID_ProjektParam
join CTE_ProjektRollen pr
on ppr.Rolle = pr.Rolle
group by pp.ID_ProjektParam
having Count(distinct pp.ID_ProjektParam)
= case when(select Count(distinct Rolle) from CTE_ProjektRollen)) = 0
then Count(distinct pp.ID_ProjektParam)
else (select Count(distinct Rolle) from CTE_ProjektRollen))
end;

SQL View slow when filtered. Is there a clean way to improve performance?

Let me open with:
SHOWPLAN permission denied in database 'MyDatabase'.
With that out of the way, I'll layout my situation.
So, The database I work with has a view that executes fairly quickly.
SELECT * FROM MyView
returns 32 rows in 1 second and includes a non-indexed column of values (IDs) I need to filter on.
If I filter on these IDs directly in the view:
SELECT * FROM MyView WHERE MyView.SomeId = 18
Things slow immensely and it takes 21 seconds to return the 20 rows with that ID.
As an experiment I pushed the unfiltered results into a temporary table and executed the filtered query on the the temporary table:
IF OBJECT_ID('tempdb..#TEMP_TABLE') IS NOT NULL
BEGIN
DROP TABLE #TEMP_TABLE
END
SELECT * INTO #TEMP_TABLE
FROM MyView;
SELECT *
FROM #TEMP_TABLE
WHERE #TEMP_TABLE.SomeId = 18
DROP TABLE #TEMP_TABLE
And found that it returns the filtered results far faster (roughly 1 second)
Is there a cleaner syntax or pattern that can be implemented to achieve the same performance?
UPDATE: View Definition and Description
Manually obfuscated, but I was careful so hopefully there aren't many errors. Still waiting on SHOWPLAN permissions, so Execution Plan is still pending.
The view's purpose is to provide a count of all the records that belong to a specific component (CMP.COMPONENT_ID = '100') grouped by location.
"Belonging" is determined by the record's PROC_CODE (mapped through PROC_ID) being within the CMP's inclusion range (CMP_INCs) and not in the CMP's exclusion range (CMP_EXCs).
In practice, exclusion ranges are created for individual codes (the bounds are always equal) making it sufficient to check that the code is not equal a bound.
PROC_CODES can (and don't always) have an alphabetic prefix or suffix, which makes the ISNUMERIC() comparison necessary.
Records store PROC_IDs for their PROC_CODEs, so it's necessary to convert the CMP's PROC_CODE ranges into a set of PROC_IDs for identifying which records belong to that component
The performance issue occurs when trying to filter by DEPARTMENT_ID or LOCATION_ID
[CO_RECORDS] is also a view, but if it's that deep I'm going turf this to someone with less red tape to fight through.
CREATE VIEW [ViewsSchema].[MyView] AS
WITH
CMP_INCs AS (SELECT RNG.*, COALESCE(RNG.RANGE_END, RNG.RANGE_BEG) [SAFE_END] FROM DBEngine.DBO.DB_CMP_RANGE [RNG] WHERE [RNG].COMPONENT_ID = '100'),
CMP_EXCs AS (SELECT CER.* FROM DBEngine.DBO.DB_CMP_EXC_RANGE CER WHERE CER.COMPONENT_ID = '100'),
CMP_PROC_IDs AS (
SELECT
DBEngine_ProcTable.PROC_ID [CMP_PROC_ID],
DBEngine_ProcTable.PROC_CODE [CMP_PROC_CODE],
DB_CmpTable.COMPONENT_ID [CMP_ID],
MAX(DB_CmpTable.COMPONENT_NAME) [CMP_NAME]
FROM [DBEngine].DBO.DBEngine_ProcTable DBEngine_ProcTable
LEFT JOIN CMP_INCs ON ISNUMERIC(DBEngine_ProcTable.PROC_CODE) = ISNUMERIC(CMP_INCs.RANGE_BEG)
AND(DBEngine_ProcTable.PROC_CODE = CMP_INCs.RANGE_BEG
OR DBEngine_ProcTable.PROC_CODE BETWEEN CMP_INCs.RANGE_BEG AND CMP_INCs.SAFE_END)
INNER JOIN DBEngine.DBO.DB_CmpTable ON CMP_INCs.COMPONENT_ID = DB_CmpTable.COMPONENT_ID
LEFT JOIN CMP_EXCs EXCS ON EXCS.COMPONENT_ID = DB_CmpTable.COMPONENT_ID AND EXCS.EXCL_RANGE_END = DBEngine_ProcTable.PROC_CODE
WHERE EXCS.EXCL_RANGE_BEG IS NULL
GROUP BY
DBEngine_ProcTable.PROC_ID,
DBEngine_ProcTable.PROC_CODE,
DBEngine_ProcTable.BILL_DESC,
DBEngine_ProcTable.PROC_NAME,
DB_CmpTable.COMPONENT_ID
)
SELECT
RECORD.LOCATION_NAME [LOCATION_NAME]
, RECORD.LOCATION_ID [LOCATION_ID]
, MAX(RECORD.[Department]) [DEPARTMENT]
, RECORD.[Department ID] [DEPARTMENT_ID]
, SUM(RECORD.PROCEDURE_QUANTITY) [PROCEDURE_COUNT]
FROM DBEngineCUSTOMRPT.ViewsSchema.CO_RECORDS [RECORDS]
INNER JOIN CMP_PROC_IDs [CV] ON [CV].CMP_PROC_ID = [RECORDS].PROC_ID
CROSS JOIN (SELECT DATEADD(M, DATEDIFF(M, 0,GETDATE()), 0) [FIRSTOFTHEMONTH]) VARS
WHERE [RECORDS].TYPE = 1
AND ([RECORDS].VOID_DATE IS NULL OR [RECORDS].VOID_DATE >= VARS.[FIRSTOFTHEMONTH] )
AND [RECORDS].POST_DATE < VARS.[FIRSTOFTHEMONTH]
AND [RECORDS].DOS_MONTHS_BACK = 2
GROUP BY [RECORDS].LOCATION_NAME, [RECORDS].[Department ID]
GO
Based on the swift down votes, the answer to my question is
'No, there is not a clean syntax based solution for the improved
performance, and asking for one is ignorant of the declarative nature
of SQL you simple dirty plebeian'.
From the requests for the view's definition, it's clear that performance issues in simple queries should be addressed by fixing the structure of the objects being queried ('MyView' in this case) rather than syntactical gymnastics.
For interested parties the issue was resolved by adding a Row_Number() column to the final select in the view definition, wrapping it in a CTE, and using the new column in an always true filter while selecting the original columns.
I have no idea if this is the optimal solution. It doesn't feel good to me, but it appears to be working.
CREATE VIEW [ViewsSchema].[MyView] AS
WITH
CMP_INCs AS (SELECT RNG.*, COALESCE(RNG.RANGE_END, RNG.RANGE_BEG) [SAFE_END] FROM DBEngine.DBO.DB_CMP_RANGE [RNG] WHERE [RNG].COMPONENT_ID = '100'),
CMP_EXCs AS (SELECT CER.* FROM DBEngine.DBO.DB_CMP_EXC_RANGE CER WHERE CER.COMPONENT_ID = '100'),
CMP_PROC_IDs AS (
SELECT
DBEngine_ProcTable.PROC_ID [CMP_PROC_ID],
DBEngine_ProcTable.PROC_CODE [CMP_PROC_CODE],
DB_CmpTable.COMPONENT_ID [CMP_ID],
MAX(DB_CmpTable.COMPONENT_NAME) [CMP_NAME]
FROM [DBEngine].DBO.DBEngine_ProcTable DBEngine_ProcTable
LEFT JOIN CMP_INCs ON ISNUMERIC(DBEngine_ProcTable.PROC_CODE) = ISNUMERIC(CMP_INCs.RANGE_BEG)
AND(DBEngine_ProcTable.PROC_CODE = CMP_INCs.RANGE_BEG
OR DBEngine_ProcTable.PROC_CODE BETWEEN CMP_INCs.RANGE_BEG AND CMP_INCs.SAFE_END)
INNER JOIN DBEngine.DBO.DB_CmpTable ON CMP_INCs.COMPONENT_ID = DB_CmpTable.COMPONENT_ID
LEFT JOIN CMP_EXCs EXCS ON EXCS.COMPONENT_ID = DB_CmpTable.COMPONENT_ID AND EXCS.EXCL_RANGE_END = DBEngine_ProcTable.PROC_CODE
WHERE EXCS.EXCL_RANGE_BEG IS NULL
GROUP BY
DBEngine_ProcTable.PROC_ID,
DBEngine_ProcTable.PROC_CODE,
DBEngine_ProcTable.BILL_DESC,
DBEngine_ProcTable.PROC_NAME,
DB_CmpTable.COMPONENT_ID
),
RESULTS as (
SELECT
RECORD.LOCATION_NAME [LOCATION_NAME]
, RECORD.LOCATION_ID [LOCATION_ID]
, MAX(RECORD.[Department]) [DEPARTMENT]
, RECORD.[Department ID] [DEPARTMENT_ID]
, SUM(RECORD.PROCEDURE_QUANTITY) [PROCEDURE_COUNT]
, ROW_NUMBER() OVER (ORDER BY TDL.[Medical Department ID], TDL.[BILL_AREA_ID], TDL.JP_POS_NAME) [ROW]
FROM DBEngineCUSTOMRPT.ViewsSchema.CO_RECORDS [RECORDS]
INNER JOIN CMP_PROC_IDs [CV] ON [CV].CMP_PROC_ID = [RECORDS].PROC_ID
CROSS JOIN (SELECT DATEADD(M, DATEDIFF(M, 0,GETDATE()), 0) [FIRSTOFTHEMONTH]) VARS
WHERE [RECORDS].TYPE = 1
AND ([RECORDS].VOID_DATE IS NULL OR [RECORDS].VOID_DATE >= VARS.[FIRSTOFTHEMONTH] )
AND [RECORDS].POST_DATE < VARS.[FIRSTOFTHEMONTH]
AND [RECORDS].DOS_MONTHS_BACK = 2
GROUP BY [RECORDS].LOCATION_NAME, [RECORDS].[Department ID]
)
SELECT
[LOCATION_NAME]
, [LOCATION_ID]
, [DEPARTMENT]
, [DEPARTMENT_ID]
, [PROCEDURE_COUNT]
FROM RESULTS
WHERE [ROW] > 0
GO

How to find highest count of result set using multiple tables in SQL (Oracle)

I have four tables. Here are the skeletons...
ACADEMIC_TBL
academic_id
academic_name
AFFILIATION_TBL
academic_id*
institution_id*
joined_date
leave_date
INSTITUTION_TBL
institution_id
institution_name
REVIEW_TBL
academic_id*
institution_id*
date_posted
review_score
Using these tables I need to find the academic (displaying their name, not ID) with the highest number of reviews and the institution name (not ID) they are currently affiliated with. I imagine this will need to be done using multiple sub-select scripts but I'm having trouble figuring out how to structure it.
this will work:
SELECT at.academic_name,
it.institution_name,
Max(rt.review_score),
from academic_tbl at,
affiliation_tbl afft,
institution_tbl it,
review_tbl rt
WHERE AT.academic_id=afft.academic_id
AND afft.institution_id=it.institution_id
AND afft.academic_id=rt.academic_id
GROUP BY at.academia_name,it.instituton_id
You need an aggregated query that JOINs all 4 tables to count how many reviews were performed by each academic.
Query :
SELECT
inst.institution_name,
aca.academic_name,
COUNT(*)
FROM
academic_tbl aca
INNER JOIN affiliation_tbl aff ON aff.academic_id = aca.academic_id
INNER JOIN institution_tbl inst ON inst.institution_id = aff.institution_id
INNER JOIN review_tbl rev ON rev.academic_id = aca.academic_id AND rev.institution_id = aff.institution_id
GROUP BY
inst.institution_name,
aca.academic_name,
inst.institution_id,
aca.academic_id
NB :
added the academic and institution id to the GROUP BY clause to prevent potential academics or institutions having the same name from being (wrongly) grouped together
if the same academic performed reviews for different institutions, then you will find one row for each academic / institution couple, which, if I understood you right, is what you want
Try this one:
select
inst.institution_name
, aca.academic_name
from
academic_tbl aca
, institution_tbl inst
, affiliation_tbl aff
, review_tbl rev
, (
select
max(rt.review_score) max_score
from
review_tbl rt
, affiliation_tbl aff_inn
where
rt.date_posted >= aff_inn.join_date
and rt.date_posted <= aff_inn.leave_date
and rt.academic_id = aff_inn.academic_id
and rt.institution_id = aff_inn.institution_id
)
agg
where
aca.academic_id = inst.academic_id
and inst.institution_id = aff.institution_id
and aff.institution_id = rev.institution_id
and aff.academic_id = rev.academic_id
and rev.date_posted >= aff.join_date
and rev.date_posted <= aff.leave_date
and rev.review_score = agg.max_score
;
It might return more than one academic, if there are more with the same score (maximum one).

Handle Complex Query

I have following tables with their columns
tbAgent :- Agent, AgentX, AgentCode, NIPRNumber, PhysicalAddressState,
SystemUser
tbBroker :- Broker, BusinessName, BrokerCode,SystemUser
tbCompany :- Company, CompanyX
tbSystemUser :- SystemUser FirstName, LastName, EmailAddress
tbProduct :- Product, ProductX, ProductCode, Jurisdiction, CompanyId
tbLicence :- Licence, LicenceNumber,DateIssued,ExpirationDate,Jurisdiction,
StateIssued, BrokerId, AgentId
tbCompanyAgent :- CompanyId, AgentId, ProductId, LicenseNumber,
LicenseIssueDate,LicenceExpirationDate
tbBrokerAgent :- BrokerId, AgentId
tbJurisdiction :- Jurisdiction, JurisdictionX
In this project, we store Agents, Agencies (Brokers) and Companies in tbAgent, tbBroker and tbCompany respectively. We store Company's Products in tbProduct.
Thr Agent's LicenseDetails are stored in tbLicence. Agent's are appointed to Agencies(Brokers) and these details are stored in tbBrokerAgent.
Also Agents are appointed to Companies and these details are stored in tbCompanyAgent. The Agents are appointed to Companies, if Company's product's Jurisdiction matched with the Agent's License's Resident State or Non Resident state.
Note that Agent's has two type of licences stored in tbLicence, one is Resident and other is Non Resident Licenses. If it is Resident License, then the column name "Jurisdiction" contains 0 and If it is Non Resident License, then it contain actual Jurisdiction Id of State. If it contains 0 then we have to consider Agent's PhysicalAddressState as ResidentState.
All jurisdictions (States) are present in tbJurisdiction.
Now I have to create a view where I have to fetch the following Information
CompanyX
CompanyCode
BrokerX
BrokerCode
AgentX
Agentcode
NIPRNumber
ProductX
ProductCode
State
LicenceNumber
EffectiveDate
ExpirationDate
I have tried the following query
SELECT a.AgentCode,sy.AgentName,L.Licence,L.LicenceNumber,DateIssued as EffectiveDate,L.ExpirationDate,J.JurisdictionX as State
From tbAgent as a
INNER JOIN tbLicence L ON L.AgentId=a.Agent
LEFT OUTER JOIN (SELECT Jurisdiction,JurisdictionX FROM tbJurisdiction) as j on j.Jurisdiction=
(
CASE WHEN ISNULL(L.Jurisdiction,'0')='0' THEN a.PhysicalAddressState
ELSE
L.Jurisdiction
END
)
LEFT OUTER JOIN (SELECT SystemUser, (FirstName + ' '+LastName) as AgentName FROM tbSystemUser ) as sy on sy.SystemUser=a.SystemUser
The above query is fetching the following information
AgentX
Agentcode
NIPRNumber
State
LicenceNumber
EffectiveDate
ExpirationDate
Excluding the following columns
CompanyX
CompanyCode
BrokerX
BrokerCode
ProductX
ProductCode
I am not able to tweak the above query for fetching the excluding Column's information because the query is getting complex to handle...
Please help me !!!
If the question is about complexity, I hope CTE-technique will be a good tip for you:
;WITH cteJur as
(
SELECT
Jurisdiction,
JurisdictionX
FROM tbJurisdiction j
),
cteSysUsr as
(
SELECT
SystemUser,
(FirstName + ' '+LastName) as AgentName
FROM tbSystemUser su
),
cteAgent as
(
SELECT
a.AgentCode, a.SystemUser,
L.Licence, L.LicenceNumber,
L.DateIssued as EffectiveDate, L.ExpirationDate,
CASE
WHEN ISNULL(L.Jurisdiction,'0')='0'
THEN a.PhysicalAddressState
ELSE L.Jurisdiction
END as Jurisdiction
FROM tbAgent as a
INNER JOIN tbLicence L ON L.AgentId=a.Agent
)
SELECT
a.AgentCode, sy.AgentName,
a.Licence, a.LicenceNumber,
a.EffectiveDate, a.ExpirationDate,
J.JurisdictionX as State
FROM tbAgent as a
LEFT JOIN cteJur as j on j.Jurisdiction = a.Jurisdiction
LEFT JOIN cteSysUsr as sy on sy.SystemUser = a.SystemUser
If you were looking where to include your "excluded columns" - add them into appropriate CTE and reference them in final select. You don't have to put every joined table into a subquery. Just join it and reference table's columns in select list, that's it. Just as described in the query above.
First, you appear to have a good following of the tables and how related. I have tried to implement them and get ALL columns from the respective table(s). You can strip out whatever you want.
Now, first, I want you to look at the FROM clause section. Think of this before getting the columns, especially in a complex query of a lot of tables being joined. Take each one to the next. I always try to do my joins with the first table (or alias) as the left-side of the ON clause and the JOINING TO as the right-side... Then, if something is nested under the second, I keep the indentation going so I see the literal correlations more directly and have less chance of getting confused.
from
FirstTable alias1
JOIN SecondTable alias2
on alias1.IDColumn = alias2.IDColumn
JOIN ThirdTable alias3
on alias2.OtherID = alias3.OtherID
Now, in the case of your Jurisdictions, there are 3 possible places it CAN originate from... The agent, product and the license. Because I do not know which version you specifically want, I applied LEFT-JOINs to each one respectively. This allows me to use the same table multiple times with different aliases. Then I grab each JurisdictionX and call it an appropriate "as" name in the result.
Finally, I build out all the field columns that are wanted. If you wanted to narrow the list of data (such as a single broker) then you just apply the WHERE criteria. Hopefully this makes a lot of sense and you can strip out the extra fields you may not care about.
SELECT
a.Agent,
a.AgentX,
a.AgentCode,
a.NIPRNumber,
a.PhysicalAddressState,
a.SystemUser,
( AgUser.FirstName + ' '+ AgUser.LastName) as AgentName,
AgUser.EmailAddress as AgentEMail,
b.Broker,
b.BusinessName,
b.BrokerCode,
b.SystemUser as BrokerUser,
( BrUser.FirstName + ' '+ BrUser.LastName) as BrokerName,
BrUser.EmailAddress as BrokerEMail,
l.License,
l.LicenseNumber,
l.DateIssued,
l.ExpirationDate,
l.Jurisdiction,
l.StateIssued,
ca.LicenseNumber as CA_LicenseNumber,
ca.LicenseIssueDate as LicenseIssueDate,
ca.LicenseExpirationDate as LicenseExpirationDate,
c.Company,
c.CompanyX,
p.ProductX,
p.ProductCode,
AgJuris.JurisdictionX as AgentJurisdiction,
LicJuris.Jurisdiction as LicenseJurisdiction,
ProdJuris.Jurisdiction as ProductJurisdiction
from
tbAgent a
JOIN tbSystemUser AgUser
ON a.SystemUser = ag.SystemUser
JOIN tbLicense l
ON a.Agent = l.AgentID
JOIN tbBroker B
ON l.BrokerID = B.BrokerID
JOIN tbSystemUser BrUser
ON b.SystemUser = br.SystemUser
LEFT JOIN tbJurisdiction LicJuris
ON ISNULL(L.Jurisdiction,'0') = LicJuris.Jurisdiction
JOIN tbCompanyAgent ca
ON a.Agent = ca.AgentID
JOIN tbCompany c
ON ca.CompanyID = c.Company
JOIN tbProduct p
ON ca.CompanyID = p.CompanyID
AND ca.ProductID = p.Product
LEFT JOIN tbJurisdiction ProdJuris
ON p.Jurisdiction = ProdJuris.Jurisdiction
LEFT JOIN tbJurisdiction AgJuris
ON a.PhysicalAddressState = AgJuris.Jurisdiction
Additionally, for the issue on Jurisdictions, since you have all 3 POSSIBLE, you could add a last column such as
COALESCE( LicJuris.Jurisdiction, AgJuris.JurisdictionX ) as WhichJurisdiction
or considering all 3...
COALESCE( LicJuris.Jurisdiction, COALESCE( ProdJuris.Jurisdiction , AgJuris.JurisdictionX )) as WhichJurisdiction
So, if the license jurisdiction is not available, grab the value from product jurisdiction, if not that, fall back to the agent's jurisdiction.

SQL Server Query for Many to Many Relationship

I have the following Many to many relationship (See the picture below) in my SQL server.
In most cases there's are 2 rows in table tblWavelengths related to the table tblSensors, (in some cases only 1, and in extreme cases there can be 20 rows)
I made the following simple query to retrieve the data from those 3 tables :
select W.DateTimeID,S.SensorName,S.SensorType,W.Channel,W.PeakNr,W.Wavelength
from tblWavelengths as W
Left Join tblSensorWavelengths as SW on W.tblWavelengthID = SW.WavelengthID
Left Join tblSensors as S on SW.SensorID = S.SensorID
order by W.DateTimeID
After running this query I got the following results :
Here comes my problem. I want to write a query which filters only those Sensors (SensorName) which at a given moment in time (DateTimeID) has two rows (two different wavelengths) in the tblWavelengths table. So for example I want to have the results without
the 77902/001 Sensor - because it has only one row (one Wavelength) related to the tblSensors at a given moment in time
You could use a windowed function to find out the number of wavelengths for each sensorname/datetimeid combination:
WITH Data AS
( SELECT W.DateTimeID,
S.SensorName,
S.SensorType,
W.Channel,
W.PeakNr,
W.Wavelength,
[Wcount] = COUNT(*) OVER(PARTITION BY s.SensorName, d.DateTimeID)
from tblWavelengths as W
LEFT JOIN tblSensorWavelengths as SW
ON W.tblWavelengthID = SW.WavelengthID
LEFT JOIN tblSensors as S
ON SW.SensorID = S.SensorID
)
SELECT DateTimeID, SensorName, SensorType, Channel, PeakNr, WaveLength
FROM Data
WHERE Wcount = 2
ORDER BY DateTimeID;
ADDENDUM
As an after thought I realised that you might have two results for one sensor at the same time with the same wavelength, which would return 2 records, but not have two different wavelengths. Since windowed functions don't support the use of DISTINCT an alternative is below
WITH Data AS
( SELECT W.DateTimeID,
S.SensorName,
S.SensorType,
W.Channel,
W.PeakNr,
W.Wavelength,
W.tblWaveLengthID
from tblWavelengths as W
LEFT JOIN tblSensorWavelengths as SW
ON W.tblWavelengthID = SW.WavelengthID
LEFT JOIN tblSensors as S
ON SW.SensorID = S.SensorID
)
SELECT d.DateTimeID, d.SensorName, d.SensorType, d.Channel, d.PeakNr, d.WaveLength
FROM Data d
INNER JOIN
( SELECT DateTimeID, SensorName
FROM Data
GROUP BY DateTimeID, SensorName
HAVING COUNT(DISTINCT tblWaveLengthID) = 2
) t
ON t.DateTimeID = d.DateTimeID
AND t.SensorName = d.SensorName
ORDER BY d.DateTimeID;