how to convert xml out put of a TSQL query into varchar output - sql

I am trying to generate
SELECT DISTINCT
P.DOMAIN_ID,
P.SOURCE_SYSTEM_ID
FROM EDW.dbo.DOMAIN_VALUE AS P
WHERE P.ID = 4
AND CURRENT_FLAG = 'Y'
EXCEPT
( SELECT F.DOMAIN_ID,
F.SOURCE_SYSTEM_ID
FROM EDW.dbo.DOMAIN AS F
WHERE F.ID = 4
AND F.CURRENT_FLAG = 'Y'
)
FOR XML PATH('DOMAIN'),
ROOT('DOMAIN_VALUE')
The output value in XML in Result tab as
<REFERENCE_DOMAIN_VALUE>
<REFERENCE_DOMAIN>
<REFERENCE_DOMAIN_ID>10799</REFERENCE_DOMAIN_ID>
<REFERENCE_SOURCE_SYSTEM_ID>7452-001</REFERENCE_SOURCE_SYSTEM_ID>
</REFERENCE_DOMAIN>
</REFERENCE_DOMAIN_VALUE>
Now I need to convert this XML out to varchar(max) but the result needs to be same.

Just subquery it into a scalar value and convert it. The trick here is that FOR XML in a subquery and EXCEPT on top don't mix, so subquery the EXCEPT part first.
SELECT CONVERT(varchar(max), (
SELECT * FROM (
SELECT DISTINCT P.DOMAIN_ID, P.SOURCE_SYSTEM_ID
FROM EDW.dbo.DOMAIN_VALUE AS P
WHERE P.ID = 4 AND CURRENT_FLAG = 'Y'
EXCEPT (
SELECT F.DOMAIN_ID, F.SOURCE_SYSTEM_ID
FROM EDW.dbo.DOMAIN AS F
WHERE F.ID = 4 AND F.CURRENT_FLAG = 'Y' )
) I
FOR XML PATH('DOMAIN'), ROOT('DOMAIN_VALUE')
))

Related

Types don't match between the anchor and the recursive part

I am executing the following query :
WITH rg(id, childid, NAME)
AS (SELECT id,
0 ChildID,
NAME
FROM kuaf
WHERE id = 1000
UNION ALL
SELECT c.id,
c.childid,
k.NAME
FROM kuafchildren c
JOIN rg p
ON ( c.childid = p.id )
JOIN kuaf k
ON ( c.id = k.id ))
SELECT DISTINCT ka.id
FROM rg,
lm_approvals app
JOIN kuaf ka
ON ( ka.id = app.useridentifier )
JOIN dtree dt
ON ( dt.dataid = app.dataid )
WHERE app.dataid = 25773
AND app.isapproved = 0
AND Replace(ka.NAME, ka.type + '_', dt.ownerid + '_') = rg.NAME
But I am ending with the following error:
Types don't match between the anchor and the recursive part in column
"ChildID" of recursive query "rg".
If you change the first SELECT or the anchor part of the resursive CTE as follows, it will work
SELECT id,
CAST(0 as int) ChildID,
NAME
FROM kuaf
WHERE id = 1000
This is the case we experience generally with empty string or NULL is selected at this step.
So explicitely defining the type at anchor SELECT is required for CTEs
I myself have not tried this
Judging by the documentation
it is necessary to explicitly convert
0 type like kuafchildren.childid
through
CAST ( expression AS data_type [ ( length ) ] )
or
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
expression - 0
data_type [ ( length ) ] ) same as kuafchildren.childid
You can try to write instead
0 ChildID
kuaf.id*0 ChildID
This might work if kuaf.id type the same as the kuafchildren.childid
Try this ...
;WITH CTE RG AS (
SELECT Id,
0 AS 'ChildId',
Name
FROM Kuaf
WHERE id = 1000
UNION ALL
SELECT C.Id,
C.ChildId,
C.Name
FROM KuafChildren C
INNER JOIN RG ON (C.ChildId = RG.ChildId)
)
SELECT ...
I assume ChildId column datatype is int

How to combine different counts in one SQL Server query

