Вопрос

I have a SQL Server 2012 query that is returning 1 row of data , BUT could return multiple rows, based on the query.

I want to turn the following data into a csv concatenated string. My query uses STUFF() with a UNION query which I based off this Stack Overflow question.

i.e: my data would be this

MR
------
NS
------

and would become:

MR, NS

When I select the data without the STUFF() part of the query, it returns data no problem.

The full query (see below) runs without errors but always returns NULL even though the SELECT UNION part of the query returns data.

My full query looks like this:

SELECT STUFF((Select * FROM (
SELECT ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines
FROM personenc INNER JOIN contacts ON personenc.cntid = contacts.cntid INNER JOIN scddisc ON contacts.discipline = scddisc.disid
WHERE (personenc.perid = 15410) AND (scddisc.active = 1) AND (contacts.active = 1) AND (scddisc.medgroup = 1) --AND (personenc.sdate BETWEEN '2014-03-05' AND '2014-03-12')
UNION 
SELECT ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines
FROM scddisc INNER JOIN contacts ON scddisc.disid = contacts.discipline INNER JOIN personenc ON contacts.cntid = personenc.ocntid
WHERE (personenc.perid = 15410) AND (scddisc.active = 1) AND (contacts.active = 1) AND (scddisc.medgroup = 1) -- AND (personenc.sdate BETWEEN '2014-03-05' AND '2014-03-12')
) AS k
FOR XML PATH(''),TYPE).value('text()[1]','nvarchar(max)'),1,2,'')

Can anyone let me know what I have done wrong?

The query that works is the SELECT UNION part of the above query i.e. when I run the query below it returns valid data.

SELECT ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines
    FROM personenc INNER JOIN contacts ON personenc.cntid = contacts.cntid INNER JOIN scddisc ON contacts.discipline = scddisc.disid
    WHERE (personenc.perid = 15410) AND (scddisc.active = 1) AND (contacts.active = 1) AND (scddisc.medgroup = 1) --AND (personenc.sdate BETWEEN '2014-03-05' AND '2014-03-12')
    UNION 
    SELECT ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines
    FROM scddisc INNER JOIN contacts ON scddisc.disid = contacts.discipline INNER JOIN personenc ON contacts.cntid = personenc.ocntid
    WHERE (personenc.perid = 15410) AND (scddisc.active = 1) AND (contacts.active = 1) AND (scddisc.medgroup = 1) -- AND (personenc.sdate BETWEEN '2014-03-05' AND '2014-03-12')

However when combined with the FOR XML and STUFF, then the full statement return NULL

Это было полезно?

Решение

Interestingly enough I have found the issue. It appears to be 2 fold...

  • It appears that the .value('text()[1]','nvarchar(max)'),1,2,'') part of the STUFF query was the part that was not displaying data.

    When I change the text() to a . i.e. .value('.[1]','nvarchar(max)'),1,2,'') the query returns as expected.

  • Secondly I had forgotten to add the N', ' + to the ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines to make it a comma separated list as required.

Therefore the whole new statement became:

SELECT
    STUFF (
        (
            SELECT
                *
            FROM
                (
                    SELECT
                        N', ' + ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines
                    FROM
                        personenc
                    INNER JOIN contacts ON personenc.cntid = contacts.cntid
                    INNER JOIN scddisc ON contacts.discipline = scddisc.disid
                    WHERE
                        (personenc.perid = 15410)
                    AND (scddisc.active = 1)
                    AND (contacts.active = 1)
                    AND (scddisc.medgroup = 1) --
                    AND (
                        personenc.sdate BETWEEN '2014-03-05'
                        AND '2014-03-12'
                    )
                    UNION
                        SELECT
                            N', ' + ISNULL(scddisc.abbrev, '!!') AS medicalDisciplines
                        FROM
                            scddisc
                        INNER JOIN contacts ON scddisc.disid = contacts.discipline
                        INNER JOIN personenc ON contacts.cntid = personenc.ocntid
                        WHERE
                            (personenc.perid = 15410)
                        AND (scddisc.active = 1)
                        AND (contacts.active = 1)
                        AND (scddisc.medgroup = 1) -- AND (personenc.sdate BETWEEN '2014-03-05' AND '2014-03-12')
                ) AS k FOR XML PATH (''),
                TYPE ).
            VALUE
                ('.[1]', 'nvarchar(max)'),
                1,
                2,
                ''
        );

Can anyone tell me what the meaning/difference of .value('.[1]','nvarchar(max)'),1,2,'') and .value('text()[1]','nvarchar(max)'),1,2,'') is??

Другие советы

SELECT STUFF (
(SELECT ... FOR XML PATH ('')), 1, 2, '')
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top