1

私の質問

MERGEあるテーブルから別のテーブルに結果を取得するために、クエリ内でクエリを実行しようとしています。これは、1 つの小さな問題を除けば、すべて正常に機能します...

テーブルからデータを取得するために実行されるクエリは、 という変数に依存します@User_ID

の場合@User_IDNULLサブクエリ A を実行し、そうでない場合はサブクエリ B を実行します。

私が抱えている問題はIF、サブクエリ内に を配置する方法がわからないことです...どうすればこれを行うことができますか?

私が試したこと...

これは私がこれまでに持っているものです:

これは機能する可能性がありますが、2012 ではなく SQL Server 2008 を実行しているため (私が思うに)、この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 句の 2 番目の条件は、@User_ID が指定されているか、ユーザー ID が null であり、会社 ID が一致していることを示しています。

これらの条件のいずれかが他の条件とともに満たされている場合は、このレコードを含めます。複雑なネストされた選択なしで、必要なすべての情報をカプセル化する必要があります。

于 2013-09-18T12:03:13.270 に答える
1

クエリをテストしないと、明らかな問題が発生するため、1 つの解決策をすぐに提案できます。

問題: CASE式とIIF関数呼び出しは、結果セットではなく値で機能します。そのため、上記の提案されたアプローチは、SQL Server 2012 でも機能しません。

考えられる解決策の 1 つ: a を使用しUNION ALLて 2 つの考えられるクエリを組み合わせ、異なる 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;

別のオプション: 2 つの完全に別個の 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;

(潜在的な)パフォーマンス上の利点のために、2番目のオプションを使用する可能性があります。

于 2013-09-18T11:59:48.773 に答える