Join Results in duplication - sql-server

I have two tables. I suppose to get the result into one row, but when i try with the below query it results duplication.
Query:
Select OrgaID, UnitID, LeaveTitle, NoOfFromService, NoOfToService,
EmpType.EmployeeTypeName, IsExpatriate,
(ALR.LeaveTypeShortName + '(' + convert(varchar,ALR.NoofDays) + ') | ' +
MLR.LeaveTypeShortName + '(' + convert(varchar,MLR.NoofDays) + ') | ')
Leaves
From LeaveCategory LvCat
Left Join (Select LeaveCategoryID, LeaveTypeShortName, NoofDays From
LeaveEntitledEntry Where LeaveTypeShortName = 'AL' ) ALR On
ALR.LeaveCategoryId = LvCat.Id
Left Join (Select LeaveCategoryID, LeaveTypeShortName, NoofDays From
LeaveEntitledEntry Where LeaveTypeShortName = 'MDL' ) MLR On
ALR.LeaveCategoryId = LvCat.Id
Where OrgaID = #OrgaID and LvCat.Status = 1
For Reference :
Table 1: (LeaveCategory)
Table 2: (LeaveEntitledEntry)
Result :
So how can i change my joins to achieve expected result. Any help appreciated. Thanks in advance

You can try using conditional aggregation to access the two types of leave data by using a join to a single subquery. The reason this trick might work is that allows us to generate a single record for each LeaveCategoryID, along with its NoofDays values for both the AL and MDL types. This means that we can do with just a single join, which should avoid the duplication problem you were having.
WITH cte AS (
SELECT
LeaveCategoryID,
MAX(CASE WHEN LeaveTypeShortName = 'AL' THEN NoofDays END) AS NoofDaysAL,
MAX(CASE WHEN LeaveTypeShortName = 'MDL' THEN NoofDays END) AS NoofDaysMDL
FROM LeaveEntitledEntry
GROUP BY LeaveCategoryID
)
SELECT
OrgaID,
UnitID,
LeaveTitle,
NoOfFromService,
NoOfToService,
EmpType.EmployeeTypeName,
IsExpatriate,
'AL(' + CONVERT(varchar, t.NoofDaysAL) + ') | ' +
'MDL(' + CONVERT(varchar, t. NoofDaysMDL) + ') | ') AS Leaves
FROM LeaveCategory LvCat
LEFT JOIN cte t
ON LvCat.Id = t.LeaveCategoryID
WHERE
OrgaID = #OrgaID AND
LvCat.Status = 1;

Related

SQL Stuff from Subquery

I have a query that returns a list of services and ContractorIDs. I need to stuff these services into a field to join them with another select statement by ContractorID, but I can't figure out how to do it.
The Select that lists the services is "
SELECT DISTINCT SM.ContractorID,
CASE WHEN S.bitRestrictedSelection = 1
THEN S.vchDescription + '*'
ELSE S.vchDescription
END AS vchDescription
FROM tblAscServiceRegionToOperator SRTO
INNER JOIN tblServiceMatrix SM
ON SRTO.OperatorID = 12624
AND SM.ServiceRegionID = SRTO.ServiceRegionID
AND SM.bitPrimaryService = 1
INNER JOIN tblServices S
ON S.ServiceID = SM.ServiceID
This produces the following:
In the example, for Contractor #16 He has 4 services I need to put them in one field called services by joining with another Select statement
I tried the following, but I get errors:
Select DISTINCT CompanyID, vchCompanyName as CompanyName,vchFIDNumber,vchPrimContactName, vchPrimContactEmail
,stuff((','
SELECT DISTINCT
SM.ContractorID,
CASE WHEN S.bitRestrictedSelection = 1
THEN S.vchDescription + '*'
ELSE S.vchDescription
END AS vchDescription
FROM tblAscServiceRegionToOperator SRTO
INNER JOIN tblServiceMatrix SM
ON SRTO.OperatorID = 12624
AND SM.ServiceRegionID = SRTO.ServiceRegionID
AND SM.bitPrimaryService = 1
INNER JOIN tblServices S
ON S.ServiceID = SM.ServiceID
FOR XML PATH('')
), 1, 1, '') as Services from tblCompany
Any assistance is greatly appreciated!!!
The following query would work:
SELECT SS.contractor Contractor,
STUFF((SELECT '; ' + US.vchdescription
FROM ServicesList US
WHERE US.contractor = SS.contractor
FOR XML PATH('')), 1, 1, '') [Services]
FROM ServicesList SS
GROUP BY SS.contractor
ORDER BY 1
I have created a table and inserted there two rows for contractor = 16, for you to get the idea.
You can use the suggestion given to you in the comments, to wrap the first select into a CTE and then perform the STUFF function on that CTE.
You can check a demo of this query here.

