如何使用声明创建视图

How to create view with a declare

我需要根据我编写的查询创建一个视图。这个问题是这个包含一个声明和一个CTE。现在我知道 CTE 应该没问题,但声明会引发问题。部分代码为:

CREATE OR ALTER VIEW vw_NonApprovedTests AS
DECLARE @StartDate DATETIME = (SELECT MIN(ActionOn) FROM WFD) 
DECLARE @EndDate DATETIME = GETDATE();
WITH OrderDays as 
( 
    SELECT 
        CalendarDate = @StartDate
    UNION ALL 
    SELECT 
        CalendarDate = DATEADD(MONTH, 1, CalendarDate)
    FROM 
        OrderDays WHERE DATEADD (MONTH, 1, CalendarDate) <= @EndDate 
),
Calendar AS
(
    SELECT
        EndOfMonth =  EOMONTH (CalendarDate) 
    FROM
        OrderDays                 
) 

SELECT etc.......

它给出的错误是:

Msg 156, Level 15, State 1, Procedure vw_NonApprovedOrWithdrawIntegrityTests, Line 6 [Batch Start Line 0]
Incorrect syntax near the keyword 'DECLARE'.

我用它来计算其余查询中的某些结果。这些结果需要放在一个视图中,以便它们可以在 PowerBI 中用于仪表板。有没有办法让我完成这项工作?

正如我在评论中提到的,您不能在 VIEW 中定义变量。 VIEW 必须由导致 SELECT 单个 语句组成;因此不能将变量定义为 2+ 语句。

正如我还提到的,我建议不要使用 rCTE 来创建日历。它们是 slow,如果您的结果需要超过 100 行,如果您没有在 OPTION 子句中定义 MAXRECURSION 值,则很可能会出错外部查询。

而是使用内联计数或日历 table 来获取所需的日期。我这里用的是理货,个人比较推荐后者(虽然没有样本数据,这个是未经测试的):

CREATE OR ALTER VIEW vw_NonApprovedOrWithdrawIntegrityTests AS

    WITH N AS(
        SELECT N
        FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
    Tally AS(
        SELECT 0 AS I
        UNION ALL
        SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
        FROM N N1, N N2, N N3), --1,000 rows
    Calendar AS(
        SELECT TOP (SELECT DATEDIFF(MONTH,MIN(ActionOn),GETDATE()) FROM dbo.WorkFlowDetails)
               EOMONTH(DATEADD(MONTH,T.I,WFD.ActionOn)) AS EndOfMonth
        FROM Tally T
             CROSS APPLY (SELECT MIN(ActionOn) FROM dbo.WorkFlowDetails) WFD)
    SELECT ...;

您可以通过将变量替换为分配它们的语句来做到这一点,即

WITH OrderDays AS 
(   
    SELECT CalendarDate  = MIN(ActionOn) 
    FROM   WorkFlowDetails 
    UNION ALL 
    SELECT CalendarDate = DATEADD(MONTH, 1, CalendarDate)
    FROM   OrderDays 
    WHERE  DATEADD (MONTH, 1, CalendarDate) <= GETDATE()
), ....

正如评论中所建议的那样,Calendar table 将使这变得更容易,性能也更高:

SELECT  Date
FROM    dbo.Calendar
WHERE   Date >= (SELECT MIN(ActionOn) FROM WorkFlowDetails) 
AND     Date <= GETDATE()