根据多个列连接两个具有条件的表

时间:2015-01-05 16:45:28

标签: sql-server

在SQL Server 2008中,我想在可能有重复的密钥上加入两个表,但匹配对于其他列的信息是唯一的。

对于简化的购买记录示例,

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

它保证:

  1. 表A和表B的行数相同,两个表中的UserId都是相同的数字组。

  2. 对于任何UserIdPayDate总是晚于OrderDate

  3. 具有相同UserId的行与Date的排序序列匹配。例如,表A中的第1行应与表B中的第2行匹配

  4. 我的想法是,在两个表格上,首先按Date排序,然后添加另一个Id列,然后加入此Id列。但我没有授权在数据库中写任何东西。我该怎么做这个任务?

2 个答案:

答案 0 :(得分:2)

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确定计数器何时应“重置”,即在更改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。我选择了外部加入,因为我认为并不总是会为每个订单付款。

答案 1 :(得分:0)

尝试:

;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