TSQL Optimize for multiple nested case query

Can someone help me optimize this query. I only wrote out 2 of the case statements, but it actually has like 30 such cases all nested as seen in this example (with 2) below.
SELECT *
FROM QS
INNER JOIN R ON (CASE
WHEN R.FieldCode = 'L'
THEN ---
CASE
when (
(R.Match = 1 AND QS.lineid
IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))
OR (R.Match = 0 AND QS.lineid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))) then 1
ELSE 0
END
----
WHEN R.FieldCode = 'D'
THEN
CASE
when ((R.Match = 1 AND QS.productid
IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))
OR (R.Match = 0 AND QS.productid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))) then 1
ELSE 0
END
END)=1
This is really bad SQL code, as the database engine cannot do any optimization at all since it needs to enumerate the entire table and go record by record doing multiple tests on each, twice.
You can do this without any CASE at all:
SELECT *
FROM QS
INNER JOIN R ON ( (R.FieldCode = 'L'
AND ( (R.Match = 1 AND QS.lineid IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))
OR (R.Match = 0 AND QS.lineid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))))
OR (R.FieldCode = 'D'
AND ( (R.Match = 1 AND QS.productid IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))
OR (R.Match = 0 AND QS.productid NOT IN (SELECT CONVERT(int,s) FROM SplitFunc(',', R.FieldValue)))))
)
Does this perform better for you? Not knowing the relative row counts or underlying data, I would think this might be much faster and easier to maintain since you don't have to run the scalar function over and over again and should be more optimizer-friendly.
SELECT * -- Change to only get fields you need from QS.*
FROM (
SELECT
QS.*,
',' + CONVERT(VARCHAR(10),
CASE R.FieldCode
WHEN 'L' THEN QA.lineid
WHEN 'D' THEN QA.productid
-- ...
END + ',' AS MatchValue,
',' + R.FieldValue + ',' AS FieldValueCSV
R.Match
FROM QS
CROSS JOIN R
) T
WHERE (T.Match = 1 AND T.FieldValueCSV LIKE '%' + T.MatchValue + '%')
OR (T.Match = 0 AND NOT T.FieldValueCSV LIKE '%' + T.MatchValue + '%')

return 1 row from multiple case statements

In the following Query below in the port with the case statements I'm trying to figure out how to not return a null value when the SegmentType doesn't match.
QRSubscriberTag,MLKSubscriberTag, QTMSubscriber Tag, are actually a table of Tags uniquely identified by their SegID and a segmentType associated to the SegID. I use an outer apply with a subquery that calls FOR XML PATH('') to concatenate the Tags together related to the specific tag.
The flaw with this method is that when the Tag isn't for example QRSubscriberTag, then a null record in the QRSubscriberTag column is created.
QRSubscriberTag|QR01|MLKSubscriberTag|MLK01|QTMSubscriberTag|QTM01|QTM02
NULL |NULL|NULL |{Data}|null |FH |45
TKP ;OCP ;OCR ;|R |NULL |null |null |null |null
What I would like to see is all the Data in 1 line
QRSubscriberTag|QR01|MLKSubscriberTag|MLK01|QTMSubscriberTag|QTM01|QTM02
TKP ;OCP ;OCR ;|R |NULL |{Data}|null |FH |45
Below is my code
SET NOCOUNT ON
USE [Apps]
SELECT [BusRuleEnforceID], [FormatType], [Format],
[tag], [TagValue], Operator,
[QRSubscriberTag],[QR01],
[MLKSubscriberTag],[MLK01],
[QTMSubscriberTag],[QTM01],[QTM02]
FROM
(
SELECT
DISTINCT main.BusRuleEnforceID,
main.FormatType,
main.Format,
main.tag,
main.TagValue,
main.Operator,
CASE
WHEN seg.SegmentType = 'QR' THEN LEFT(SegsubscriberTags.list, LEN(SegsubscriberTags.list))
END AS [QRSubscriberTag],
CASE
WHEN seg.SegmentType = 'MLK' THEN LEFT(SegsubscriberTags.list, LEN(SegsubscriberTags.list)-1)
END AS [MLKSubscriberTag],
CASE
WHEN seg.SegmentType = 'QTM' THEN LEFT(SegsubscriberTags.list, LEN(SegsubscriberTags.list)-1)
END AS [QTMSubscriberTag],
c.ItemName as [SegmentId],
Case
WHEN c.ItemValue is not null and len(rtrim(c.ItemValue)) > 0 THEN c.ItemValue
ELSE LEFT(TagOptions.list, LEN(TagOptions.list)-1)
END as [Tags]
FROM
BMT_BusRulemaineria main
LEFT OUTER JOIN
BMT_BusRuleServiceType st
ON st.MappingmaineriaID = main.BusRuleEnforceID
LEFT OUTER JOIN
BMT_BusRuleSegment seg
ON seg.BusRuleEnforceID = main.BusRuleEnforceID
LEFT OUTER JOIN
BMT_BusRuleItem c
ON c.BusRuleEnforceSegID = seg.BusRuleEnforceSegID
LEFT OUTER JOIN
BMT_BusRuleItemOption co
ON c.BusRuleItemId = co.BusRuleItemId
OUTER APPLY
(
SELECT
IsNull(co2.Tag, '{Unknown}') + ISNULL('=' + co2.TagValue, '') + ':' + IsNull(co2.ItemValue, '')+ ';' AS [text()]
FROM
BMT_BusRuleItemOption co2
WHERE
co.BusRuleItemId = co2.BusRuleItemId
ORDER BY
co2.BusRuleItemId
FOR XML PATH('')
) TagOptions (list)
OUTER APPLY
(
SELECT
IsNull(porttag.Tag, '{Unknown}') + ' ' + ISNULL(porttag.Operator, '') + ' ' + IsNull(porttag.TagValue, '') + ';' AS [text()]
FROM
BMT_BusRuleSegmentTag porttag
WHERE
seg.BusRuleEnforceSegID = porttag.BusRuleEnforceSegID
ORDER BY
porttag.BusRuleEnforceSegID
FOR XML PATH('')
) SegsubscriberTags (list)
WHERE main.BusRuleEnforceID = 632563
AND main.TagTypeId = 1
) AS QRSourceTable
PIVOT
(
max([Tags])
FOR [SegmentId] IN ([QR01], [MLK01], [QTM01], [QTM02])
) AS QRPivotTable
ORDER BY
[TagTypeId], [BusRuleEnforceID]
EDIT: Full Result Set
Note: QRSubscriber, MLKSubscriber, and QTMSubscriber tags all have unique SegIDs.
<table><tbody><tr><th>FormatType</th><th>Format</th><th>Version</th><th>AmtCode</th><th>Date</th><th>LocationIdentifier</th><th>TagType</th><th>tag</th><th>TagValue</th><th>Operator</th><th>InfoCode</th><th>QRSubscriberTag</th><th>QR01</th><th>QR02</th><th>QR03</th><th>QR04</th><th>QR05</th><th>QR06</th><th>QR07</th><th>MLKSubscriberTag</th><th>MLK01</th><th>QTMSubscriberTag</th><th>QTM01</th><th>QTM02</th></tr><tr><td>DN</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>TIR</td><td>RPSAMN</td><td>NULL</td><td>exists</td><td>78</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>{Data}</td><td>NULL</td><td>TRH</td><td>675</td></tr><tr><td>DN</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>TIR</td><td>RPSAMN</td><td>NULL</td><td>exists</td><td>78</td><td>TKRARAP not exists TKRALAP not exists TKRADAP not exists </td><td>J</td><td>SKU</td><td>34</td><td>NULL</td><td>NULL</td><td>SILMULTU:2;SILMHLTU:67</td><td>TOPALD:{Data};QORITK{Data}</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td><td>NULL</td></tr></tbody></table>
Use the ELSE clause to assign a default value when the comparison does not match, like so:
CASE WHEN port.SegmentType = 'QR' THEN
LEFT(SegDependantTags.list, LEN(SegDependantTags.list))
ELSE 'Your Value Rather Than NULL Goes Here'
END AS [QRSubscriberTag],
It seems that instead of using Distinct in your QRSourceTable sub-query you want to use a Group By with a MAX aggregate function on your subscriber tag fields:
SELECT
main.BusRuleEnforceID,
main.FormatType,
main.Format,
main.tag,
main.TagValue,
main.Operator,
max(CASE
WHEN port.SegmentType = 'QR' THEN LEFT(SegDependantTags.list, LEN(SegDependantTags.list))
END) AS [QRSubscriberTag],
max(CASE
WHEN port.SegmentType = 'MLK' THEN LEFT(SegDependantTags.list, LEN(SegDependantTags.list)-1)
END) AS [MLKSubscriberTag],
max(CASE
WHEN port.SegmentType = 'QTM' THEN LEFT(SegDependantTags.list, LEN(SegDependantTags.list)-1)
END) AS [QTMSubscriberTag],
c.ItemName as [SegmentId],
Case
WHEN c.ItemValue is not null and len(rtrim(c.ItemValue)) > 0 THEN c.ItemValue
ELSE LEFT(TagOptions.list, LEN(TagOptions.list)-1)
END as [Tags]
from
...
WHERE main.BusRuleEnforceID = 632563
AND main.TagTypeId = 1
GROUP BY main.BusRuleEnforceID,
main.FormatType,
main.Format,
main.tag,
main.TagValue,
main.Operator

Intersect query with no duplicates

I have not used sql server in a large complex scale in years, and Looking for help on how to proper sintax intersect type query to joing these two data sets, and not create duplicate names. Some patients will have both an order and a clinical event entry and some will only have a clinical event.
Data Set 1
SELECT
distinct
ea.alias as FIN,
per.NAME_Last + ', ' + per.NAME_FIRST + ' ' + Isnull(per.NAME_MIDDLE, '') as PatientName,
oa.action_dt_tm as CirOrder,
od.ORIG_ORDER_DT_TM as DischOrder,
e.disch_dt_tm as ActualDisch,
prs.NAME_FULL_FORMATTED as OrderedBy,
from pathway py
join encounter e on e.CERNER_ENCOUNTER_ID = py.encntr_id
join encntr_alias ea on ea.CERNER_ENCNTR_ID = e.CERNER_ENCOUNTER_ID and ea.ENCNTR_ALIAS_TYPE_WCD = 1049
join person per on per.CERNER_PERSON_ID = e.cerner_PERSON_ID
join orders o on o.CERNER_ENCNTR_ID= e.CERNER_ENCOUNTER_ID and o.CATALOG_wCD = '82111' -- communication order
and o.pathway_catalog_id = '43809296' ---Circumcision Order
join order_action oa on oa.[CERNER_ORDER_ID] = o.CERNER_ORDER_ID and oa.ACTION_TYPE_WCD = '2494'--ordered
join orders od on od.CERNER_ENCNTR_ID= e.CERNER_ENCOUNTER_ID and od.CATALOG_WCD = '203520' --- Discharge Patient
join prsnl prs on prs.CERNER_PERSON_ID = oa.order_provider_id
where py.pathway_catalog_id = '43809296' and ---Circumcision Order
oa.action_dt_tm > '2016-01-01 00:00:00'
and oa.ACTION_DT_TM < '2016-01-19 23:59:59'
--use the report prompts as parameters for the action_dt_tm
Data Set 2
SELECT
distinct e.[CERNER_ENCOUNTER_ID],
ea.alias as FIN,
per.NAME_Last + ', ' + per.NAME_FIRST + ' ' + Isnull(per.NAME_MIDDLE, '') as PatientName,
ce.EVENT_END_DT_TM as CircTime,
od.ORIG_ORDER_DT_TM as DischOrder,
e.disch_dt_tm as ActualDisch,
'' OrderedBy, -- should be blank for this set
cv.DISPLAY
from encounter e
join clinical_event ce on e.CERNER_ENCOUNTER_ID = ce.CERNER_ENCNTR_ID
join encntr_alias ea on ea.CERNER_ENCNTR_ID = e.CERNER_ENCOUNTER_ID and ea.ENCNTR_ALIAS_TYPE_WCD = 1049
join person per on per.CERNER_PERSON_ID = e.cerner_PERSON_ID
join orders od on od.CERNER_ENCNTR_ID= e.CERNER_ENCOUNTER_ID and od.CATALOG_WCD = '203520' --- Discharge Patient
left outer join ENCNTR_LOC_HIST elh on elh.CERNER_ENCNTR_ID = e.CERNER_ENCOUNTER_ID
left outer join CODE_VALUE cv on cv.CODE_VALUE_WK = elh.LOC_NURSE_UNIT_WCD
where ce.event_wcd = '201148' ---Newborn Circumcision
and ce.[RESULT_VAL] = 'Newborn Circumcision'
and ce.EVENT_END_DT_TM > '2016-01-01 00:00:00'
and ce.event_end_dt_tm < '2016-01-19 23:59:59’
and ce.RESULT_STATUS_WCD = '25'
and elh.ACTIVE_STATUS_DT_TM < ce.event_end_dt_tm -- Circ time between the location's active time and end time.
and elh.END_EFFECTIVE_DT_TM > ce.[EVENT_END_DT_TM]
--use the report prompts as parameters for the ce.[EVENT_END_DT_TM]
The structure of an intersect query is as simple as:
select statement 1
intersect
select statement 2
intersect
select statement 3
...
This will return all columns that are in both select statements. The columns returned in the select statements must be of the same quantity and type (or at least be convertible to common type).
You can also do an intersect type of query just using inner joins to filter out records in the one query that are not in the other. So for a simple example let's say you have two tables of colors.
Select distinct ColorTable1.Color
from ColorTable1
join ColorTable2
on ColorTable1.Color = ColorTable2.Color
This will return all the distinct colors in ColorTable1 that are also in ColorTable2. Using joins to filter could help your query perform better, but it does take more thought.
Also see: Set Operators (Transact-SQL)

How to Increment a nvarchar value + number when more then one value is displayed for a given ID

I need to add a address type value to a column when more then one value is returned from the query below. For example if a single result is returned then I want the value in the address type column to be Business. But if there is more then one value returned, I want it to increment a value after the first result to be Alternate Business 1,Alternate Business 2, Alternate Business 3 etc.
Can anyone help me out?
SELECT al.ADDRESS_ID,
addr.LINE1 + ' (' + addr.LABEL + ')' AS ModifiedLine1,
addr2.ADDR_TYP_ID,
addr2.LABEL,
addr2.LINE2,
addr2.LINE3,
addr2.CITY,
addr2.STATE,
addr2.COUNTRY,
addr2.POSTAL_CD
FROM INT_AUX_LST_ADDR al
LEFT JOIN INT_AUX_ADDRESS addr
ON addr.ADDRESS_ID = al.ADDRESS_ID
LEFT JOIN INT_AUX_ADDRESS addr2
ON addr2.ADDRESS_ID = al.ADDRESS_ID
LEFT JOIN INT_RELATION_TYP rt
ON rt.RLTN_TYP_ID = al.RLTN_TYP_ID
WHERE al.LISTING_ID = 1
This is a job for row_number() . . . The only caveat is that you need some ordering. But here it goes:
SELECT al.ADDRESS_ID,
addr.LINE1 + ' (' + addr.LABEL + ')' AS ModifiedLine1,
addr2.ADDR_TYP_ID,
addr2.LABEL,
addr2.LINE2,
addr2.LINE3,
addr2.CITY,
addr2.STATE,
addr2.COUNTRY,
addr2.POSTAL_CD,
(case row_number() over (order by (select NULL))
when 1 then 'Business'
else 'Alternate Business '+cast(-1 + row_number() over (order by (select NULL)) as varchar(255))
end) as WhatYouWant
FROM INT_AUX_LST_ADDR al
LEFT JOIN INT_AUX_ADDRESS addr
ON addr.ADDRESS_ID = al.ADDRESS_ID
LEFT JOIN INT_AUX_ADDRESS addr2
ON addr2.ADDRESS_ID = al.ADDRESS_ID
LEFT JOIN INT_RELATION_TYP rt
ON rt.RLTN_TYP_ID = al.RLTN_TYP_ID
WHERE al.LISTING_ID = 1 ;
By the way, with the indeterminate order by in the example above, there is no guarantee that the two row_number() calls return the same values -- but in practice they will. If you replace it with the correct field for ordering, then this is not a problem.

Resources