3

我正在使用 SQL Server 2008-R2 和 Transact SQL。

我有一个状态报告,它从多个表/视图返回数据并使用 UNION 将行“连接”在一起。

SQL 脚本的摘录

    SELECT
    NR.FormStatus AS [Item],
    (SELECT COUNT(PerinatalReportID) FROM NotificationDatesForReport 
        WHERE FormStatus = NR.FormStatus AND NotificationDate BETWEEN dbo.DateNoTime(GetDate()) AND dbo.DateNoTime(GetDate() + 1)) AS [Today],
    (SELECT COUNT(PerinatalReportID) FROM NotificationDatesForReport WHERE FormStatus = NR.FormStatus) AS [Total]   

FROM
    NotificationDatesForReport AS NR

GROUP BY
    NR.FormStatus, NR.DisplayOrder  

UNION ALL

SELECT
    'Distinct password requests',
    (SELECT COUNT(DISTINCT ToEMail) FROM PasswordRequests
        WHERE DateProcessed BETWEEN dbo.DateNoTime(GetDate()) AND dbo.DateNoTime(GetDate() + 1)) AS [Today],
    (SELECT COUNT(DISTINCT ToEMail) FROM PasswordRequests) AS [Total]

这可以按预期工作,但是,带有子句的脚本第一部分中的项目顺序GROUP BY以随机顺序出现。我想做的是只对脚本的那一部分进行排序,但我找不到方法来做,因为SORTBY 子句必须在最后一个 UNION 之后。

欢迎所有建议。

4

4 回答 4

2

您可以像这样将整个东西包装在 CTE 中...

WITH cte AS
(
 SELECT
    NR.FormStatus AS [Item],
    (SELECT COUNT(PerinatalReportID) FROM NotificationDatesForReport 
        WHERE FormStatus = NR.FormStatus AND NotificationDate BETWEEN dbo.DateNoTime(GetDate()) AND dbo.DateNoTime(GetDate() + 1)) AS [Today],
    (SELECT COUNT(PerinatalReportID) FROM NotificationDatesForReport WHERE FormStatus = NR.FormStatus) AS [Total],
    0 AS [Section], 
    ROW_NUMBER() OVER (ORDER BY NR.FormStatus, NR.DisplayOrder) AS [DisplayOrder]
FROM
    NotificationDatesForReport AS NR
GROUP BY
    NR.FormStatus, NR.DisplayOrder  

UNION ALL

SELECT
    'Distinct password requests',
    (SELECT COUNT(DISTINCT ToEMail) FROM PasswordRequests
        WHERE DateProcessed BETWEEN dbo.DateNoTime(GetDate()) AND dbo.DateNoTime(GetDate() + 1)) AS [Today],
    (SELECT COUNT(DISTINCT ToEMail) FROM PasswordRequests) AS [Total],
    1 AS [Section],
    ROW_NUMBER() OVER (ORDER BY ToEMail) AS [DisplayOrder]
) 

SELECT ***desired columns*** FROM cte ORDER BY Section, DisplayOrder
于 2013-05-29T13:24:32.700 回答
1

关键是,当您说“[X] 在 [Y] 之后”时,您指定了一个特定的顺序,因此必须在您的代码中为此做出规定。

我猜第一个SELECT应该由 订购NR.DisplayOrder,在这种情况下,这样的事情应该可以解决问题:

    SELECT
    NR.FormStatus AS [Item],
    (SELECT COUNT(PerinatalReportID) FROM NotificationDatesForReport 
        WHERE FormStatus = NR.FormStatus AND NotificationDate BETWEEN dbo.DateNoTime(GetDate()) AND dbo.DateNoTime(GetDate() + 1)) AS [Today],
    (SELECT COUNT(PerinatalReportID) FROM NotificationDatesForReport WHERE FormStatus = NR.FormStatus) AS [Total],
    NR.DisplayOrder
FROM
    NotificationDatesForReport AS NR
GROUP BY
    NR.FormStatus, NR.DisplayOrder  
UNION ALL

SELECT
    'Distinct password requests',
    (SELECT COUNT(DISTINCT ToEMail) FROM PasswordRequests
        WHERE DateProcessed BETWEEN dbo.DateNoTime(GetDate()) AND dbo.DateNoTime(GetDate() + 1)) AS [Today],
    (SELECT COUNT(DISTINCT ToEMail) FROM PasswordRequests) AS [Total],
    999999999 AS DisplayOrder

ORDER BY
    DisplayOrder

在这里,我们在 的每个部分中显式选择排序列UNION,以便ORDER BY在联合完成后可以使用它。DisplayOrder行的合适值Distinct password requests当然取决于数据类型和应用程序细节。

于 2013-05-29T13:09:04.780 回答
0

将联合全部包装并将其放入临时表中..然后对其进行排序

像这样

SELECT * INTO #TMPUNION FROM (
SELECT firstname, lastname FROM TABLE1
UNION ALL
SELECT firstname, lastname FROM TABLE2
)

SELECT * FROM #TMPUNION
ORDER BY FIRSTNAME

确保检查 tmptable 是否存在

编辑:我看到你正在尝试做其他事情。

将第一个表放入 #tmptable 中,并在查询中对其进行排序。

然后联合 tmptable

于 2013-05-29T12:53:10.190 回答
0

您总是可以在涉及工会的地方“欺骗”一点,并在每个工会中添加一个额外的列以进行排序。

; with unions as 
       (
       Select 
           c.name
       ,   c2.name
       ,   1 as 'Order'
       from table1 c 
           join table2 c2 on c.ID =c2.ID
       union
       select 
           c.name
       ,   c2.name
       ,   2
       from table3 c 
           join table4 c2 on c.ID =c2.ID
       )
select *
from unions
order by Order

如果您想变得更加疯狂并进行一些多列排序,您可以在第一个联合块中使用 row_number over() 窗口函数,例如:

row_number over(partition by c.name order by c2.name) as Order

通常,当我想对联合块进行排序时,我会执行类似的操作并显式地放入行号占位符指针,然后使用嵌套选择获取联合块或将它们包装在 CTE 中(如图所示)。

于 2013-05-29T14:11:53.213 回答