1

我的问题

我正在尝试在查询中执行MERGE查询,以便将结果从一个表中提取到另一个表中。这一切都很好,除了一点点小问题......

为从表中获取数据而执行的查询取决于名为 的变量@User_ID

如果@User_IDNULL则执行子查询A,否则执行子查询B。

我遇到的问题是我不知道如何IF在子查询中放置...我该怎么做?

我尝试过的...

这是我到目前为止所拥有的:

请注意,这可能有效,但由于我运行的是 SQL Server 2008 而不是 2012(我认为),所以我认为该IIF功能不可用,所以我需要另一种方法来实现这一点。

-- Get the relevant logins for the past 12 weeks and insert
-- them into the temporary table where the week number is the same
MERGE INTO #Number_Of_Logins AS NOL
USING (
    SELECT IIF (ISNULL(@User_ID,0), (
            SELECT 
                Year(UA.Audit_When) AS Year_Num,
                DatePart(wk, UA.Audit_When) AS Week_Number,
                Count(*) AS Num_Logins
            FROM User_Auditing UA
            WHERE Audit_Type = 'SYSLI'
                AND User_ID = @User_ID
                AND DATEDIFF(wk, Audit_When, GETDATE()) <= 11
            GROUP BY Year(Audit_When), DatePart(wk, Audit_When)
        ),
        (
            SELECT 
                Year(UA.Audit_When) AS Year_Num,
                DatePart(wk, UA.Audit_When) AS Week_Number,
                Count(*) AS Num_Logins
            FROM User_Auditing UA
                JOIN User_Profiles UP ON UA.User_ID = UP.User_ID
            WHERE UA.Audit_Type = 'SYSLI'
                AND UP.Company_ID = @Company_ID
                AND DATEDIFF(wk, UA.Audit_When, GETDATE()) <= 11
            GROUP BY Year(Audit_When), DatePart(wk, UA.Audit_When)
        )
    )
) AS TEST
ON NOL.Week_Number = TEST.Week_Number
WHEN MATCHED THEN
UPDATE
    SET Number_Of_Logins = Num_Logins;

更新

我也尝试过使用CASE,我收到以下错误:

在预期条件的上下文中指定的非布尔类型的表达式,靠近“THEN”。

4

2 回答 2

1

这是您的解决方案,无需在如此高的级别控制流量。

MERGE INTO #Number_Of_Logins AS NOL
USING (
    SELECT 
                Year(UA.Audit_When) AS Year_Num,
                DatePart(wk, UA.Audit_When) AS Week_Number,
                Count(*) AS Num_Logins
            FROM User_Auditing UA
                LEFT OUTER JOIN User_Profiles UP ON UA.User_ID = UP.User_ID
            WHERE Audit_Type = 'SYSLI'
                AND ( User_ID = @User_ID
                    OR ( @User_ID IS NULL
                       AND UP.Company_ID = @Company_ID 
                    )
                )
                AND DATEDIFF(wk, Audit_When, GETDATE()) <= 11
            GROUP BY Year(Audit_When), DatePart(wk, Audit_When)
) AS TEST
ON NOL.Week_Number = TEST.Week_Number
WHEN MATCHED THEN
UPDATE
    SET Number_Of_Logins = Num_Logins;

在此示例中,where 子句的第二个条件是:提供 @User_ID 或用户 ID 为空且公司 ID 匹配。

如果这些条件中的任何一个与您的其他条件一起满足,则包括此记录。这应该封装您需要的所有信息,而无需复杂的嵌套选择。

于 2013-09-18T12:03:13.270 回答
1

没有测试你的查询,有一个明显的问题,我可以快速提出一种解决方案。

问题: CASE表达式和IIF函数调用使用值,而不是结果集。出于这个原因,您上面提出的方法也不适用于 SQL Server 2012。

一种可能的解决方案:使用 aUNION ALL组合两个可能的查询,使用不同的 WHERE 子句来过滤一个或另一个结果集:

-- Get the relevant logins for the past 12 weeks and insert
-- them into the temporary table where the week number is the same
MERGE INTO #Number_Of_Logins AS NOL
USING (
        SELECT 
            Year(UA.Audit_When) AS Year_Num,
            DatePart(wk, UA.Audit_When) AS Week_Number,
            Count(*) AS Num_Logins
        FROM User_Auditing UA
        WHERE Audit_Type = 'SYSLI'
            AND User_ID = @User_ID
            AND DATEDIFF(wk, Audit_When, GETDATE()) <= 11
            AND @User_ID Is Not Null
        GROUP BY Year(Audit_When), DatePart(wk, Audit_When)

        UNION ALL

        SELECT 
            Year(UA.Audit_When) AS Year_Num,
            DatePart(wk, UA.Audit_When) AS Week_Number,
            Count(*) AS Num_Logins
        FROM User_Auditing UA
            JOIN User_Profiles UP ON UA.User_ID = UP.User_ID
        WHERE UA.Audit_Type = 'SYSLI'
            AND UP.Company_ID = @Company_ID
            AND DATEDIFF(wk, UA.Audit_When, GETDATE()) <= 11
            AND @User_ID Is Null
        GROUP BY Year(Audit_When), DatePart(wk, UA.Audit_When)
    )
) AS TEST
ON NOL.Week_Number = TEST.Week_Number
WHEN MATCHED THEN
UPDATE
    SET Number_Of_Logins = Num_Logins;

另一种选择:有两个完全独立的 MERGE 语句,一个 IF 语句选择执行哪个(更多重复的代码,但可能具有查询缓存/性能优势):

-- Get the relevant logins for the past 12 weeks and insert
-- them into the temporary table where the week number is the same
IF @User_ID IS NOT NULL
    MERGE INTO #Number_Of_Logins AS NOL
    USING (
        SELECT Year(UA.Audit_When) AS Year_Num
            ,DatePart(wk, UA.Audit_When) AS Week_Number
            ,Count(*) AS Num_Logins
        FROM User_Auditing UA
        WHERE Audit_Type = 'SYSLI'
            AND User_ID = @User_ID
            AND DATEDIFF(wk, Audit_When, GETDATE()) <= 11
        GROUP BY Year(Audit_When)
            ,DatePart(wk, Audit_When)
        ) AS TEST
        ON NOL.Week_Number = TEST.Week_Number
    WHEN MATCHED
        THEN
            UPDATE
            SET Number_Of_Logins = Num_Logins;
ELSE
    MERGE INTO #Number_Of_Logins AS NOL
    USING (
        SELECT Year(UA.Audit_When) AS Year_Num
            ,DatePart(wk, UA.Audit_When) AS Week_Number
            ,Count(*) AS Num_Logins
        FROM User_Auditing UA
        INNER JOIN User_Profiles UP ON UA.User_ID = UP.User_ID
        WHERE UA.Audit_Type = 'SYSLI'
            AND UP.Company_ID = @Company_ID
            AND DATEDIFF(wk, UA.Audit_When, GETDATE()) <= 11
        GROUP BY Year(Audit_When)
            ,DatePart(wk, UA.Audit_When)
        ) AS TEST
        ON NOL.Week_Number = TEST.Week_Number
    WHEN MATCHED
        THEN
            UPDATE
            SET Number_Of_Logins = Num_Logins;

为了(潜在的)性能优势,我可能会选择第二种选择。

于 2013-09-18T11:59:48.773 回答