I would like to combine different Count statements in one query so that in the end the query just returns one number (total) for each Count.
The following queries work separately but I could not find a way to combine them without repeating the same result (nested tables) and without losing the separate names for each of them (Union All).
My SQL (just combined for easier view here):
(
SELECT COUNT(*) OVER() AS countB
FROM MOC_Log2 B
WHERE B.modBy = #modBy
AND B.lastUpdate = 'Added'
FOR XML PATH(''), ELEMENTS, TYPE
),
(
SELECT COALESCE(SUM(D.vote), '0') AS countC
FROM MOC_Log3 C
LEFT JOIN MOC_Log3_Votes D
ON D.itemID = C.itemID
WHERE C.modBy = #modBy
AND C.lastUpdate = 'Added'
FOR XML PATH(''), ELEMENTS, TYPE
),
(
SELECT COALESCE(SUM(F.vote), '0') AS countE
FROM MOC_Log4 E
LEFT JOIN MOC_Log4_Votes F
ON F.itemID = E.itemID
WHERE E.modBy = #modBy
AND E.lastUpdate = 'Added'
FOR XML PATH(''), ELEMENTS, TYPE
)
just add null columns?
SELECT COUNT(*) OVER() AS countB,
Null AS countC,
Null AS countE
FROM MOC_Log2 B
WHERE B.modBy = #modBy
AND B.lastUpdate = 'Added'
FOR XML PATH(''), ELEMENTS, TYPE
Union
SELECT null,
COALESCE(SUM(D.vote), '0'),
null
FROM MOC_Log3 C
LEFT JOIN MOC_Log3_Votes D
ON D.itemID = C.itemID
WHERE C.modBy = #modBy
AND C.lastUpdate = 'Added'
FOR XML PATH(''), ELEMENTS, TYPE
Union
SELECT null,
null,
COALESCE(SUM(F.vote), '0')
FROM MOC_Log4 E
LEFT JOIN MOC_Log4_Votes F
ON F.itemID = E.itemID
WHERE E.modBy = #modBy
AND E.lastUpdate = 'Added'
FOR XML PATH(''), ELEMENTS, TYPE
Also note I used Union over Union all. It is hard to tell if this would work for you as I cannot tell if the extra null columns may cause some error.

Replace no result

I have a query like this:
SELECT TV.Descrizione as TipoVers,
sum(ImportoVersamento) as ImpTot,
count(*) as N,
month(DataAllibramento) as Mese
FROM PROC_Versamento V
left outer join dbo.PROC_TipoVersamento TV
on V.IDTipoVersamento = TV.IDTipoVersamento
inner join dbo.PROC_PraticaRiscossione PR
on V.IDPraticaRiscossioneAssociata = PR.IDPratica
inner join dbo.DA_Avviso A
on PR.IDDatiAvviso = A.IDAvviso
where DataAllibramento between '2012-09-08' and '2012-09-17' and A.IDFornitura = 4
group by V.IDTipoVersamento,month(DataAllibramento),TV.Descrizione
order by V.IDTipoVersamento,month(DataAllibramento)
This query must always return something. If no result is produced a
0 0 0 0
row must be returned. How can I do this. Use a isnull for every selected field isn't usefull.
Use a derived table with one row and do a outer apply to your other table / query.
Here is a sample with a table variable #T in place of your real table.
declare #T table
(
ID int,
Grp int
)
select isnull(Q.MaxID, 0) as MaxID,
isnull(Q.C, 0) as C
from (select 1) as T(X)
outer apply (
-- Your query goes here
select max(ID) as MaxID,
count(*) as C
from #T
group by Grp
) as Q
order by Q.C -- order by goes to the outer query
That will make sure you have always at least one row in the output.
Something like this using your query.
select isnull(Q.TipoVers, '0') as TipoVers,
isnull(Q.ImpTot, 0) as ImpTot,
isnull(Q.N, 0) as N,
isnull(Q.Mese, 0) as Mese
from (select 1) as T(X)
outer apply (
SELECT TV.Descrizione as TipoVers,
sum(ImportoVersamento) as ImpTot,
count(*) as N,
month(DataAllibramento) as Mese,
V.IDTipoVersamento
FROM PROC_Versamento V
left outer join dbo.PROC_TipoVersamento TV
on V.IDTipoVersamento = TV.IDTipoVersamento
inner join dbo.PROC_PraticaRiscossione PR
on V.IDPraticaRiscossioneAssociata = PR.IDPratica
inner join dbo.DA_Avviso A
on PR.IDDatiAvviso = A.IDAvviso
where DataAllibramento between '2012-09-08' and '2012-09-17' and A.IDFornitura = 4
group by V.IDTipoVersamento,month(DataAllibramento),TV.Descrizione
) as Q
order by Q.IDTipoVersamento, Q.Mese
Use COALESCE. It returns the first non-null value. E.g.
SELECT COALESCE(TV.Desc, 0)...
Will return 0 if TV.DESC is NULL.
You can try:
with dat as (select TV.[Desc] as TipyDesc, sum(Import) as ToImp, count(*) as N, month(Date) as Mounth
from /*DATA SOURCE HERE*/ as TV
group by [Desc], month(Date))
select [TipyDesc], ToImp, N, Mounth from dat
union all
select '0', 0, 0, 0 where (select count (*) from dat)=0
That should do what you want...
If it's ok to include the "0 0 0 0" row in a result set that has data, you can use a union:
SELECT TV.Desc as TipyDesc,
sum(Import) as TotImp,
count(*) as N,
month(Date) as Mounth
...
UNION
SELECT
0,0,0,0
Depending on the database, you may need a FROM for the second SELECT. In Oracle, this would be "FROM DUAL". For MySQL, no FROM is necessary

