Cross Apply remove NULL values - sql

I want to remove the row with NULL values on Crit_Value column. Appreciate your help.
Query:
SELECT DISTINCT GP.PRIORITY_CD, CODE_Val
FROM TCRITERIA_GROUP_PS GP
CROSS APPLY ( SELECT PV.CODE + ','
FROM TCRITERIA_GROUP_PS_VALUE GPV
--JOIN TCRITERIA_GROUP_PS GP ON GP.CRITERIA_GROUP_PS_ID = GPV.CRITERIA_GROUP_PS_ID
JOIN TCRITERIA_PS_VALUE PV ON PV.CRITERIA_PS_VALUE_ID = GPV.CRITERIA_PS_VALUE_ID
JOIN TCRITERIA_PS CP ON PV.CRITERIA_PS_ID = CP.CRITERIA_PS_ID
WHERE
PV.PARTNER_ID = 'JETSTAR'
AND GP.PARTNER_SYS_ID = 'JETSTAR1'
AND GP.ISO_CNTRY_CD = 'AU'
AND GP.CRITERIA_GROUP_PS_ID = GPV.CRITERIA_GROUP_PS_ID
FOR XML PATH('') ) D ( CODE_Val )
RESULTSET of the Query:
PRIORITY_CD CODE_Val
-------------------------
1 NULL
1 AU,AU,AUD,OW,0_1999,
2 NULL
2 AU,AU,AUD,OW,2000_99999,
3 NULL
3 AU,AU,AUD,RT,0_1999,
4 NULL
4 AU,AU,AUD,RT,2000_99999,
5 NULL
5 AU,ALL_EX,AUD,OW,

Try changing the correlation between the main table and the subquery, or add a where clause to filter out the NULLs
SELECT DISTINCT
GP.PRIORITY_CD
, D.CODE_Val
FROM TCRITERIA_GROUP_PS GP
CROSS APPLY (
SELECT
PV.CODE + ','
FROM TCRITERIA_GROUP_PS_VALUE GPV
JOIN TCRITERIA_PS_VALUE PV ON PV.CRITERIA_PS_VALUE_ID = GPV.CRITERIA_PS_VALUE_ID
JOIN TCRITERIA_PS CP ON PV.CRITERIA_PS_ID = CP.CRITERIA_PS_ID
WHERE PV.PARTNER_ID = 'JETSTAR'
AND GP.PARTNER_SYS_ID = 'JETSTAR1'
AND GP.ISO_CNTRY_CD = 'AU'
AND GP.PRIORITY_CD = GPV.CRITERIA_GROUP_PS_ID -- changed
FOR xml PATH ('')
) D (CODE_Val)
-- WHERE D.CODE_Val IS NOT NULL

Related

Pivot on duplicate column name

The query below is doing what I want, except a given accessruleId could have more than one businessArea. So, the current query is just grabbing the max one instead of all of them.
I get businessArea column to list all of the values perhaps comma delimited like the screenshot below.
I am using SQL Server 2016.
AccessRuleId EffectiveDate TermDate CreatedByUser CreateDateTime LastUpdatedUser LastUpdatedDateTime
1 2019-12-13 2020-01-22 User1 2019-12-11 User2 2019-12-12
RuleFieldId FieldName
1 BusinessArea
2 ProviderTaxId
3 VendorName
RuleOperationId AccessRuleId Fieldid Value
1 1 1 ABC
2 1 2 1234537890
3 1 3 Vendor1
30 1 4 XYZ
SELECT *
FROM (
SELECT ar.AccessRuleId
,ar.EffectiveDate
,ar.TermDate
,ar.CreatedByUser
,ar.LastUpdatedUser
,rf.FieldName
,ro.Value
FROM AccessRule.AccessRule ar
JOIN AccessRule.RuleOperation ro ON ar.AccessRuleId = ro.AccessRuleId
JOIN AccessRule.RuleField rf ON ro.FieldId = rf.RuleFieldId
) AS t
pivot(max([value]) FOR [FieldName] IN (
[BusinessArea]
,[ProviderTaxId]
,[VendorName]
)) AS pt
You need to merge the value for the field before the pivoting:
;WITH cte_raw(AccessRuleId,EffectiveDate,TermDate,CreatedByUser,LastUpdatedUser,FieldName,Value)
AS
(
SELECT ar.AccessRuleId
,ar.EffectiveDate
,ar.TermDate
,ar.CreatedByUser
,ar.LastUpdatedUser
,rf.FieldName
,ro.Value
FROM AccessRule.AccessRule ar
JOIN AccessRule.RuleOperation ro ON ar.AccessRuleId = ro.AccessRuleId
JOIN AccessRule.RuleField rf ON ro.FieldId = rf.RuleFieldId
),
cte_merged(AccessRuleId,EffectiveDate,TermDate,CreatedByUser,LastUpdatedUser,FieldName,Value)
AS
(
SELECT r.AccessRuleId,r.EffectiveDate,r.TermDate,r.CreatedByUser,r.LastUpdatedUser,r.FieldName,
STUFF((SELECT N','+v.Value
FROM cte_raw v
WHERE v.AccessRuleId=r.AccessRuleId
AND v.EffectiveDate=r.EffectiveDate
AND v.TermDate=r.TermDate
AND v.CreatedByUser=r.CreatedByUser
AND v.LastUpdatedUser=r.LastUpdatedUser
AND v.FieldName=r.FieldName
ORDER BY v.Value
FROM XML PATH (N''),TYPE).value('.','nvarchar(4000)')
,1,1,N'') AS Value
FROM cte_raw r
GROUP BY r.AccessRuleId
,r.EffectiveDate
,r.TermDate
,r.CreatedByUser
,r.LastUpdatedUser
,r.FieldName
)
SELECT *
FROM cte_merged t
pivot(max([value]) FOR [FieldName] IN (
[BusinessArea]
,[ProviderTaxId]
,[VendorName]
)) AS pt
I figured out how to do this in an a more simplified way.
SELECT ar.AccessRuleId
,ar.EffectiveDate
,ar.TermDate
,(select Value from AccessRule.RuleOperation ro where ro.AccessRuleId = ar.AccessRuleId and ro.FieldId = 2) as ProviderTaxId
,(select Value from AccessRule.RuleOperation ro where ro.AccessRuleId = ar.AccessRuleId and ro.FieldId = 3) as VendorName
,(SELECT STUFF( (SELECT ',' + value FROM AccessRule.RuleOperation ro where ro.AccessRuleId = ar.AccessRuleId and ro.FieldId = 1 FOR XML PATH('')),1, 1, '')) AS BusinessAreas
FROM AccessRule.AccessRule ar

