2016-03-24 12 views
1

私は複雑な要件に問題があります。私はこれを解決するためにいくつかの助けを得ることができると考えています。私のSQL知識は非常に基本的なものであり、この問題の解決方法はわかりません。SQLで行を1つの行に結合する方法は?

ID  | Name | Time     | Event Type 
---------------------------------------------------------- 
133000 | Elise | 2016-02-17 06:39:42.000 | Arrival 
133000 | Elise | 2016-02-18 06:20:22.000 | Arrival 
133000 | Elise | 2016-02-18 20:43:46.000 | Departure 
133020 | Elise | 2016-02-19 06:29:46.000 | Arrival 
133445 | Peter | 2016-02-01 20:09:00.000 | Departure 
133445 | Peter | 2016-02-02 06:32:02.000 | Arrival 
133445 | Peter | 2016-02-02 17:03:04.000 | Departure 
133445 | Peter | 2016-02-02 19:44:06.000 | Arrival 
133445 | Peter | 2016-02-02 19:56:56.000 | Departure 

は今、私はそれがこのように構成されているような方法で、このデータを照会する:つまり

ID  | Name | Arrival     | Departure 
---------------------------------------------------------- 
133000 | Elise | 2016-02-17 06:39:42.000 | NULL 
133000 | Elise | 2016-02-18 06:20:22.000 | 2016-02-18 20:43:46.000 
133000 | Elise | 2016-02-19 06:29:46.000 | NULL 
133445 | Peter | NULL     | 2016-02-01 20:09:00.000 
133445 | Peter | 2016-02-02 06:32:02.000 | 2016-02-02 17:03:04.000 
133445 | Peter | 2016-02-02 19:44:06.000 | 2016-02-02 19:56:56.000 

を、私が持っている現在、私は次のように構造化さEventsテーブルを持っています2つの新しい列:ArrivalDeparture次いで、テーブル内のそれぞれの人のために、時系列順に次のロジックを適用する:

  • Event TypeあるArrival場合、それはArrival列のTime値と新しい行にマッピングされなければなりません。
  • Event TypeDepartureの場合は、前の行もDepartureであるかどうかを確認してください。その場合は、Departure列のTime値を持つ新しい行にマップする必要があります。Arrivalはnullです。そうでない場合は、Timeの値を前の行のDeparture列に転送してください。

これはSQLクエリで実行できますが、機能は正常です。私はMS SQL Serverを使用しています。ありがとう!

答えて

1

あなたのデータは、必ず到着行の正確な量を持っている場合は、ゴードン・リノフのソリューションは、おそらくより良いですが、データが壊れている場合、あなたはおそらく、ROW_NUMBERでこのような何かを、より複雑なトリックを行う必要があります:

select 
    Name, 
    max(case when [Event Type] = 'Arrival' then Time end) as Arrival, 
    max(case when [Event Type] = 'Departure' then Time end) as Departure 
from (
    select case when [Event Type] = 'Departure' and lag([Event Type]) over (partition by Name order by [Time] asc) = 'Arrival' then RN -1 else RN end as RN2, * 
    from (
    select row_number() over (partition by Name order by [Time]) as RN, * 
    from yourtable 
) X 
) Y 
group by Name, RN2 
order by Name, Arrival, Departure 

これは、すべての行に行番号を割り当てます。行が出発点で、前の行が到着の場合は、行番号から1つを差し引く - >それらの行は同じ番号になります。この番号を使用してデータをグループ化するので、すべての孤立した行が別々に表示されます。

+0

私はサーバー'08にいるので、ラグの代わりに適用を使用するために少し変更しなければなりませんでした。しかし、これはまさに私が望んでいたものです。 – painiyff

1

これはさまざまな方法で実行できます。一つの方法はlead()ですが、あなたは注意する必要があります。

select id, name, time as Arrival, 
     (case when next_eventtype = 'Departure' then next_time end) as Departure 
from (select e.*, 
      lead(time) over (partition by id order by time) as next_time, 
      lead(eventtype) over (partition by id order by time) as next_eventtype, 
     from events e 
    ) e 
where eventtype = 'Arrival'; 

lead()は、SQL Serverの2012+で利用可能です。以前のバージョンでは、代わりにapplyを使用します。

関連する問題