如何在sql server中连接两个表而不重复

时间:2013-06-08 16:17:13

标签: sql sql-server

嗨,我有两张桌子A和B

表A:

Order        Pick up
100          Toronto
100          Mississauga
100          Scarborough

表B

Order              Drop off
100                Oakvile
100                Hamilton
100                Milton

请让我知道如何才能获得此输出(即我只想加入A右侧B中的字段)

Order    pickup        Dropoff
100      Toronto       oakvile
100      Mississauga   Hamilton
100      Scarborough   Milton

如何编写查询,我尝试加入a.rownum = b.rownum,但没有运气。

3 个答案:

答案 0 :(得分:1)

由于 OP 未提及任何 RDBMS

我冒昧地将 SQL SERVER 2008 作为 RDBMS 。如果OP希望以下查询可以轻松地转换到任何其他 RDBMS

select A.[Order],
    ROW_NUMBER() OVER(ORDER BY A.[Pick up]) rn1,
    A.[Pick up]
    into A1
FROM A
;
select B.[Order],
    ROW_NUMBER() OVER(ORDER BY B.[Drop off]) rn2,
    B.[Drop off]
    into B1
FROM B
;
Select A1.[Order],
    A1.[Pick up],
    B1.[Drop off]
FROM A1
INNER JOIN B1 on A1.rn1=B1.rn2

<强> SQL FIDDLE to Test

答案 1 :(得分:1)

从使用rownum开始,我假设您使用的是Oracle。您可以尝试以下操作:

select a.Order as "order", a.Pickup, b.DropOff
from (select a.*, rownum as seqnum
      from a
     ) a join
     (select b.*, rownum as seqnum
      from b
     ) b
     on a.order = b.order and a.seqnum = b.seqnum;

(这假设所有订单完全匹配。)

我必须强调,虽然这可能似乎可以工作(并且它应该适用于小例子),但它通常不起作用。并且,它不适用于已删除记录的数据。并且,它可能不适用于并行系统。如果您有少量数据,我建议将其转储到Excel中并在那里进行工作 - 这样,您就可以看出这些对是否有意义。

此外,如果您确实有一个指定排序的列,那么基本相同的结构将起作用:

select coalesce(a.Order, b.Order) as "order", a.Pickup, b.DropOff
from (select a.*,
             row_number() over (partition by "order" order by <ordering field>) as seqnum
      from a
     ) a join
     (select b.*,
             row_number() over (partition by "order" order by <ordering field>) as seqnum
      from b
     ) b
     on a.order = b.order and a.seqnum = b.seqnum;

答案 2 :(得分:0)

我将使用CTE和ROW_NUMBER窗口函数。

WITH keyed_A AS (
  SELECT
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS id
   ,[Order]
   ,[Pick Up]
  FROM A
), keyed_B AS (
  SELECT
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS id
   ,[Order]
   ,[Drop Off]
  FROM B
)
SELECT
   a.[Pick Up]
  ,b.[Drop Off]
  FROM keyed_A AS a
  INNER JOIN keyed_B AS b
    ON a.id = b.id
;

可以将CTE视为具有跨越两个表的id的虚拟表。具有窗口函数ROW_NUMBER的OVER子句可用于在CTE中创建id。由于我们依赖于记录的物理存储(不是一个好主意,请在表中添加键)我们可以ORDER BY(SELECT NULL)这意味着只需使用命令就可以读入。

SQLFiddle to test