所以,我有这个SQL表:
Traveller checkin dateTime
5566 Madrid 2017-01-01 01:00:00.00
5566 Barcelona 2017-01-02 03:00:00.00
5566 Berlin 2017-01-03 02:00:00.00
5566 Paris 2017-01-06 05:00:00.00
5566 London 2017-01-07 06:00:00.00
5566 Madrid 2017-01-08 02:00:00.00
4422 Moscow 2017-01-03 08:00:00.00
4422 Madrid 2017-01-04 07:00:00.00
4422 Barcelona 2017-01-05 03:00:00.00
8833 Barcelona 2017-02-01 08:00:00.00
8833 Berlin 2017-02-02 04:00:00.00
8833 London 2017-02-03 01:00:00.00
8833 Berlin 2017-02-03 22:00:00.00
9966 Paris 2017-02-03 04:00:00.00
9966 London 2017-02-04 06:00:00.00
9966 Berlin 2017-02-05 01:00:00.00
... ... ...
是否有可能以某种方式将这些命令分配到一个从一个表到另一个表,使用除了第一个签到之外的所有来自目的地。像这样:
Traveller From To
5566 Madrid Barcelona
5566 Barcelona Berlin
5566 Berlin Paris
5566 Paris London
5566 London Madrid
4422 Moscow Madrid
4422 Madrid Barcelona
8833 Barcelona Berlin
8833 Berlin London
8833 London Berlin
... ... ...
我知道SQL的基础知识,但我还在学习,所以如果有人能够想到一种方法可以做到(或不做),请帮助我理解它是如何工作的。
非常感谢!
答案 0 :(得分:2)
您可以使用ROW_NUMBER()
为CTE中每位旅行者的签到分配序号,然后将CTE加入自身以创建结果:
declare @t table (Traveller int not null, checkin varchar(19) not null,
TimeStamp datetime2 not null)
insert into @t (Traveller,checkin,TimeStamp) values
(5566,'Madrid', '2017-06-02T07:56:01'),
(5566,'Barcelona','2017-06-02T07:56:02'),
(5566,'Berlin', '2017-06-02T07:56:03'),
(5566,'Paris', '2017-06-02T07:56:04'),
(5566,'London', '2017-06-02T07:56:05'),
(5566,'Madrid', '2017-06-02T07:56:06'),
(4422,'Moscow', '2017-06-02T07:56:07'),
(4422,'Madrid', '2017-06-02T07:56:08'),
(4422,'Barcelona','2017-06-02T07:56:09'),
(8833,'Barcelona','2017-06-02T07:56:10'),
(8833,'Berlin', '2017-06-02T07:56:11'),
(8833,'London', '2017-06-02T07:56:12'),
(8833,'Berlin', '2017-06-02T07:56:13'),
(9966,'Paris', '2017-06-02T07:56:14'),
(9966,'London', '2017-06-02T07:56:15'),
(9966,'Berlin', '2017-06-02T07:56:16')
;With Numbered as (
select
*,
ROW_NUMBER() OVER (PARTITION BY Traveller ORDER by TimeStamp) as rn
from @t
)
select
n1.Traveller,n1.checkin,n2.checkin
from
Numbered n1
inner join
Numbered n2
on
n1.Traveller = n2.Traveller and
n1.rn = n2.rn - 1
order by
n1.Traveller,n1.rn
结果:
Traveller checkin checkin
----------- ------------------- -------------------
4422 Moscow Madrid
4422 Madrid Barcelona
5566 Madrid Barcelona
5566 Barcelona Berlin
5566 Berlin Paris
5566 Paris London
5566 London Madrid
8833 Barcelona Berlin
8833 Berlin London
8833 London Berlin
9966 Paris London
9966 London Berlin
答案 1 :(得分:0)
您可以使用row_number
窗口功能。它是Sql Server 2008处理此问题的方法。这是:
;with raw_data (id, city, arrival) as (
select 5566, 'Madrid', '2017-01-01 01:00:00.00' union all
select 5566, 'Barcelona', '2017-01-02 03:00:00.00' union all
select 5566, 'Berlin', '2017-01-03 02:00:00.00' union all
select 5566, 'Paris', '2017-01-06 05:00:00.00' union all
select 5566, 'London', '2017-01-07 06:00:00.00' union all
select 5566, 'Madrid', '2017-01-08 02:00:00.00' union all
select 4422, 'Moscow', '2017-01-03 08:00:00.00' union all
select 4422, 'Madrid', '2017-01-04 07:00:00.00' union all
select 4422, 'Barcelona', '2017-01-05 03:00:00.00' union all
select 8833, 'Barcelona', '2017-02-01 08:00:00.00' union all
select 8833, 'Berlin', '2017-02-02 04:00:00.00' union all
select 8833, 'London', '2017-02-03 01:00:00.00' union all
select 8833, 'Berlin', '2017-02-03 22:00:00.00' union all
select 9966, 'Paris', '2017-02-03 04:00:00.00' union all
select 9966, 'London', '2017-02-04 06:00:00.00' union all
select 9966, 'Berlin', '2017-02-05 01:00:00.00'
)
, arrivals as (
select
id, city, arrival,
row_number() over (partition by id order by arrival) as rn
from raw_data
)
, flies as (
select
fr.id,
fr.city as [from],
fr.arrival as [departure],
[to].city as [to],
[to].arrival as [arrival]
from arrivals fr
join arrivals [to] on
fr.id = [to].id
and [to].rn = fr.rn + 1
)
select
*
from flies
SQL Server 2012及更高版本
但是如果你有Sql Server 2012及更高版本,你可以使用lag
函数来解决它,它可以访问当前的某些前一行。
E.g。 lag(colX, N, <default>)
表示您获得列colX的第N个值或值(如果没有)。这只是我们需要的!严格地说是前一个:
;with raw_data (id, city, arrival) as (
-- omitted for the sake of shortness :)
)
, flies as (
select
id,
-- here it is!!! prev city and arrival
lag(city, 1, null) over (partition by id order by arrival) as [from],
lag(arrival, 1, null) over (partition by id order by arrival) as [departure],
city as [to],
arrival as [arrival]
from raw_data
)
select
*
from flies
where
-- and here we take only rows from where we're 'departured'
[from] is not null
答案 2 :(得分:0)
您可以使用LEAD function返回下一行的值,例如
export default class React.Component {
constructor(props) {
super(props);
}
renderNames() {
let empty = ``
let names = this.props.names;
let namesLength = names.length;
for (var i = 0; i < namesLength; i++) {
empty = empty + `-` + ` ${names[i]}`
}
return empty;
}
render() {
return(
<div>
{this.renderNames()}
</div>
)
}
}
这将返回最后一段的NULL目的地。要删除它,您可以使用CTE过滤数据:
select
Traveller,
checkin,
LEAD(checkin,1) OVER(PARTITION by traveller order by timestamp) as destination
from @t t
测试所有这些:
with checkins as (
select
Traveller,
checkin,LEAD(checkin,1) OVER(PARTITION by traveller order by timestamp) as destination
from @t t)
select * from checkins
where destination is not null
将返回:
declare @t table (Traveller int not null, checkin varchar(19) not null, TimeStamp datetime2 not null);
insert into @t (Traveller,checkin,TimeStamp) values
(5566,'Madrid', '2017-06-02T07:56:01'),
(5566,'Barcelona','2017-06-02T07:56:02'),
(5566,'Berlin', '2017-06-02T07:56:03'),
(5566,'Paris', '2017-06-02T07:56:04'),
(5566,'London', '2017-06-02T07:56:05'),
(5566,'Madrid', '2017-06-02T07:56:06'),
(4422,'Moscow', '2017-06-02T07:56:07'),
(4422,'Madrid', '2017-06-02T07:56:08'),
(4422,'Barcelona','2017-06-02T07:56:09'),
(8833,'Barcelona','2017-06-02T07:56:10'),
(8833,'Berlin', '2017-06-02T07:56:11'),
(8833,'London', '2017-06-02T07:56:12'),
(8833,'Berlin', '2017-06-02T07:56:13'),
(9966,'Paris', '2017-06-02T07:56:14'),
(9966,'London', '2017-06-02T07:56:15'),
(9966,'Berlin', '2017-06-02T07:56:16');
with checkins as (
select
Traveller,
checkin,LEAD(checkin,1) OVER(PARTITION by traveller order by timestamp) as destination
from @t t)
select * from checkins
where destination is not null