根据多个列的条件连接两个表
Join two tables with conditions depending on multiples columns
在 SQL Server 2008 中,我想加入两个 table 可能有重复的键,但与其他列的信息匹配是唯一的。
对于简化的购买记录示例,
Table A:
UserId PayDate Amount
1 2015 100
1 2010 200
2 2014 150
Table B:
UserId OrderDate Count
1 2009 4
1 2014 2
2 2013 5
Desired Result:
UserId OrderDate PayDate Amount Count
1 2009 2010 200 4
1 2014 2015 100 2
2 2013 2014 150 5
保证:
Table A 和 Table B 的行数相同,并且 table 中的 UserId
是同一组数字。
对于任何 UserId
,PayDate
总是晚于 OrderDate
具有相同 UserId
的行按 Date
的排序序列匹配。例如,Table A 中的第 1 行应匹配 Table B
中的第 2 行
我的想法是,在两个 table 上,首先按 Date
排序,然后添加另一个 Id
列,然后加入此 Id
列。但我无权向数据库中写入任何内容。我该如何完成这个任务?
Row_Number()
将成为您的朋友。它允许您向结果集添加虚拟排序。
运行 并研究输出:
SELECT UserID
, OrderDate
, "Count" As do_not_use_reserved_words_for_column_names
, Row_Number() OVER (PARTITION BY UserID ORDER BY OrderDate) As sequence
FROM table_b
PARTITION BY
确定计数器何时应为 "reset" 即它应在更改 UserID
后重新启动
ORDER BY
,嗯,你猜对了——决定了序列的顺序!
把这一切放在一起:
; WITH payments AS (
SELECT UserID
, PayDate
, Amount
, Row_Number() OVER (PARTITION BY UserID ORDER BY PayDate) As sequence
FROM table_b
)
, orders AS (
SELECT UserID
, OrderDate
, "Count" As do_not_use_reserved_words_for_column_names
, Row_Number() OVER (PARTITION BY UserID ORDER BY OrderDate) As sequence
FROM table_b
)
SELECT orders.UserID
, orders.OrderDate
, orders.do_not_use_reserved_words_for_column_names
, payments.PayDate
, payments.Amount
FROM orders
LEFT
JOIN payments
ON payments.UserID = orders.UserID
AND payments.sequence = orders.sequence
P.S。我选择了外部连接,因为我认为不会总是为每个订单付款。
尝试:
;WITH t1
AS
(
SELECT UserId, PayDate, Amount,
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY PayDate) AS RN
FROM TableA
),
t2
AS
(
SELECT UserId, OrderDate, [Count],
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY OrderDate) AS RN
FROM TableB
)
SELECT t1.UserId, t2.OrderDate, t1.PayDate, t1.Amount, t2.[Count]
FROM t1
INNER JOIN t2
ON t1.UserId = t2.UserId AND t1.RN = t2.RN
在 SQL Server 2008 中,我想加入两个 table 可能有重复的键,但与其他列的信息匹配是唯一的。
对于简化的购买记录示例,
Table A:
UserId PayDate Amount
1 2015 100
1 2010 200
2 2014 150
Table B:
UserId OrderDate Count
1 2009 4
1 2014 2
2 2013 5
Desired Result:
UserId OrderDate PayDate Amount Count
1 2009 2010 200 4
1 2014 2015 100 2
2 2013 2014 150 5
保证:
Table A 和 Table B 的行数相同,并且 table 中的
UserId
是同一组数字。对于任何
UserId
,PayDate
总是晚于OrderDate
具有相同
UserId
的行按Date
的排序序列匹配。例如,Table A 中的第 1 行应匹配 Table B 中的第 2 行
我的想法是,在两个 table 上,首先按 Date
排序,然后添加另一个 Id
列,然后加入此 Id
列。但我无权向数据库中写入任何内容。我该如何完成这个任务?
Row_Number()
将成为您的朋友。它允许您向结果集添加虚拟排序。
运行 并研究输出:
SELECT UserID
, OrderDate
, "Count" As do_not_use_reserved_words_for_column_names
, Row_Number() OVER (PARTITION BY UserID ORDER BY OrderDate) As sequence
FROM table_b
PARTITION BY
确定计数器何时应为 "reset" 即它应在更改 UserID
ORDER BY
,嗯,你猜对了——决定了序列的顺序!
把这一切放在一起:
; WITH payments AS (
SELECT UserID
, PayDate
, Amount
, Row_Number() OVER (PARTITION BY UserID ORDER BY PayDate) As sequence
FROM table_b
)
, orders AS (
SELECT UserID
, OrderDate
, "Count" As do_not_use_reserved_words_for_column_names
, Row_Number() OVER (PARTITION BY UserID ORDER BY OrderDate) As sequence
FROM table_b
)
SELECT orders.UserID
, orders.OrderDate
, orders.do_not_use_reserved_words_for_column_names
, payments.PayDate
, payments.Amount
FROM orders
LEFT
JOIN payments
ON payments.UserID = orders.UserID
AND payments.sequence = orders.sequence
P.S。我选择了外部连接,因为我认为不会总是为每个订单付款。
尝试:
;WITH t1
AS
(
SELECT UserId, PayDate, Amount,
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY PayDate) AS RN
FROM TableA
),
t2
AS
(
SELECT UserId, OrderDate, [Count],
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY OrderDate) AS RN
FROM TableB
)
SELECT t1.UserId, t2.OrderDate, t1.PayDate, t1.Amount, t2.[Count]
FROM t1
INNER JOIN t2
ON t1.UserId = t2.UserId AND t1.RN = t2.RN