在使用STUFF FOR XML连接之前对数据进行排序

时间:2015-08-18 15:53:46

标签: tsql sql-server-2012

我有以下用于SSRS报告的查询:

SELECT  ROW_NUMBER() OVER ( ORDER BY Judge.EventJudgeID ) AS JudgeRow ,
        Judge.EventID ,
        Judge.Judge_PersonID ,
        STUFF(( SELECT DISTINCT
                        ',' + CAST(Fights.FightNumber AS VARCHAR(MAX)) AS [text()]
                FROM    dbo.tblFights Fights ,
                        dbo.tblFightJudge FRJudge
                WHERE   Fights.FightID = FRJudge.fightid
                        AND ( Judge.Judge_PersonID = FRJudge.judge1id
                              OR Judge.Judge_PersonID = FRJudge.judge2id
                              OR Judge.Judge_PersonID = FRJudge.judge3id
                            )
              FOR
                XML PATH('')
              ), 1, 1, '') AS BoutsJudged ,
        Persons.LastName + ' ' + Persons.FirstName AS JudgeName ,
        Events.EventName ,
        Events.EventDate
FROM    dbo.tblEventJudge Judge
        INNER JOIN dbo.tblPersons Persons ON PersonID = Judge_PersonID
        INNER JOIN dbo.tblEvents Events ON Events.EventID = Judge.EventID
WHERE   Judge.EventID = 1278;

问题是STUFF命令返回以下字符串:

1,10,11,12,13,14,15,16,17,18,19,2,3,4,5,6,7,8,9

如何在将数字连接成字符串之前对其进行排序?

2 个答案:

答案 0 :(得分:2)

试试这个

SELECT  ROW_NUMBER() OVER ( ORDER BY Judge.EventJudgeID ) AS JudgeRow ,
        Judge.EventID ,
        Judge.Judge_PersonID ,
        STUFF(Select ',' + CAST(Fights.FightNumber AS VARCHAR(MAX)) AS [text()] From ( SELECT DISTINCT Fights.FightNumber
                FROM    dbo.tblFights Fights ,
                        dbo.tblFightJudge FRJudge
                WHERE   Fights.FightID = FRJudge.fightid
                        AND ( Judge.Judge_PersonID = FRJudge.judge1id
                              OR Judge.Judge_PersonID = FRJudge.judge2id
                              OR Judge.Judge_PersonID = FRJudge.judge3id
                            )
                      ) X 
             ORDER BY Fights.FightNumber
             FOR
                XML PATH('')
              ), 1, 1, '') AS BoutsJudged ,
        Persons.LastName + ' ' + Persons.FirstName AS JudgeName ,
        Events.EventName ,
        Events.EventDate
FROM    dbo.tblEventJudge Judge
        INNER JOIN dbo.tblPersons Persons ON PersonID = Judge_PersonID
        INNER JOIN dbo.tblEvents Events ON Events.EventID = Judge.EventID
WHERE   Judge.EventID = 1278;

您可以查看以下sqls,

之前:

Select *, 
       STUFF((Select Distinct ','+Cast(high as varchar(MAX)) 
              from master..spt_values where type = 'p' and number < 20  
              for xml Path('')),1,1,'')
from  master..spt_values where type = 'p' and number < 20

之后:

Select *, 
           STUFF((Select ','+Cast(high as varchar(MAX)) from (Select distinct     high 
    from master..spt_values where type = 'p' and number < 20) x Order by high  for xml Path('')),1,1,'')
    from  master..spt_values where type = 'p' and number < 20

答案 1 :(得分:0)

我很抱歉这个解决方案很迂腐,但我很难解析代码,需要逐步查看。此外,Microsoft在2012版本中添加了一项功能,但此代码应适用于大多数版本。首先,在大多数SQLServer中使用对用户开放的数据库......

USE MASTER; SELECT TOP 3 TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS;
/*TABLE_NAME      COLUMN_NAME         ORDINAL_POSITION
spt_fallback_db   xserver_name        1
spt_fallback_db   xdttm_ins           2
spt_fallback_db   xdttm_last_ins_upd  3
*/

现在,打破这种方法(对列中的列表进行排序)...
(1)将FOR XML PATH('')添加到1列查询将其转到一行,但为列标题添加XML标记...

SELECT TOP 3 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS FOR XML PATH('');
/*<COLUMN_NAME>xserver_name</COLUMN_NAME><COLUMN_NAME>xdttm_ins</COLUMN_NAME><COLUMN_NAME>xdttm_last_ins_upd</COLUMN_NAME>*/

(2)Concatination使列标题无效,从而消除了标记。任何字符串都可以,我想要逗号空间...

SELECT TOP 3 ', ' + COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS FOR XML PATH('');
/*, xserver_name, xdttm_ins, xdttm_last_ins_upd*/

(3)其他列需要自己的SELECT,因此FOR XML必须是子查询, ORDER BY是FOR XML子查询中的合法前缀;)...

SELECT    TOP 2 TABLE_NAME
        , (SELECT    ', ' + COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
               WHERE COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
            ORDER BY ORDINAL_POSITION FOR XML PATH('')
          ) LIST_OF_COLUMNS
     FROM INFORMATION_SCHEMA.TABLES
 ORDER BY TABLE_NAME;
/*TABLE_NAME      LIST_OF_COLUMNS
spt_fallback_db   , xserver_name, xdttm_ins, xdttm_last_ins_upd, xfallback_dbid, name, dbid, status, version
spt_fallback_dev  , xserver_name, xdttm_ins, xdttm_last_ins_upd, xfallback_low, xfallback_drive, low, high, status, name, phyname
*/

(4)最后,SUBSTRING比STUFF更熟悉删除已知的前缀......

SELECT    TOP 2 TABLE_NAME
        , SUBSTRING((SELECT    ', ' + COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
                         WHERE COLUMNS.TABLE_NAME = TABLES.TABLE_NAME
                      ORDER BY ORDINAL_POSITION FOR XML PATH('')
                        )
                   , 2+1--Add 1 to start substring after the first 2 characters
                   , 99999) LIST_OF_COLUMNS
     FROM INFORMATION_SCHEMA.TABLES
 ORDER BY TABLE_NAME;
/*TABLE_NAME      LIST_OF_COLUMNS
spt_fallback_db    xserver_name, xdttm_ins, xdttm_last_ins_upd, xfallback_dbid, name, dbid, status, version
spt_fallback_dev   xserver_name, xdttm_ins, xdttm_last_ins_upd, xfallback_low, xfallback_drive, low, high, status, name, phyname
*/
     

讽刺的是你 - 吉姆盖特曼