Difference between IN and JOIN - sql

I was wondering what was the difference between the two queries mentioned below, because the first one takes more than 10 seconds to execute on the server and the second one executes in less than one second...
UPDATE - I
Here are the actual queries and their Execution Plans as copied and pasted from SQL Server (as is), sorry for any inconvenience caused by my previous queries... :(
SELECT REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS ManagmentPlanDate
FROM ManagmentPlan m
INNER JOIN Product p ON p.Product_ID = m.ProductID
INNER JOIN Category c ON c.C_ID = p.C_ID
LEFT OUTER JOIN Employee e ON e.emp_no = m.PrescribedBy
LEFT OUTER JOIN dbo.Issue_Stock i ON i.serial_no = m.IssueStockID
INNER JOIN dbo.Units u ON u.U_ID = p.U_ID
WHERE ( ( #PatientID IS NULL )
AND ( #VisitID IS NULL )
AND ( m.WardRegNo = #WardRegNo )
)
OR --Get only cuurent admission TP
( ( #PatientID IS NULL )
AND ( #WardRegNo IS NULL )
AND ( VisitID = #VisitID
AND m.WardRegNo IS NULL
)
)
OR -- Get Only Current OPD visit TP
( ( #WardRegNo IS NULL )
AND ( #VisitID IS NULL )
AND ( visitid IN ( SELECT id
FROM PatientVisit
WHERE PatientID = #PatientID ) )
)
OR --Get All Visits TP
( ( #PatientID IS NULL )
AND ( #VisitID IS NOT NULL )
AND ( #WardRegNo IS NOT NULL )
AND ( ( VisitID = #VisitID )
OR ( m.WardRegNo = #WardRegNo )
)
) -- Get Current OPD visit and cuurent admission TP (Both)
AND m.Deleted != 1
AND m.PatientDeptID = #PatientDeptID
GROUP BY REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-')
ORDER BY CAST(REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS DATETIME) DESC
and
SELECT REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS ManagmentPlanDate
FROM ManagmentPlan m
WHERE m.ProductID IN ( SELECT Product_ID
FROM Product
WHERE C_ID IN ( SELECT C_ID
FROM Category )
AND U_ID IN ( SELECT U_ID
FROM Units ) )
AND m.PrescribedBy IN ( SELECT Emp_no
FROM Employee )
AND m.IssueStockID IN ( SELECT Serial_No
FROM Issue_Stock )
AND ( ( #PatientID IS NULL )
AND ( #VisitID IS NULL )
AND ( m.WardRegNo = #WardRegNo )
)
OR --Get only cuurent admission TP
( ( #PatientID IS NULL )
AND ( #WardRegNo IS NULL )
AND ( VisitID = #VisitID
AND m.WardRegNo IS NULL
)
)
OR -- Get Only Current OPD visit TP
( ( #WardRegNo IS NULL )
AND ( #VisitID IS NULL )
AND ( visitid IN ( SELECT id
FROM PatientVisit
WHERE PatientID = #PatientID ) )
)
OR --Get All Visits TP
( ( #PatientID IS NULL )
AND ( #VisitID IS NOT NULL )
AND ( #WardRegNo IS NOT NULL )
AND ( ( VisitID = #VisitID )
OR ( m.WardRegNo = #WardRegNo )
)
) -- Get Current OPD visit and cuurent admission TP (Both)
AND m.Deleted != 1
AND m.PatientDeptID = #PatientDeptID
GROUP BY REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-')
ORDER BY CAST(REPLACE(CONVERT(VARCHAR(11), m.PlanDate, 106), ' ', '-') AS DATETIME) DESC
Although, it solved my problem of speed or optimization of the query, but just was curious as to what exactly is the difference between those two queries, as I thought the first one translates to the second one...
UPDATE - I
As you can see, both queries differ in only the JOINS converted to IN statements...

For one, your first statement retrieves all matching records from both the Products and Category tables whereas your second statement only retrieves all matching rows from Products.
What is the performance difference if you change your first statement to
SELECT p.*
FROM Products p
INNER JOIN Category c ON p.CatNo = c.CatNo
Edit
(as mentioned by Martin) note that the number of rows is only identical for both statements if CatNo is unique in the Category table. The INNER JOIN will return as many records as there are in the Category table whereas the IN statement will return as many records as there are unique CatNo in the Category table.

An in clause filters the rows that come back from product. An inner join adds columns from category to the select statement output.

Related

how to make a DISTINCT of STRING_AGG

I am trying to do a DISTINCT of the offerDetails column of the STRING_AGG function
OUTER APPLY
(
SELECT
STRING_AGG(CAST(co.OfferId AS NVARCHAR(MAX)), ';') AS OfferDetails,
STRING_AGG(CAST(ct.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
FROM ConferenceTransfer ct
INNER JOIN ConferenceOffer co ON ct.ConferenceId = co.ConferenceId
WHERE
ct.ConferenceTransferTypeId = 1 AND
ct.DateStarted IS NOT NULL AND
ct.CallerUserId = #agentId AND
ct.DateInitiated BETWEEN #dateFrom AND #dateTo
) CallTransfered
I'm not aware of any native way of making string_agg distinct, but you can ignore all but the first instance of each value by using a subquery and row_number to identify the first instance, i.e.
OUTER APPLY
(
SELECT
STRING_AGG(CAST(CASE WHEN c.RowNumber = 1 THEN c.OfferId END AS NVARCHAR(MAX)), ';') AS OfferDetails,
STRING_AGG(CAST(c.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
FROM ( SELECT co.OfferId,
ct.ConferenceId,
RowNumber = ROW_NUMBER() OVER(PARTITION BY co.OfferId ORDER BY ct.ConferenceId)
FROM ConferenceTransfer ct
INNER JOIN ConferenceOffer co
ON ct.ConferenceId = co.ConferenceId
WHERE
ct.ConferenceTransferTypeId = 1 AND
ct.DateStarted IS NOT NULL AND
ct.CallerUserId = #agentId AND
ct.DateInitiated BETWEEN #dateFrom AND #dateTo
) AS c
) CallTransfered
The key part being CASE WHEN c.RowNumber = 1 THEN c.OfferId END, so for anything other than the first instance, you are passing NULL, so the end result will only contain each OfferId once.
You need to group by OfferId, then group again
OUTER APPLY
(
SELECT
STRING_AGG(CAST(c.OfferId AS NVARCHAR(MAX)), ';') AS OfferDetails,
STRING_AGG(c.CustomTransferDetails, ';') AS CustomTransferDetails
FROM (
SELECT
co.OfferId,
STRING_AGG(CAST(ct.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
FROM ConferenceTransfer ct
INNER JOIN ConferenceOffer co ON ct.ConferenceId = co.ConferenceId
WHERE
ct.ConferenceTransferTypeId = 1 AND
ct.DateStarted IS NOT NULL AND
ct.CallerUserId = #agentId AND
ct.DateInitiated BETWEEN #dateFrom AND #dateTo
GROUP BY
co.OfferId
) c
) CallTransfered
This obviously only works for one DISTINCT. If you need both to be distinct, you can re-split the values, distinct them and re-aggregate
OUTER APPLY
(
SELECT
(
SELECT
STRING_AGG(s.value, ';')
FROM (
SELECT DISTINCT s.value
FROM STRING_SPLIT(OfferDetails, ';') s
) s
) AS OfferDetails,
(
SELECT
STRING_AGG(s.value, ';')
FROM (
SELECT DISTINCT s.value
FROM STRING_SPLIT(ConferenceId, ';') s
) s
) AS CustomTransferDetails
FROM (
SELECT
STRING_AGG(CAST(co.OfferId AS NVARCHAR(MAX)), ';') AS OfferDetails,
STRING_AGG(CAST(ct.ConferenceId AS NVARCHAR(MAX)), ';') AS CustomTransferDetails
FROM ConferenceTransfer ct
INNER JOIN ConferenceOffer co ON ct.ConferenceId = co.ConferenceId
WHERE
ct.ConferenceTransferTypeId = 1 AND
ct.DateStarted IS NOT NULL AND
ct.CallerUserId = #agentId AND
ct.DateInitiated BETWEEN #dateFrom AND #dateTo
GROUP BY
co.OfferId
) c
) CallTransfered

Avoid SQL Pivot returning duplicate rows

I have the following SQL script which returns duplciate values in PIVOT. How do I combine those duplicate records to one row.
Please check the below image for the results set.
SELECT *
FROM (SELECT X.stockcode,
X.description,
X.pack,
X.location,
X.lname,
X.qty,
Y.stockcode AS StockCode2,
y.periodname,
Y.months,
Y.saleqty
FROM (SELECT dbo.stock_items.stockcode,
dbo.stock_items.description,
dbo.stock_items.pack,
dbo.stock_loc_info.location,
dbo.stock_locations.lname,
dbo.stock_loc_info.qty
FROM dbo.stock_locations
INNER JOIN dbo.stock_loc_info
ON dbo.stock_locations.locno = dbo.stock_loc_info.location
LEFT OUTER JOIN dbo.stock_items
ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
WHERE ( dbo.stock_items.status = 's' )) AS X
LEFT OUTER JOIN (SELECT dbo.dr_invlines.stockcode,
( 12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate) ) % 12 + 1 AS Months,
Sum(dbo.dr_invlines.quantity) AS SaleQty,
dbo.period_status.periodname
FROM dbo.dr_trans
INNER JOIN dbo.period_status
ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
RIGHT OUTER JOIN dbo.dr_invlines
ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode
ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno
WHERE ( STOCK_ITEMS_1.status = 'S' )
AND ( dbo.dr_trans.transtype IN ( 1, 2 ) )
AND ( dbo.dr_trans.transdate >= Dateadd(m, -6, Getdate()) )
GROUP BY dbo.dr_invlines.stockcode,
Datepart(month, dbo.dr_trans.transdate),
dbo.period_status.periodname) AS Y
ON X.stockcode = Y.stockcode) z
PIVOT (Sum(saleqty) FOR [months] IN ([1],[2],[3],[4],[5],[6])) AS pivoted
EDIT: I missed the root-cause of your issue being the inclusion of the periodname column causing the percieved duplication. I am leaving this in place as general solution showing CTE usage, because it could still be useful if you then want to do extra filtering/transformation of your pivot results
One way is to take the results of the pivot query and run it through a SELECT DISTINCT query.
An example of wrapping your pivot query as a CTE and using it to feed a SELECT DISTINCT below (please note: untested, but parses as valid in my SSMS)
WITH PivotResults_CTE (
stockcode,
description,
pack,
location,
lname,
qty,
StockCode2,
periodname,
months,
saleqty
)
AS (
SELECT *
FROM (
SELECT X.stockcode
,X.description
,X.pack
,X.location
,X.lname
,X.qty
,Y.stockcode AS StockCode2
,y.periodname
,Y.months
,Y.saleqty
FROM (
SELECT dbo.stock_items.stockcode
,dbo.stock_items.description
,dbo.stock_items.pack
,dbo.stock_loc_info.location
,dbo.stock_locations.lname
,dbo.stock_loc_info.qty
FROM dbo.stock_locations
INNER JOIN dbo.stock_loc_info ON dbo.stock_locations.locno = dbo.stock_loc_info.location
LEFT OUTER JOIN dbo.stock_items ON dbo.stock_loc_info.stockcode = dbo.stock_items.stockcode
WHERE (dbo.stock_items.STATUS = 's')
) AS X
LEFT OUTER JOIN (
SELECT dbo.dr_invlines.stockcode
,(12 + Datepart(month, Getdate()) - Datepart(month, dbo.dr_trans.transdate)) % 12 + 1 AS Months
,Sum(dbo.dr_invlines.quantity) AS SaleQty
,dbo.period_status.periodname
FROM dbo.dr_trans
INNER JOIN dbo.period_status ON dbo.dr_trans.period_seqno = dbo.period_status.seqno
LEFT OUTER JOIN dbo.stock_items AS STOCK_ITEMS_1
RIGHT OUTER JOIN dbo.dr_invlines ON STOCK_ITEMS_1.stockcode = dbo.dr_invlines.stockcode ON dbo.dr_trans.seqno = dbo.dr_invlines.hdr_seqno WHERE (STOCK_ITEMS_1.STATUS = 'S')
AND (
dbo.dr_trans.transtype IN (
1
,2
)
)
AND (dbo.dr_trans.transdate >= Dateadd(m, - 6, Getdate()))
GROUP BY dbo.dr_invlines.stockcode
,Datepart(month, dbo.dr_trans.transdate)
,dbo.period_status.periodname
) AS Y ON X.stockcode = Y.stockcode
) z
PIVOT(Sum(saleqty) FOR [months] IN (
[1]
,[2]
,[3]
,[4]
,[5]
,[6]
)) AS pivoted
)
SELECT DISTINCT *
FROM
PivotResults_CTE
;
Also note, your sql included in the above may look slightly different to your original but that is only because i ran it through a reformatter to ensure i understood the structure of it.
In other words, the basic CTE wrapper for your pivot query is:
WITH PivotResults_CTE (
Field1,
Field2,
...
)
AS (
YOUR_PIVOT_QUERY_HERE
)
SELECT DISTINCT *
FROM
PivotResults_CTE
;

SQL for a Join that contains a condition within one of the join conditions

I have a requirement to do a left join between two tables. TableA is a transactional table while TableB contains reference data. The logical rule for my join is as follow:
SELECT *
FROM
TableA a
LEFT JOIN TableB b
ON a.ItemCode = b.ItemCode
AND a.ItemType = b.ItemType
AND b.FundID = 1 (but if no match found use b.FundID = 99)
The last join condition, the part in brackets, is what I'm having trouble with.
EDIT: Some clarification - If no match is found on ItemCode & ItemType & FundID = 1 then I want to join on ItemCode & ItemType & FundID = 99. Also TableB might have two records that match on both ItemCode and ItemType with one record having a FundID = 1 and the second record having FundID = 2. I that case I only want the record with FundID = 1.
What would be the most efficient way to write this query?
The only thing I can come up with is to execute the query twice, once with FundID = 1 and then with FundID = 99. Then use a set operator to return all the records form the first query and only records from the second query that does not exist in the first one. The code will not be pretty and it does not seem efficient either.
Thanks for your ideas in advance.
Marius
If i do understand your requirement correctly, this should gives you what you want
SELECT *
FROM
TableA a
OUTER APPLY
(
SELECT TOP 1 *
FROM TableB b
WHERE a.ItemCode = b.ItemCode
AND a.ItemType = b.ItemType
AND b.FundID IN (1, 99)
ORDER BY b.FundID
) b
You can change the query to
AND b.FundID IN (1,99)
or
AND (b.FundID = 1 or b.FundID = 99)
This is the best solution I have received so far. Thanks to #HABO (see the comments section of my question).
Add a column to create a Row_Number() partitioned on ItemType and ItemCode and ordered by FundId, then use only the results with row number 1
For posterity:
-- Sample data.
declare #TableA as Table ( AId Int Identity, ItemCode VarChar(20), ItemType VarChar(20) );
declare #TableB as Table ( BId Int Identity, ItemCode VarChar(20), ItemType VarChar(20), FundId Int );
insert into #TableA ( ItemCode, ItemType ) values
( 'Nemo', 'Fish' ), ( 'Blinky', 'Fish' ), ( 'Muddy Mudskipper', 'Fish' ),
( 'Hammer', 'Tool' ), ( 'Screwdriver', 'Tool' ), ( 'Politician', 'Tool' ),
( 'Grape Nehi', 'Beverage' ), ( 'Screwdriver', 'Beverage' );
insert into #TableB ( ItemCode, ItemType, FundId ) values
( 'Blinky', 'Fish', 1 ), ( 'Muddy Mudskipper', 'Fish', 2 ),
( 'Hammer', 'Tool', 1 ), ( 'Screwdriver', 'Tool', 99 ),
( 'Politician', 'Tool', 1 ), ( 'Politician', 'Tool', 99 ),
( 'Grape Nehi', 'Beverage', 42 ), ( 'Screwdriver', 'Beverage', 1 );
select * from #TableA;
select * from #TableB;
-- Do the deed.
with JoinWithRanking as (
select A.AId, A.ItemCode, A.ItemType, B.BId, B.FundId,
Row_Number() over ( partition by A.ItemCode, A.ItemType order by B.FundId ) as RN
from #TableA as A left outer join
#TableB as B on B.ItemCode = A.ItemCode and B.ItemType = A.ItemType and
B.FundId in ( 1, 99 )
)
select AId, ItemCode, ItemType, BId, FundId
from JoinWithRanking
where RN = 1;

The query is getting slow when a CASE statement in Having a clause in PostgreSQL

Below query is getting slower as I have used the case statement in having clause and the data is very huge, so below query is taking time for fetching the such huge data for overcoming this I need some alternatiive solution instead of the Having clause with case statement.
Explanation about the query,
I need to fetch the data by some types with condtions like I have three types
Flat Amount(1), Flat amount of rent(2) and percentage of rent(3) on that basis I need to do the SUM of the charges with condtions like if type is 2 then fetch the record with charge type is 2 and charge code is 3 like that. Please look into the below query and suggest me alternative solution is there,
SELECT
n.id,
ro.id,
n.notice_amount,
n.notice_type_id,
SUM ( c.charge_amount ) AS charge_amount
FROM
notification n
JOIN notification_doc_groups ndg ON ( ndg.notice_id = n.id AND ndg.is_published = TRUE )
JOIN properties p ON ( p.id = ndg.property_id )
JOIN customer_details cd ON ( cd.notification_id = n.id )
JOIN rent_out ro ON ( ro.property_id = p.id )
JOIN charges c ON ( c.rent_out_id = ro.id )
WHERE
( ( n.notice_type_id = 1
AND c.charge_amount > 0
AND c.charge_type_id = 2 )
OR ( n.notice_type_id = 2
AND c.charge_type_id = 2
AND c.charge_code = 3 )
OR ( n.notice_type_id = 3
AND c.scheduled_id IS NOT NULL ) )
GROUP BY
n.id,
ro.id,
n.notice_type_id,
n.notice_amount
HAVING
CASE
WHEN n.notice_type_id = 1 THEN ( ( sum ( c.charge_amount ) >= n.notice_amount ) )
WHEN n.notice_type_id = 2 THEN sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 ) -- or( )
WHEN n.notice_type_id = 3 THEN sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 )
END;
Thanks
You can separate out the three different cases and use a union to join them. It shouldn't make a difference in the results but might make it easier for the optimizer. If nothing else you'll be able to run each separate notice type and see if one is causing the slowdown.
I am a bit confused about the condition on notice types 2 and 3 though:
sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 )
It looks like you don't need to check the charge amount at all, you can just find entries where the notice_amount is 100 or less.
SELECT
n.id,
ro.id,
n.notice_amount,
n.notice_type_id,
SUM ( c.charge_amount ) AS charge_amount
FROM
notification n
JOIN notification_doc_groups ndg ON ( ndg.notice_id = n.id AND ndg.is_published = TRUE )
JOIN properties p ON ( p.id = ndg.property_id )
JOIN rent_out ro ON ( ro.property_id = p.id )
JOIN charges c ON ( c.rent_out_id = ro.id )
WHERE
n.notice_type_id = 3 AND c.scheduled_id IS NOT NULL
GROUP BY
n.id,
ro.id,
n.notice_type_id,
n.notice_amount
HAVING
sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 )
UNION ALL
SELECT
n.id,
ro.id,
n.notice_amount,
n.notice_type_id,
SUM ( c.charge_amount ) AS charge_amount
FROM
notification n
JOIN notification_doc_groups ndg ON ( ndg.notice_id = n.id AND ndg.is_published = TRUE )
JOIN properties p ON ( p.id = ndg.property_id )
JOIN rent_out ro ON ( ro.property_id = p.id )
JOIN charges c ON ( c.rent_out_id = ro.id )
WHERE
n.notice_type_id = 2 AND c.charge_type_id = 2
GROUP BY
n.id,
ro.id,
n.notice_type_id,
n.notice_amount
HAVING
sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 )
UNION ALL
SELECT
n.id,
ro.id,
n.notice_amount,
n.notice_type_id,
SUM ( c.charge_amount ) AS charge_amount
FROM
notification n
JOIN notification_doc_groups ndg ON ( ndg.notice_id = n.id AND ndg.is_published = TRUE )
JOIN properties p ON ( p.id = ndg.property_id )
JOIN rent_out ro ON ( ro.property_id = p.id )
JOIN charges c ON ( c.rent_out_id = ro.id )
WHERE
n.notice_type_id = 1 AND c.charge_amount > 0 AND c.charge_type_id = 2
GROUP BY
n.id,
ro.id,
n.notice_type_id,
n.notice_amount
HAVING
sum ( c.charge_amount ) >= n.notice_amount
Can you try this:
HAVING (n.notice_type_id = 1 AND sum ( c.charge_amount ) >= n.notice_amount)
OR ( n.notice_type_id IN (2,3) AND n.notice_amount / 100 >=1)
My guess it that the planner can't optimize for the case so try an array:
having (array[
sum ( c.charge_amount ) >= n.notice_amount,
sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 ),
sum ( c.charge_amount ) >= sum ( c.charge_amount ) * ( n.notice_amount / 100 )
]::bool[])[n.notice_type_id]

SQL Server - get rid of derived query in join

I'm interested in some suggestions with examples on how to 1)get rid of the derived query in the left outer join and 2)remove/consolidate the cte cteSecType in the code below The derived query in the join chooses the minimum assistant_personnel_number out of a list; there can be multiple primary and backup assistants associated with an employee . thx
WITH cteAssistants ( executive_personnel_number, assistant_personnel_number, assistant_type, assign_role )
AS ( SELECT CASE WHEN ISNUMERIC(JP.XA_asgn_emplid) = 1
THEN JP.XA_asgn_emplid
ELSE ''
END AS executive_personnel_number ,
JAP.emplid AS assistant_personnel_number ,
LAT1.FIELDVALUE AS assistant_type ,
LAT3.xlatshortname AS assign_role
FROM dbo.XA_ASGN_PRNT AS KAP
LEFT OUTER JOIN dbo.XA_ASSIGNMENTS AS KA ON JP.emplid = JAP.emplid
AND JP.effdt = JAP.effdt
LEFT OUTER JOIN dbo.XA_EMPLOYEES AS EXECT ON EXECT.EMPLID = JP.XA_ASGN_EMPLID
LEFT OUTER JOIN dbo.XA_EMPLOYEES AS ASST ON ASST.EMPLID = JAP.EMPLID
LEFT OUTER JOIN dbo.XLATITEM AS XLAT1 ON LAT1.fieldname = 'XA_ASGN_TYPE'
AND LAT1.fieldvalue = JAP.XA_asgn_type
LEFT OUTER JOIN dbo.XLATITEM AS XLAT3 ON LAT3.fieldname = 'XA_ASGN_ROLE'
AND LAT3.fieldvalue = JP.XA_asgn_role
WHERE JAP.effdt = ( SELECT MAX(effdt)
FROM dbo.XA_ASGN_PRNT
WHERE emplid = JAP.emplid
AND effdt <= GETDATE()
)
--Return data only when both executive and assistant are still active; null is for Floaters
AND ( EXECT.HR_STATUS = 'A'
OR EXECT.HR_STATUS IS NULL
)
AND ASST.HR_STATUS = 'A'
AND ( JAP.XA_asgn_type = 'F'
OR ( JAP.XA_asgn_type IN ( 'A', 'AF' )
AND JP.XA_asgn_person = 'Y'
)
)
),
cteSecType ( assistant_personnel_number, SecType )
AS ( SELECT assistant_personnel_number ,
assistant_type AS SecType
FROM cteAssistants
GROUP BY assistant_type ,
assistant_personnel_number
)
SELECT EMP.XA_NETWORK_ID AS network_id ,
EMP.XA_EMPLID AS empid ,
EMP.XA_EMPLID AS employeeNumber ,
EMP.XA_FIRST_NAME AS first_name ,
EMP.XA_LAST_NAME AS last_name ,
SECRES.SecType AS SecType ,
AsstInfo.XA_fml_pref_name AS PrimaryAssistant_FML ,
AsstInfo.XA_network_id AS PrimaryAssistant_Newtork_ID ,
AsstInfo.XA_EMPLID AS PrimaryAssistant_EmpID ,
AsstInfo.XA_phone_ext AS PrimaryAssitant_Extension
FROM dbo.XA_EMPLOYEES AS EMP
LEFT OUTER JOIN dbo.XA_EMPLOYEES AS MGR ON EMP.supervisor_id = MGR.emplid
LEFT OUTER JOIN cteSecType AS SECRES ON CAST(CAST(SECRES.assistant_personnel_number AS INT) AS VARCHAR(11)) = EMP.XA_EMPLID
LEFT OUTER JOIN ( SELECT executive_personnel_number AS AttorneyID ,
MIN(assistant_personnel_number) AS AssistantID
FROM cteEmployeeAssistants AS A
WHERE ( assign_role = 'Primary' )
GROUP BY executive_personnel_number
) AS ASST ON ASST.AttorneyID = EMP.XA_EMPLID
LEFT OUTER JOIN dbo.XA_EMPLOYEES AS ASSTINFO ON ASSTINFO.XA_EMPLID = ASST.AssistantID
WHERE ( EMP.HR_STATUS = 'A' )
AND ( EMP.PER_ORG IN ( 'EMP', 'CWR' ) )
AND ( ISNULL(EMP.XA_NETWORK_ID, '') <> '' )
GO