Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 根据参数/变量执行子查询 我的问题_Sql_Sql Server_Stored Procedures_Subquery - Fatal编程技术网

Sql 根据参数/变量执行子查询 我的问题

Sql 根据参数/变量执行子查询 我的问题,sql,sql-server,stored-procedures,subquery,Sql,Sql Server,Stored Procedures,Subquery,我试图在合并查询中执行一个查询,以便将结果从一个表拉到另一个表中。这一切都很好,除了一个小插曲 为从表中获取数据而执行的查询依赖于名为@User\u ID的变量 如果@User\u ID为空,则执行子查询A,否则执行子查询B 我的问题是我不知道如何在子查询中放置IF。。。我该怎么做 我所尝试的。。。 这就是我到目前为止所做的: 请注意,这可能有效,但由于我运行的是SQL Server 2008而不是2012,我认为IIF函数不可用,因此我需要另一种方法来实现这一点 使现代化 我也尝试过使用CAS

我试图在合并查询中执行一个查询,以便将结果从一个表拉到另一个表中。这一切都很好,除了一个小插曲

为从表中获取数据而执行的查询依赖于名为@User\u ID的变量

如果@User\u ID为空,则执行子查询A,否则执行子查询B

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

我所尝试的。。。 这就是我到目前为止所做的:

请注意,这可能有效,但由于我运行的是SQL Server 2008而不是2012,我认为IIF函数不可用,因此我需要另一种方法来实现这一点

使现代化 我也尝试过使用CASE,但出现以下错误:

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


如果不测试您的查询,就会出现一个明显的问题,我可以很快提出一种解决方案

问题是:大小写表达式和IIF函数调用使用的是值,而不是结果集。因此,您提出的上述方法在SQL Server 2012中也不起作用

一种可能的解决方案:使用UNION 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;
另一种选择:使用两个完全独立的合并语句,使用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;

出于潜在的性能优势,我可能会选择第二个选项。

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

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\u ID 或者用户ID为空且公司ID匹配


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

可能是我的视力很差,但这两个查询看起来identical@RichardNewman很好的发现,在这个例子中,他们是,但他们并不意味着。将更新。谢谢你指出这一点!:-看起来很好,但是连接呢?好的地方,我假设除了那一点,查询是相同的。左外连接应该注意这一点。请参阅我的更新答案:上面的内容是否没有查询缓存?你会选择什么方法?重复的代码和IF语句,还是如上所述?我应该把Where子句放在哪里?这会返回什么结果?公司还是用户?非常感谢你的帮助,谢谢!联合查询防止自动参数化,因此防止为临时查询缓存;也就是说,在一个过程中没有区别。出于这个原因,我会选择第二种选择,如果没有其他选择的话,使用单独的语句可以分别使用更可能是最优的计划来缓存每个语句。至于返回的结果是什么,恐怕我不明白你的问题。没问题,我现在已经全部解决了。非常感谢!:-。为了接受最佳答案,您对发布的另一个答案有什么看法?这是一个更好的解决方案吗?哈,这非常主观,而且肯定取决于您的数据库结构:-另一个解决方案当然更简单/更易于维护的代码,并且在大多数情况下性能可能不会更差,但我认为它没有回答您关于@User_ID是否为NULL然后执行子查询a的问题,否则执行子查询B。无论如何,我相信另一个答案可能更适合您的情况!
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;