Sql 使用自联接将2行合并为1行

Sql 使用自联接将2行合并为1行,sql,sql-server,join,Sql,Sql Server,Join,下面是简化的表格 CustNr OrderNr Date Price Curry 1 555 030316 2,4 EUR 1 666 030316 2,5 EUR 1 777 030316 2,3 EUR 1 777 030316 1,9 USD 1 888 030316 2,3 EUR 1 888 030316 2,4 EUR 期望输出: C

下面是简化的表格

CustNr OrderNr Date    Price Curry
1      555     030316  2,4   EUR
1      666     030316  2,5   EUR
1      777     030316  2,3   EUR
1      777     030316  1,9   USD
1      888     030316  2,3   EUR
1      888     030316  2,4   EUR
期望输出:

CustNr OrderNr Date    Price Curry   CustNr OrderNr Date    Price Curry
1      555     030316  2,4   EUR
1      666     030316  2,5   EUR
1      777     030316  2.3   EUR     1      777     030316   1,9   USD
1      888     030316  2,3   EUR     1      888     030316   2,4   EUR
我尝试了以下自我连接:

SELECT * FROM TEST T1 INNER JOIN TEST T2 ON T1.OrderNr = T2.OrderNr

但是我会得到重复的记录,并且只有在按OrderNr分组时,groupby才有效,但我还需要其他列

您需要一个表示唯一订单号的顶级查询:

select 
t.OrderNr,
t1.*,
t2.*
from (select distinct OrderNr from test) t
cross apply (select top 1 * from test t1 where t1.OrderNr = t.OrderNr order by Curry) t1
outer apply (select top 1 * from test t2 where t2.OrderNr = t.OrderNr and t2.Curry <> t1.Curry order by Curry) t2

我认为这回答了这个问题,但我认为它提出了更多关于所需输出设计的问题。

您应该使用左连接而不是内部连接并按Curry过滤

SELECT * FROM TEST T1 LEFT JOIN TEST T2 ON (T1.OrderNr = T2.OrderNr
AND  T1.Curry <> T2.Curry )

我觉得你的问题不是100%清楚。但根据您当前的描述,此查询应该可以:

with cte as (
  select CustNr, OrderNr, Date, Price, Curry,
         row_number() over (partition by OrderNr order by OrderNr) as rn
    from test
)
select t1.CustNr, t1.OrderNr, t1.Date, t1.Price, t1.Curry,
       t2.CustNr, t2.OrderNr, t2.Date, t2.Price, t2.Curry
  from cte t1
  left join cte t2
    on t2.OrderNr = t1.OrderNr
   and t2.rn = 2
 where t1.rn = 1

在上面的查询中,哪些行显示在左侧与右侧完全是任意的。如果要定义哪一行去哪里,可以通过调整row_number窗口函数中的order by子句来实现。

需要以相同的顺序对行进行编号

with tn as (
    select *, rn=row_number() over(partition by OrderNr order by Price)
    from table
)
select t1.*, t2.*
from tn t1
left join tn t2 on t2.OrderNr = t1.OrderNr and t2.rn=2
where t1.rn=1

你也可以试试这个:

DECLARE @tab TABLE (
  CustNr int,
  OrderNr int,
  Date int,
  Price varchar(20),
  Curry char(3)
);
INSERT INTO @tab
  VALUES (1, 555, 030316, '2,4', 'EUR'),
  (1, 666, 030316, '2,5', 'EUR'),
  (1, 777, 030316, '2,3', 'EUR'),
  (1, 777, 030316, '1,9', 'USD'),
  (1, 888, 030316, '2,3', 'EUR'),
  (1, 888, 030316, '2,4', 'EUR');

SELECT
  T1.custNr,
  T1.OrderNr,
  T1.date,
  T1.price,
  T1.curry,
  T2.custNr,
  T2.OrderNr,
  T2.date,
  T2.price,
  T2.curry
FROM (SELECT
  T1.custNr,
  T1.OrderNr,
  T1.date,
  T1.price,
  T1.curry,
  ROW_NUMBER() OVER (PARTITION BY T1.custNr,
  T1.OrderNr ORDER BY T1.custNr,
  T1.OrderNr) AS [rank1]
FROM @tab T1) T1
LEFT JOIN (SELECT
  (custNr) AS custNr,
  OrderNr,
  (date) AS date,
  (price) AS price,
  (curry) AS curry,
  ROW_NUMBER() OVER (PARTITION BY custNr,
  OrderNr ORDER BY custNr,
  OrderNr) AS [rank]
FROM @tab T2) T2
  ON T1.OrderNr = T2.OrderNr
  AND T2.rank > 1
WHERE T1.rank1 <> 2
ORDER BY T1.OrderNr;

如果你有三个或四个记录,你会想要什么结果?在这种情况下,我有三个或四个记录不可能存在,是什么让一行显示在左边而不是右边?是否基于货币、价格或其他标准?当您有副本时,是否总是欧元对美元副本?我认为您忽略了重要的细节。CustNr OrderNr会重复两次以上吗?@sstan哪个向左或向右或什么货币都不相关,如果有重复订单号的记录,则应在一行中包含两行。我认为这将适用于所给出的确切示例,但如果货币发生变化,则不会发生变化。但也可能存在记录重复,货币完全不同,例如瑞士法郎、人民币等。但您有两种或更多不同的货币?你可以有多行不同的货币?@mance在这种情况下,更多的货币,你是说你想要更多的列吗?一行或多行组合,以及如何选择主/第一货币。我错过了欧洲杯,但是的,那应该是开着的。。如果你只用两个咖喱。。用T1解决cab问题。咖喱!=t2.curry..这看起来不错,但是如果重复记录中的货币相同,我在第2列中只得到空值,我已经调整了描述中的输出,我希望现在它是清楚的。啊,明白了。然后@Serg解决了这个问题。这解决了我的问题。非常感谢,我已经将“按价格排序”部分更改为“按订单编号”,对我来说,这与行的显示方式无关