Adding Switch to WHERE clausse

I've been trying to add a switch into the following script.
If #IgnoreExclusions = 1 then I do not want to exclude any of the values in Controltb_AssocAccounts_ExcludedSurnameDOB or in Controltb_AssocAccounts_ExcludedDOB ?
I've included one of my attempts but I don't think this is very readable and also I'm unsure if it works reliably as NULL could be a value in one of the exclusion lists.
DECLARE #IgnoreExclusions TINYINT = 1;
SELECT ua.UserAccountKey,
FROM #Accounts x
INNER JOIN WH.dbo.vw_DimUserAccount ua
ON
( --surname and DOB need to match
x.Surname = ua.Surname AND
x.DOB = ua.DOB
)
AND
x.UserAccountKey <> ua.UserAccountKey
WHERE EXISTS
(
SELECT x.Surname, x.DOB
EXCEPT
SELECT ExcludedSurname,ExcludedDOB
FROM WH.dbo.Controltb_AssocAccounts_ExcludedSurnameDOB
)
AND
EXISTS
(
SELECT x.DOB
--SELECT CASE WHEN #IgnoreExclusions = 1 THEN NULL ELSE x.DOB END --<<<<ATTEMPT
EXCEPT
SELECT ExcludedDOB
FROM WH.dbo.Controltb_AssocAccounts_ExcludedDOB
)
GROUP BY ua.UserAccountKey;
I'm not sure what variant of SQL you're using, but couldn't a simple OR clause do the trick?
DECLARE #IgnoreExclusions TINYINT = 1;
SELECT ua.UserAccountKey,
FROM #Accounts x
INNER JOIN WH.dbo.vw_DimUserAccount ua
ON x.Surname = ua.Surname
AND x.DOB = ua.DOB
AND x.UserAccountKey <> ua.UserAccountKey
WHERE EXISTS
(
SELECT x.Surname, x.DOB
EXCEPT
SELECT ExcludedSurname,ExcludedDOB
FROM WH.dbo.Controltb_AssocAccounts_ExcludedSurnameDOB
)
AND
(
#IgnoreExclusions = 1 OR EXISTS
(
SELECT x.DOB
EXCEPT
SELECT ExcludedDOB
FROM WH.dbo.Controltb_AssocAccounts_ExcludedDOB
)
)
GROUP BY ua.UserAccountKey;

ordering by sql on fields not in projection

Is it possible to order the results of an SQL query, on a field that is not in the projection itself?
See example below - I am taking the distinct ID of a product table, but I want it ordered by title. I don't want to include the title because I am using NHibernate to generate a query, and page the results. I am then using this distinct ID resultset, to load the actual results.
SELECT
DISTINCT this_.`ID` AS y0
FROM
`Product` this_
LEFT OUTER JOIN
`Brand` brand3_
ON this_.BrandId=brand3_.ID
INNER JOIN
`Product_CultureInfo` productcul2_
ON this_.ID=productcul2_.ProductID
AND (
(
(
productcul2_.`Deleted` = 0
OR productcul2_.`Deleted` IS NULL
)
AND (
productcul2_.`_Temporary_Flag` = 0
OR productcul2_.`_Temporary_Flag` IS NULL
)
)
)
INNER JOIN
`ProductCategory` aliasprodu1_
ON this_.ID=aliasprodu1_.ProductID
AND (
(
(
aliasprodu1_.`Deleted` = 0
OR aliasprodu1_.`Deleted` IS NULL
)
AND (
aliasprodu1_.`_Temporary_Flag` = 0
OR aliasprodu1_.`_Temporary_Flag` IS NULL
)
)
)
WHERE
(
this_._Temporary_Flag =FALSE
OR this_._Temporary_Flag IS NULL
)
AND this_.Published = TRUE
AND (
this_.Deleted = FALSE
OR this_.Deleted IS NULL
)
AND (
this_._ComputedDeletedValue = FALSE
OR this_._ComputedDeletedValue IS NULL
)
AND (
(
this_._TestItemSessionGuid IS NULL
OR this_._TestItemSessionGuid = ''
)
)
AND (
productcul2_._ActualTitle LIKE '%silver%'
OR brand3_.Title LIKE '%silver%'
OR aliasprodu1_.CategoryId IN (
47906817 , 47906818 , 47906819 , 47906816 , 7012353 , 44662785
)
)
AND this_.Published = TRUE
AND this_.Published = TRUE
ORDER BY
this_.Priority ASC,
productcul2_._ActualTitle ASC,
this_.Priority ASC LIMIT 25;
Don't know if there's a better solution but how about a nested select where the external query exlude the field that you're not interested in?
So, something like that on a "random" table
SELECT a,b,c from (SELECT a,b,c,d from myTable order by d)
Obviously if there is a "language-direct" solution will be better because, in that way, you have to do two projection and one of those is useless