Attempting to set a non-NULL- able column's value to NULL

I am getting attempting to set a non-NULL- able column's value to NULL
error when I use FOR XML PATH('')
Code:
select
fdp.POLICYNUMBER,
fdp.INSUREDNAME,
fdp.OWNERNAME,
fdp.AGENCYCODE,
p.WFWORKSTEPNAME,
fdpc.NIGO,
fdpc.NIGOREASON,
d.NIGOREQUIREMENT,
wci.WCSTATUS,
wci.DATECOMPLETED,
fdCI.NEWUNDERWRITINGUSER,
fdr.NBAMOUNT
into
#t
from
PINewBusiness p
join
FDPolicyDetails fdp on SUBSTRING(p.CFREPKEY, 9, LEN(p.CFREPKEY)) = fdp.PARENT_CASEID
and (p.WFWORKSTEPNAME = 'PendingRequirements' or
p.WFWORKSTEPNAME = 'FollowUpRequirements' )
join
FDProcessing fdpc on SUBSTRING(p.CFREPKEY, 9, LEN(p.CFREPKEY)) = fdpc.PARENT_CASEID
join
FDRounting fdr on SUBSTRING(p.CFREPKEY, 9, LEN(p.CFREPKEY)) = fdr.PARENT_CASEID
cross apply
(select NIGOREQUIREMENT + ', '
from FDNIGORequirements nr
where nr.PARENT_CASEID = fdpc.PARENT_CASEID
for xml path('')) D (NIGOREQUIREMENT)
--join FDNIGORequirements nr on SUBSTRING(p.CFREPKEY, 9, LEN(p.CFREPKEY)) = nr.PARENT_CASEID
cross apply
(select NIGOREQUIREMENT + ', '
from FDNIGORequirements nr
where nr.PARENT_CASEID = SUBSTRING(p.CFREPKEY,9,LEN(p.CFREPKEY))
for xml path('')) D (NIGOREQUIREMENT)
join
(select max(CREATEDDATETIME) as CREATEDDATETIME, PARENT_CASEID
from FDWelcomeCall
group by PARENT_CASEID ) wc on fdr.PARENT_CASEID = wc.PARENT_CASEID
join
FDWelcomeCall wci on wci.PARENT_CASEID = wc.PARENT_CASEID
and wci.CREATEDDATETIME = wc.CREATEDDATETIME
join
FDCaseInformation fdCI on SUBSTRING(p.CFREPKEY, 9, LEN(p.CFREPKEY)) = fdCI.PARENT_CASEID
where
p.WFSTEPENTRYTIME >= #sdate
and p.WFSTEPENTRYTIME <= #edate
order by
p.WFFLOWENTRYTIME desc
If you want to keep the rows with NULL values you must replace the nulls in the column that gives you the error, to do so you can use:
SELECT COALESCE([MyColumn],__ReplacementValue__) AS [MyColumn] FROM MyTable
or
SELECT ISNULL([MyColumn],__ReplacementValue__) AS [MyColumn] FROM MyTable
You can use one of them in the inner or outer SELECT.
Otherwise, if the row should not exist if that value is null you must filter it out by adding a WHERE clause:
WHERE [MyColumn] IS NOT NULL

