0

次の列を持つテーブルがあります。

Document_ID, Customer_ID, Date, LoanedMoney.

新しいLoanedDateコラムを作成しました。次の方法で日付を入力したいLoanedDate

  1. 前のDate日付または前の日付が存在しない場合 (常に -1 日という意味ではありません)、同じDocument_IDCustomer_IDnull の場合 -> 値をコピーLoanedMoneyしてその値で更新します。
  2. 以前Date(常に -1 日という意味ではありません) が同じDocument_IDで、Customer_IDnull でない場合 -> コピーしてその値で更新します。
  3. それ以外の場合NULLLoanedDate

以前の日付を決定するための私のおおよそのロジック(ケースステートメントに入れる方法がわかりません):

SELECT TOP 1 Z1.Date
FROM DBANME Z1
LEFT JOIN DBNAME Z2
ON Z1.Document_ID = Z2.Document_ID AND Z1.Customer_ID = Z2.Customer_ID AND CONVERT(CHAR(8), Z1.Date, 112) < CONVERT(CHAR(8), Z2.Date, 112)
ORDER BY Date DESC

私はこのようなことをしました:

DECLARE @Min datetime, @Prev datetime
SELECT @Min = MIN(Date) FROM DBNAME     

UPDATE DBNAME
SET LoanedDate CASE

WHEN (LoanedMoney > 0) 
--  SET @Prev = 
    CASE WHEN @Prev IS NULL THEN Date
    ELSE @Prev
ELSE NULL   

それを実装する最良の方法は何ですか?

私が持っているもの:

Document_ID, Customer_ID, Date, LoanedMoney, LoanedDate
1, 1, 2012-04-30, 30, NULL 
1, 1, 2012-04-29, 50, NULL 
1, 1, 2012-04-28, 50, NULL 
1, 1, 2012-04-27, 0, NULL
1, 1, 2012-04-26, 20, NULL

私が期待するもの:

Document_ID, Customer_ID, Date, LoanedMoney, LoanedDate
1, 1, 2012-04-30, 30, 2012-04-28 
1, 1, 2012-04-29, 50, 2012-04-28 
1, 1, 2012-04-28, 50, 2012-04-28 
1, 1, 2012-04-27, 0, NULL -- Because LoanedMoney = 0
1, 1, 2012-04-26, 20, 2012-04-26
4

1 に答える 1

0

このようなことを試してみてください-すべてのルールを強制する相関サブクエリのカップルだけです。最初のサブクエリは現在よりも小さいすべての日付を検索し、2 番目のサブクエリは最新の LoanedMoney = 0 の後の値を削除します。そこから MIN を選択し、NULL の場合は COALESCE を使用して現在の日付に置き換えます。

UPDATE z1
SET LoanedDate = 
    CASE WHEN LoanedMoney = 0 THEN NULL
         ELSE
          COALESCE ( 
             (SELECT MIN(DATE) 
                FROM DBNAME z2 
                WHERE z1.Customer_ID = z2.Customer_ID 
                    AND z1.Document_ID = z2.Document_ID 
                    AND z2.Date < z1.Date   
                    AND z2.Date > (SELECT MAX(DATE) 
                                    FROM dbo.DBNAME z3
                                    WHERE z3.Customer_ID = z2.Customer_ID 
                                        AND z3.Document_ID = z2.Document_ID 
                                        AND z3.Date < z1.Date
                                        AND z3.LoanedMoney = 0)

        ), Date) END
FROM dbo.DBNAME z1

SQLFiddle デモ

編集 - オプション 2

ROW_NUMBER()関数や再帰 CTEなどのさまざまな概念を使用する別の方法を次に示します。少しわかりにくいかもしれませんが、大きなテーブルでの最初のクエリよりも優れたパフォーマンスを発揮します。

WITH CTE_Prep AS 
(
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Document_ID, Customer_ID ORDER BY [DATE]) RN
    FROM DBNAME
)
,RCTE AS 
(
    SELECT *,  CASE WHEN LoanedMoney>0 THEN Date END AS LoanedDate2
    FROM CTE_Prep 
    WHERE RN = 1

    UNION ALL

    SELECT p.*,  CASE WHEN p.LoanedMoney=0 THEN NULL 
                      ELSE CASE WHEN r.LoanedDate2 IS NULL THEN p.Date 
                                ELSE r.LoanedDate2 END 
                 END AS LoanedDate2
    FROM CTE_Prep p
    INNER JOIN RCTE r 
        ON p.Customer_ID = r.Customer_ID
        AND p.Document_ID = r.Document_ID
        AND p.RN = r.RN + 1
)
UPDATE z 
    SET z.LoanedDate = r.LoanedDate2
FROM RCTE r
INNER JOIN dbo.DBNAME z ON r.Customer_ID = z.Customer_ID
    AND r.Document_ID = z.Document_ID
    AND r.Date = z.Date;

SQLFiddleDEMO

于 2013-10-28T15:27:50.757 に答える