SQL ROW_NUMBER()始终为每行返回1

时间:2016-06-03 17:20:57

标签: sql sql-server

我在这里有这部分查询:

(
    SELECT ROW_NUMBER() OVER (ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS 'SortOrder'
    FOR XML PATH(''), Type
)

这是针对XML的。我的问题是ROW_NUMBER()总是返回1,为什么不为每行返回不同的数字呢?

完整查询:

Select
(

Select cast ('<'+ V_CONSTAT_ACTUAL_DATES.JOB_NUMBER + '>' +
  cast(

   (Select


        (
        SELECT CONVERT(date, V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS 'closingDate'
        FOR XML PATH(''), Type
        ),
        (
        SELECT DATEDIFF(dd,V_CONSTAT_BASE_DATES.ID67,V_CONSTAT_ACTUAL_DATES.DATE_TO_END)-1 AS 'DaysOfConstruction'
        FOR XML PATH(''), Type
        ),
        (
        SELECT DATEDIFF(dd,GETDATE(),V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS 'DaysToClosing'
        FOR XML PATH(''), Type
        ),
        (
            SELECT
            CASE WHEN COALESCE(V_CONSTAT_ACTUAL_DATES.IDNOTES2, '') = '' THEN ' ' ELSE V_CONSTAT_ACTUAL_DATES.IDNOTES2 END AS 'notes'
            FOR XML PATH(''), Type
        ),
        (
        SELECT DATEDIFF(dd,V_CONSTAT_BASE_DATES.ID187,V_CONSTAT_PROJ_DATES.ID187) AS 'ScheduleVariance'
        FOR XML PATH(''), Type
        ),
        (
        SELECT SortOrder FROM 
    (SELECT ROW_NUMBER() OVER
        (ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END)
            AS 'SortOrder') AS SubQuery
FOR XML PATH(''), Type
        )


    for xml path(''))
    as varchar(max)

    )
    + '</'+ V_CONSTAT_ACTUAL_DATES.JOB_NUMBER + '>'
 as xml)
 )
 from ((homefront.dbo.V_CONSTAT_PROJ_DATES V_CONSTAT_PROJ_DATES INNER JOIN homefront.dbo.V_CONSTAT_ACTUAL_DATES V_CONSTAT_ACTUAL_DATES 
        ON 
            V_CONSTAT_PROJ_DATES.JOB_NUMBER=V_CONSTAT_ACTUAL_DATES.JOB_NUMBER) 
        INNER JOIN 
            homefront.dbo.V_CONSTAT_BASE_DATES V_CONSTAT_BASE_DATES 
        ON 
            (V_CONSTAT_ACTUAL_DATES.JOB_NUMBER=V_CONSTAT_BASE_DATES.JOB_NUMBER) AND (V_CONSTAT_PROJ_DATES.JOB_NUMBER=V_CONSTAT_BASE_DATES.JOB_NUMBER)) 
        INNER JOIN 
            homefront.dbo.V_CONSTAT_SCH_DATES V_CONSTAT_SCH_DATES 
        ON 
            ((V_CONSTAT_BASE_DATES.JOB_NUMBER=V_CONSTAT_SCH_DATES.JOB_NUMBER) AND (V_CONSTAT_PROJ_DATES.JOB_NUMBER=V_CONSTAT_SCH_DATES.JOB_NUMBER)) 
            AND (V_CONSTAT_ACTUAL_DATES.JOB_NUMBER=V_CONSTAT_SCH_DATES.JOB_NUMBER)



WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC = 'Ancaster Augusta Ph 4(A) Condos' AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()
ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END
FOR XML PATH(''), ROOT('Root')

4 个答案:

答案 0 :(得分:4)

您将ROW_NUMBER()放在标量子查询中只有一行:

(SELECT ROW_NUMBER() OVER
    (ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END)
        AS 'SortOrder')

您可能认为ORDER BY子句(引用外部查询中的列)对此处的ROW_NUMBER()计算有任何影响。它没有。此子查询返回一行,该行唯一合理的ROW_NUMBER始终为1

解决方案是尽可能延迟将结果转换为XML,并且只需通过顶层ROW_NUMBER()的{​​{1}}计算选择您的数据。

答案 1 :(得分:1)

您可以根据需要使用子查询。尝试这样的事情:

SELECT SortOrder FROM 
    (SELECT ROW_NUMBER() OVER
        (ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END)
            AS 'SortOrder') AS SubQuery
FOR XML PATH(''), Type

编辑: 在查看完整查询后,我可以向您推荐另一种解决方案。

Actualy你将在subselect中拥有所有查询逻辑,并且ROW_NUMBER()函数将完美运行。外部部分将涵盖XML格式的查询。

<强> P.S。更多解释:

SELECT (
    SELECT CAST('<'+JOB_NUMBER + '>' +  
        CAST((SELECT
            (SELECT closingDate FOR XML PATH(''), Type),
            (SELECT DaysOfConstruction FOR XML PATH(''), Type),
            (SELECT DaysToClosing FOR XML PATH(''), Type),
            (SELECT notes FOR XML PATH(''), Type),
            (SELECT ScheduleVariance FOR XML PATH(''), Type),
            (SELECT SortOrder FOR XML PATH(''), Type)
        FOR XML PATH('')) AS VARCHAR(MAX))
    + '</'+ JOB_NUMBER + '>' as xml))
FROM 
    (SELECT 
        V_CONSTAT_ACTUAL_DATES.JOB_NUMBER,
        CONVERT(date, V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS closingDate,
        DATEDIFF(dd, V_CONSTAT_BASE_DATES.ID67,V_CONSTAT_ACTUAL_DATES.DATE_TO_END) - 1 AS DaysOfConstruction,
        DATEDIFF(dd, GETDATE(),V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS DaysToClosing,
        (CASE WHEN COALESCE(V_CONSTAT_ACTUAL_DATES.IDNOTES2, '') = '' THEN ' ' ELSE V_CONSTAT_ACTUAL_DATES.IDNOTES2 END) AS notes,
        DATEDIFF(dd, V_CONSTAT_BASE_DATES.ID187,V_CONSTAT_PROJ_DATES.ID187) AS ScheduleVariance,
        ROW_NUMBER() OVER (ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS SortOrder
    FROM homefront.dbo.V_CONSTAT_PROJ_DATES V_CONSTAT_PROJ_DATES
        INNER JOIN homefront.dbo.V_CONSTAT_ACTUAL_DATES V_CONSTAT_ACTUAL_DATES ON V_CONSTAT_PROJ_DATES.JOB_NUMBER=V_CONSTAT_ACTUAL_DATES.JOB_NUMBER 
        INNER JOIN homefront.dbo.V_CONSTAT_BASE_DATES V_CONSTAT_BASE_DATES ON 
            V_CONSTAT_ACTUAL_DATES.JOB_NUMBER=V_CONSTAT_BASE_DATES.JOB_NUMBER AND V_CONSTAT_PROJ_DATES.JOB_NUMBER=V_CONSTAT_BASE_DATES.JOB_NUMBER
        INNER JOIN homefront.dbo.V_CONSTAT_SCH_DATES V_CONSTAT_SCH_DATES ON 
                V_CONSTAT_BASE_DATES.JOB_NUMBER=V_CONSTAT_SCH_DATES.JOB_NUMBER AND V_CONSTAT_PROJ_DATES.JOB_NUMBER=V_CONSTAT_SCH_DATES.JOB_NUMBER 
                AND V_CONSTAT_ACTUAL_DATES.JOB_NUMBER=V_CONSTAT_SCH_DATES.JOB_NUMBER
    WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC = 'AnCASTer Augusta Ph 4(A) Condos' AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END>=GETDATE()) AS SubQuery
ORDER BY closingDate
FOR XML PATH(''), ROOT('Root')

答案 2 :(得分:1)

通过派生表使用分析函数是很常见的,以便生成列,然后通过列别名由后续子句访问。当需要在where子句中使用row_number()时,这种情况尤为常见。 e.g。

select * from (select *
                  , row_number(partition by X order by Y) as rn
               from table1
               ) as d
where d.rn = 1

这里我相信相同的逻辑适用,您想要计算排序顺序列然后将数据放入XML结果。我的猜测是你要按作业号进行分区。

FROM (
  SELECT
        *
      , ROW_NUMBER() OVER (PARTITION BY V_CONSTAT_ACTUAL_DATES.JOB_NUMBER
                            ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS 'SortOrder'
  FROM homefront.dbo.V_CONSTAT_PROJ_DATES V_CONSTAT_PROJ_DATES
        INNER JOIN homefront.dbo.V_CONSTAT_ACTUAL_DATES V_CONSTAT_ACTUAL_DATES ON V_CONSTAT_PROJ_DATES.JOB_NUMBER = V_CONSTAT_ACTUAL_DATES.JOB_NUMBER
        INNER JOIN homefront.dbo.V_CONSTAT_BASE_DATES V_CONSTAT_BASE_DATES ON V_CONSTAT_ACTUAL_DATES.JOB_NUMBER = V_CONSTAT_BASE_DATES.JOB_NUMBER
                    AND V_CONSTAT_PROJ_DATES.JOB_NUMBER = V_CONSTAT_BASE_DATES.JOB_NUMBER
        INNER JOIN homefront.dbo.V_CONSTAT_SCH_DATES V_CONSTAT_SCH_DATES ON V_CONSTAT_BASE_DATES.JOB_NUMBER = V_CONSTAT_SCH_DATES.JOB_NUMBER
                    AND V_CONSTAT_PROJ_DATES.JOB_NUMBER = V_CONSTAT_SCH_DATES.JOB_NUMBER
                    AND V_CONSTAT_ACTUAL_DATES.JOB_NUMBER = V_CONSTAT_SCH_DATES.JOB_NUMBER
  WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC = 'Ancaster Augusta Ph 4(A) Condos'
        AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END >= GETDATE()
  ) AS d

并作为完整查询:

SELECT (
        SELECT
              CAST('<' + V_CONSTAT_ACTUAL_DATES.JOB_NUMBER + '>' +
              CAST((
                    SELECT (
                                 SELECT
                                       CONVERT(date, d.DATE_TO_END) AS 'closingDate'
                                 FOR xml PATH (''), TYPE
                           )
                         , (
                                 SELECT
                                       DATEDIFF(dd, d.ID67, V_CONSTAT_ACTUAL_DATES.DATE_TO_END) - 1 AS 'DaysOfConstruction'
                                 FOR xml PATH (''), TYPE
                           )
                         , (
                                 SELECT
                                       DATEDIFF(dd, GETDATE(), d.DATE_TO_END) AS 'DaysToClosing'
                                 FOR xml PATH (''), TYPE
                           )
                         , (
                                 SELECT
                                       CASE
                                             WHEN COALESCE(d.IDNOTES2, '') = '' THEN ' '
                                             ELSE d.IDNOTES2
                                       END AS 'notes'
                                 FOR xml PATH (''), TYPE
                           )
                         , (
                                 SELECT
                                       DATEDIFF(dd, d.ID187, d.ID187) AS 'ScheduleVariance'
                                 FOR xml PATH (''), TYPE
                           )
                         , (
                                 SELECT
                                       SortOrder
                                 FROM (
                                       SELECT
                                             d.SortOrder
                                 ) AS SubQuery
                                 FOR xml PATH (''), TYPE
                           )


                    FOR xml PATH ('')
              )
              AS varchar(max)

              )
              + '</' + V_CONSTAT_ACTUAL_DATES.JOB_NUMBER + '>'
              AS xml)
  )
FROM (
  SELECT
        *
      , ROW_NUMBER() OVER (PARTITION BY V_CONSTAT_ACTUAL_DATES.JOB_NUMBER
                            ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS "SortOrder"
  FROM homefront.dbo.V_CONSTAT_PROJ_DATES V_CONSTAT_PROJ_DATES
        INNER JOIN homefront.dbo.V_CONSTAT_ACTUAL_DATES V_CONSTAT_ACTUAL_DATES ON V_CONSTAT_PROJ_DATES.JOB_NUMBER = V_CONSTAT_ACTUAL_DATES.JOB_NUMBER
        INNER JOIN homefront.dbo.V_CONSTAT_BASE_DATES V_CONSTAT_BASE_DATES ON V_CONSTAT_ACTUAL_DATES.JOB_NUMBER = V_CONSTAT_BASE_DATES.JOB_NUMBER
                    AND V_CONSTAT_PROJ_DATES.JOB_NUMBER = V_CONSTAT_BASE_DATES.JOB_NUMBER
        INNER JOIN homefront.dbo.V_CONSTAT_SCH_DATES V_CONSTAT_SCH_DATES ON V_CONSTAT_BASE_DATES.JOB_NUMBER = V_CONSTAT_SCH_DATES.JOB_NUMBER
                    AND V_CONSTAT_PROJ_DATES.JOB_NUMBER = V_CONSTAT_SCH_DATES.JOB_NUMBER
                    AND V_CONSTAT_ACTUAL_DATES.JOB_NUMBER = V_CONSTAT_SCH_DATES.JOB_NUMBER
  WHERE V_CONSTAT_ACTUAL_DATES.AREA_DESC = 'Ancaster Augusta Ph 4(A) Condos'
        AND V_CONSTAT_ACTUAL_DATES.DATE_TO_END >= GETDATE()
  ) AS d
ORDER BY
      V_CONSTAT_ACTUAL_DATES.DATE_TO_END
FOR xml PATH (''), ROOT ('Root')

答案 3 :(得分:1)

  

我的问题是ROW_NUMBER()总是返回1,怎么回事   为每一行返回不同的数字?

<强>原因

1)原因是跟随子查询

(
    SELECT ROW_NUMBER() OVER (ORDER BY V_CONSTAT_ACTUAL_DATES.DATE_TO_END) AS 'SortOrder'
    FOR XML PATH(''), Type
)

相同
(
SELECT ROW_NUMBER() OVER (ORDER BY a.b) AS 'SortOrder'
FROM (VALUES 
    (V_CONSTAT_ACTUAL_DATES.DATE_TO_END) -- one column / one row
) AS a(b)

(
SELECT ROW_NUMBER() OVER (ORDER BY a.b) AS 'SortOrder'
FROM ( 
    SELECT V_CONSTAT_ACTUAL_DATES.DATE_TO_END -- one column / one row
) AS a(b)

这意味着以上所有子查询都将一个数据集作为数据源,其中一列,(最重要的是)一行。这就是ROW_NUMBER始终返回1的原因:因为当前子查询始终只有一个源行。

2)更多,下一个查询返回相同的结果

SELECT  *,
    (
    SELECT ROW_NUMBER() OVER (ORDER BY a.b) AS 'SortOrder'
    FROM (VALUES 
        (V_CONSTAT_ACTUAL_DATES.DATE_TO_END) -- one column / one row
    ) AS a(b)
    FOR XML PATH(''), Type
    ) AS XMLCOLUMN
FROM    (VALUES 
    ('A', '20160302'),
    ('B', '20160202'),
    ('C', '20160101')
) V_CONSTAT_ACTUAL_DATES(CODE, DATE_TO_END)

SELECT  *,
    (
    SELECT ROW_NUMBER() OVER (ORDER BY a.b) AS 'SortOrder'
    FROM ( 
        SELECT V_CONSTAT_ACTUAL_DATES.DATE_TO_END -- one column / one row
    ) AS a(b)
    FOR XML PATH(''), Type
    ) AS XMLCOLUMN
FROM    (VALUES 
    ('A', '20160302'),
    ('B', '20160202'),
    ('C', '20160101')
) V_CONSTAT_ACTUAL_DATES(CODE, DATE_TO_END)

结果

CODE DATE_TO_END XMLCOLUMN
---- ----------- ------------------------
A    20160302    <SortOrder>1</SortOrder>
B    20160202    <SortOrder>1</SortOrder>
C    20160101    <SortOrder>1</SortOrder>

并且具有相同(几乎)的执行计划,具有相同的估计查询成本(33%): enter image description here

一种解决方案可能是包含ROW_NUMBER' within V_CONSTAT_ACTUAL_DATES`视图。

注意/友好警告:请不要使用列值连接<>以生成所需的XML数据!我只会使用FOR XML。如果您想解决此问题,请发布另一个问题。