票据:
billdate billno
-------------------
2015-04-13 8090
2015-03-11 8089
2015-02-14 8088
2015-02-10 8087
TRANSACTIONS
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 :(得分:0)
您可以使用游标或递归公用表表达式(CTE)。我建议说远离游标,所以这里是CTE的一个例子。
此查询中有很多内容,所以我会尝试将其分解。
如果对这两个表执行FULL JOIN,你会得到一些看起来像答案的东西,但是有很多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
要达到解决方案,我们需要将前一个事件的billno拉到当前事件,如果当前事件的billno是NULL。
为了实现这一点,我们可以使用递归CTE。递归CTE不允许在(http://msdn.microsoft.com/en-us/library/ms175972.aspx)内进行连接,因此我必须将FULL JOIN重构为UNION ALL,别名为" AnchorSet"。该 CTE是INNER JOINed自身,与rownumber / eventdate的偏移量,而billno IS 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
这将为您提供您正在寻找的内容,但最终交易将在最后一个账单之后为空。您可以创建查询以获取最新的billno,并将其应用于事务的billnos的剩余NULL值。我将此作为练习留给读者。