【问题标题】:Sort data before concatenating using STUFF FOR XML在使用 STUFF FOR XML 连接之前对数据进行排序
【发布时间】:2015-08-18 15:53:45
【问题描述】:

我有以下用于 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

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

【问题讨论】:

    标签: tsql sql-server-2012


    【解决方案1】:

    试试这个

    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
    

    【讨论】:

    • 我确实尝试过,但不幸的是,它返回以下错误:如果指定了 SELECT DISTINCT,则消息 145、级别 15、状态 1、行 1 ORDER BY 项目必须出现在选择列表中。所以我尝试按 [text()] 排序,但它不起作用,因为它正在排序创建的字符串,该字符串返回的结果与我在原始问题中的结果相同。
    • ORDER BY CAST(Fights.FightNumber AS VARCHAR(MAX)) 怎么样?
    • 我已经编辑了上面的代码,试试看。首先,我正在做不同的事情,然后用另一个 sql 包装它。由于我没有数据,我无法测试它,如果它有效,请告诉我。
    【解决方案2】:

    对于这种迂腐的解决方案,我深表歉意,但我很难解析代码并且需要逐步查看内容。此外,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) 连接使列标题无效,从而消除了标签。任何字符串都可以,我想要逗号空间...

    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
    */
    

    学究你的 - 吉姆·格特曼

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多