Data show by list when group by is not include data

I have a sql command like this
select mainPOID.EstAPDate,mainPOID.POID,TTm.ID,TTMAmount=TTMD.InvoiceAmount
From TTBeforeMms TTM
inner join TTBeforeMms_Detail TTMD on TTM.ID = TTMD.ID
inner join (
select distinct main.EstAPDate,main_D.POID
From AP main
left join AP_Detail main_D on main.ID = main_D.ID
where main.Type ='PA' and main.EstAPDate between '2018/6/01' AND '2018/6/15' and left(main_D.InvoiceNo,4) != '1111' ) mainPOID on TTMD.poid =mainPOID.POID and TTM.EstAPdate<=mainPOID.EstAPdate and mainPOID.POID='CM3PU18030009'
order by mainPOID.EstAPDate,mainPOID.POID
sql result will like this
My question is
How can Data show by list when group by is not include data?
For example
ID will show by list When I group by EstAPDate、POID and sum(TTMAmount)
You can store in one temp table or use CTE
CREATE TABLE [dbo].#Columnss(
espapdate date ,
poid varchar(max),
id varchar(max),amount decimal(22,6))
GO
insert into #Columnss values('2018-06-15','cm3','pt20',19988.8900)
insert into #Columnss values('2018-06-15','cm3','pt21',265.8900)
SELECT
REPLACE(ESPAPDATE,'-','/') ESPAPDATE, POID,
STUFF(
(SELECT ' , ' + OD.ID
FROM #COLUMNSS OD
WHERE OD.ESPAPDATE = O.ESPAPDATE
AND OD.POID = O.POID
FOR XML PATH('')), 1, 2, ''
) PRODUCTNAMES,SUM(AMOUNT)AMOUNT
FROM #COLUMNSS O
GROUP BY ESPAPDATE, POID
output
espapdate poid ProductNames amount
2018/06/15 cm3 pt20 , pt21 20254.780000
there are lots of CSV example using FOR XML PATH. For your case here, i am wrapping your existing query in a CTE and then from there generate the CSV string for ID
; with
cte as
(
select mainPOID.EstAPDate, mainPOID.POID, TTm.ID, TTMAmount=TTMD.InvoiceAmount
From TTBeforeMms TTM
inner join TTBeforeMms_Detail TTMD on TTM.ID = TTMD.ID
inner join (
select distinct main.EstAPDate,main_D.POID
From AP main
left join AP_Detail main_D on main.ID = main_D.ID
where main.Type ='PA'
and main.EstAPDate between '2018/6/01' AND '2018/6/15'
and left(main_D.InvoiceNo,4) != '1111'
) mainPOID on TTMD.poid = mainPOID.POID
and TTM.EstAPdate <= mainPOID.EstAPdate
and mainPOID.POID = 'CM3PU18030009'
)
SELECT EstAPDate, POID,
ID = STUFF(c.ID, 1, 1, ''),
TTMAmount = SUM(TTMAmount)
FROM cte
CROSS APPLY
(
SELECT ',' + ID
FROM cte x
WHERE x.EstAPDate = cte.EstAPDate
AND x.POID = cte.POID
FOR XML PATH ('')
) c (ID)
GROUP BY EstAPDate, POID
ORDER BY EstAPDate, POID

How To Combine These 2 Queries into one Query without using union

