2016-12-19 7 views
0

BILLSキーを割り当てる:SQL Serverの、日付範囲によって

billdate billno 
------------------- 
2015-04-13 8090 
2015-03-11 8089 
2015-02-14 8088 
2015-02-10 8087 

取引

transactiondate billno 
----------------------- 
2015-04-15  8090 
2015-04-13  8090 
2015-04-12  8090 
2015-04-10  8090 
2015-03-12  8090 
2015-03-11  8089 
2015-03-10  8089 
2015-02-11  8088 
2015-02-01  8087 

を私は上記のような取引行のアイテムにbillnoを割り当てる必要があります。請求書の範囲外の取引 - つまり、2015-04-13以降の取引は、日付範囲の枠内で一致しないものは、最後に利用可能な請求書と一緒に行く必要があります。また、その逆もあります.2015-02-01のようなボトムエンドのトランザクションは、最後に利用可能な請求書と一緒に行く必要があります。

このクエリについてどうすればよいかわかりません。

+0

あなたは、トランザクションテーブル内のみtransactiondateで始まり、transactiondateとBILLSテーブル内の情報に基づいてTRANSACTIONS.billnoフィールドを移入するクエリを必要としていますか? – Narthring

+0

はい。口座番号だけでなく、請求書と取引をグループ化することもできますが、主なものは、取引と請求書を関連付ける唯一のものは日付です。 – shawno

+0

何か不足していますか? RANGEの日付は表示されません...日付は1つだけです。または「billno of billnoのbilldate-1 of billno + 1」によって定義される範囲ですか? – Tyron78

答えて

0

カーソルまたは再帰共通テーブル式(CTE)を使用できます。私はカーソルから離れて言っておくことをお勧めします。だからここにCTEの例があります。

このクエリでは多くのことが行われていますので、私はそれを細分化しようとします。あなたはFULL 2つのテーブルに対して結合を実行した場合

あなたは答えのように見えるし始め、何かを思い付くが、NULLの多くは、各トランザクションのため 値があります:

DECLARE @Bills TABLE (billdate DATE, billno INT) 
DECLARE @Transactions TABLE (transactiondate DATE) 

INSERT INTO @Bills (billdate, billno) VALUES ('2015-04-13', 8090) 
INSERT INTO @Bills (billdate, billno) VALUES ('2015-03-11', 8089) 
INSERT INTO @Bills (billdate, billno) VALUES ('2015-02-14', 8088) 
INSERT INTO @Bills (billdate, billno) VALUES ('2015-02-10', 8087) 

INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-15') 
INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-13')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-12')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-10')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-03-12')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-03-11')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-03-10')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-02-11')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-02-01') 

SELECT 
    b.billdate, 
    b.billno, 
    t.transactiondate, 
    COALESCE(b.billdate, t.transactiondate) AS [eventdate] 
FROM @Bills b 
FULL JOIN @Transactions t 
    ON b.billdate = t.transactiondate 
ORDER BY eventdate DESC 

Full Join Results

解決に到着するには、現在のイベントのbillnoがNULLの場合、前のイベントのbillnoを現在のイベントにプルする必要があります。

これを達成するには、再帰的なCTEを使用できます。再帰CTEでは(http://msdn.microsoft.com/en-us/library/ms175972.aspx)の結合が許可されないので、FULL JOINをUNION ALLにリファクタリングして、AnchorSetとして別名を付けなければなりませんでした。 CTEはINNER JOINされ、rownumber/eventdateへのオフセットを持ち、billnoはNULLです。

DECLARE @Bills TABLE (billdate DATE, billno INT) 
DECLARE @Transactions TABLE (transactiondate DATE) 

INSERT INTO @Bills (billdate, billno) VALUES ('2015-04-13', 8090) 
INSERT INTO @Bills (billdate, billno) VALUES ('2015-03-11', 8089) 
INSERT INTO @Bills (billdate, billno) VALUES ('2015-02-14', 8088) 
INSERT INTO @Bills (billdate, billno) VALUES ('2015-02-10', 8087) 

INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-15') 
INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-13')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-12')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-04-10')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-03-12')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-03-11')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-03-10')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-02-11')  
INSERT INTO @Transactions (transactiondate) VALUES ('2015-02-01')  

SELECT 
    b.billdate, 
    b.billno, 
    t.transactiondate, 
    COALESCE(b.billdate, t.transactiondate) AS [eventdate] 
FROM @Bills b 
FULL JOIN @Transactions t 
    ON b.billdate = t.transactiondate 
ORDER BY eventdate DESC 

;WITH AnchorSet AS 
(
    SELECT 
     MIN(billdate) AS billdate, 
     MIN(billno) AS billno, 
     MIN(transactiondate) as transactiondate, 
     eventdate 
    FROM 
    (
     SELECT 
      billdate, 
      billno, 
      transactiondate, 
      COALESCE(billdate, transactiondate) AS [eventdate] 
     FROM 
     (
      SELECT 
       billdate, 
       billno, 
       NULL AS [transactiondate] 
      FROM @Bills b 

      UNION ALL 

      SELECT 
       NULL AS billdate, 
       NULL AS billno, 
       transactiondate 
      FROM @transactions t 
     )innerset 
    )innerset2 
    GROUP BY eventdate 
) 
, cte (billdate, billno, transactiondate, eventdate, rownumber, recursionlevel) 
AS 
(
    SELECT 
     billdate, 
     billno, 
     transactiondate, 
     eventdate, 
     ROW_NUMBER() OVER (ORDER BY eventdate DESC) AS [rownumber], 
     0 AS [recursionlevel] 
    FROM 
     AnchorSet 
    WHERE 
     billno IS NULL 

    UNION ALL 

    SELECT 
     COALESCE(RecursiveSet.billdate, cte.billdate) AS [billdate], 
     COALESCE(RecursiveSet.billno, cte.billno) AS [billno], 
     COALESCE(RecursiveSet.transactiondate, cte.transactiondate) AS [transactiondate], 
     COALESCE(RecursiveSet.eventdate, cte.eventdate) AS [eventdate], 
     COALESCE(RecursiveSet.rownumber, cte.rownumber) AS [rownumber], 
     recursionlevel + 1 AS [recursionlevel] 
    FROM 
    (
     SELECT 
      billdate, 
      billno, 
      transactiondate, 
      eventdate, 
      ROW_NUMBER() OVER (ORDER BY eventdate DESC) AS [rownumber] 
     FROM AnchorSet  
    )RecursiveSet 
    INNER JOIN cte ON cte.rownumber = RecursiveSet.rownumber - 1 
) 

SELECT 
    billno, 
    transactiondate 
FROM 
(
    SELECT 
     billno, 
     transactiondate, 
     ROW_NUMBER() OVER (PARTITION BY transactiondate ORDER BY transactiondate DESC, rownumber DESC, recursionlevel DESC, billno DESC) AS [finalrownumber] 
    FROM cte 
)SomeSet 
WHERE finalrownumber = 1 
ORDER BY transactiondate DESC 

Recursive CTE Results

これは、前回の請求の後だから、最終的な取引はnullになりますことを除いて、あなたが探しているもの、あなたを取得します。クエリを作成して最新のbillnoを取得し、トランザクションの請求書の残りのNULL値に適用することができます。私はそれを読者のための練習として残しておきます。

関連する問題