SELECT b.KPCNO
,b.KPC_FULL_NAME
FROM xxkpc_hr_personnel_v2 b
WHERE b.type(+) = 'KPC Employee'
AND b.DESIGNATION is null
AND b.kpcno IS NOT NULL
AND b.ORGANIZATION_ID=(select g.ORGANIZATION_ID from xxkpc_fn_web_personnel_v g where g.kpcno = :kpcno)
GROUP BY b.KPCNO
,b.kpc_full_name
UNION
SELECT b.KPCNO
,b.KPC_FULL_NAME
FROM xxkpc_hr_pos_struct_code_comb a
,xxkpc_hr_personnel_v2 b
WHERE b.position_id(+) = a.child_position_id
AND b.type(+) = 'KPC Employee'
AND b.kpcno IS NOT NULL
AND a.PERANT_POSITION_ID = (select g.POSITION_ID from xxkpc_fn_web_personnel_v g where g.kpcno = :kpcno)
GROUP BY b.KPCNO
,b.kpc_full_name
Please I need to combine these 2 queries into one query without using UNION
I think you can write it like:
select distinct b.kpcno, b.kpc_full_name
from xxxkpc_hr_personnel_v2 b
where b.type(+) = 'KPC Employee'
and b.kpcno is not null
and (
(b.designation is null and
b.organization_id in (select g.organization_id
from xxkpc_fn_web_personnel_v g
where g.kpcno = :kpcno))
or
(b.position_id in (select a.child_position_id
from xxkpc_hr_pos_struct_code_comb a
where a.parent_position_id = (select g.position_id
from xxkpc_fn_web_personnel_v g
where g.kpcno = :kpcno)))
)
as far as I see you are using the group by to make the result distinct, so I used the proper key word. And a and b are not left joined, because in the next where anded clause you are saying a.parent_position_id = .....
SELECT
b.KPCNO,
b.KPC_FULL_NAME
FROM
xxkpc_hr_personnel_v2 b
LEFT OUTER JOIN xxkpc_hr_pos_struct_code_comb a ON b.position_id = a.child_position_id
INNER JOIN xxkpc_fn_web_personnel_v g ON g.kpcno = :kpcno
WHERE
b.type = 'KPC Employee'
AND b.kpcno IS NOT NULL
AND ((b.DESIGNATION IS NULL AND g.ORGANIZATION_ID = b.ORGANIZATION_ID)
OR (a.PERANT_POSITION_ID = g.POSITION_ID))
Do you have anyway to join the two tables? It looks like you can join on b.KPCNO or b.KPC_FULL_NAME.

SQL Union Query

SELECT pv.PropertyID, COUNT(pv.VisitID) AS InitialVisit
FROM tblPAppointments pa INNER JOIN tblPropertyVisit pv ON pv.AppID = pa.AppID
WHERE pv.Status = 0
GROUP BY pv.PropertyID
UNION ALL
SELECT jv.PropertyID, COUNT(jv.JobVistID) AS JobVisit
FROM tblPAppointments pa INNER JOIN tblJobVisits jv ON jv.AppID = pa.AppID
WHERE jv.VisitStatus = 1
GROUP BY jv.PropertyID
I need to get InitialVisit count and JobVisit count in two separate columns.above query returns just two columns (PropertyID,InitialVisit).
Use a NULL as a placeholder for the column that there won't be any output for:
SELECT pv.PropertyID,
COUNT(pv.VisitID) AS InitialVisit,
NULL AS jobvisit
FROM tblPAppointments pa
JOIN tblPropertyVisit pv ON pv.AppID = pa.AppID
WHERE pv.Status = 0
GROUP BY pv.PropertyID
UNION ALL
SELECT jv.PropertyID,
NULL AS initialvisit,
COUNT(jv.JobVistID) AS JobVisit
FROM tblPAppointments pa
JOIN tblJobVisits jv ON jv.AppID = pa.AppID
WHERE jv.VisitStatus = 1
GROUP BY jv.PropertyID
This will return three columns. The column alias is necessary in the first query, but not in the second -- I aliased both to make it clear what is happening.
Be aware that using NULL like this in SQL Server will require you to use CAST/CONVERT on the NULL for data types other than INT because SQL Server defaults the NULL to an INT data type (as odd as that is).
An alternate query that doesn't use UNION:
SELECT x.propertyid,
COUNT(y.visitid) AS initialvisit,
COUNT(z.jobvisitid) AS jobvisit
FROM (SELECT pv.propertyid
FROM TBLPROPERTYVISIT pv
WHERE EXISTS (SELECT NULL
FROM TBLAPPOINTMENTS a
WHERE a.appid = pv.appid)
UNION
SELECT jv.propertyid
FROM TBLJOBVISIT jv
WHERE EXISTS (SELECT NULL
FROM TBLAPPOINTMENTS a
WHERE a.appid = jv.appid)) x
LEFT JOIN TBLPROPERTYVISIT y ON y.propertyid = x.propertyid
LEFT JOIN TBLJOBVISIT z ON z.propertyid = x.propertyid
GROUP BY x.propertyid
No need for a UNION at all. And you don't use tblPAppointments either
Edited to allow for no rows in one of the tables. Still one row output though
SELECT
ISNULL(pv2.PropertyID, jv2.PropertyID),
ISNULL(pv2.InitialVisit, 0),
ISNULL(jv2.JobVisit, 0)
FROM
(
SELECT pv.PropertyID, COUNT(pv.VisitID) AS InitialVisit
FROM tblPropertyVisit pv
WHERE pv.Status = 0
GROUP BY pv.PropertyID
) pv2
FULL OUTER JOIN
(
SELECT jv.PropertyID, COUNT(jv.JobVistID) AS JobVisit
FROM tblJobVisits jv
WHERE jv.VisitStatus = 1
GROUP BY jv.PropertyID
) jv2 ON pv2.PropertyID = jv2.PropertyID