2

この表が下にある場合

   id         time
   start      08.00 AM 
   stop       09.00 AM
   stop       09.30 AM
   start      09.30 AM
   start      11.00 AM
   start      11.30 AM
   stop       11.40 AM
   stop       12.00 PM

すべての最初の開始停止後のすべての開始、および最後の停止のみを取る出力が必要です

解決策はありますか?

これは私が望む出力です:

   id         time
   start      08.00 AM 
   stop       09.00 AM
   start      09.30 AM
   stop       11.40 AM
   stop       12.00 PM
4

4 に答える 4

4

行ごとに主キーまたはいくつかの異なるIDを持たない...私の頭に浮かぶ唯一の解決策は次のようなものです:

select rn, id , time
from
(select ROW_NUMBER() over (order by time) as rn, id, time from test 
where id = 'start'
union
select ROW_NUMBER() over (order by time) as rn, id, time from test 
where id = 'stop'
) d
order by rn

基本的に、次のように、開始された行と停止された行の間の結合を作成しました。

 (select ROW_NUMBER() over (order by time) as rn, id, time from test 
    where id = 'start'
    union
    select ROW_NUMBER() over (order by time) as rn, id, time from test 
    where id = 'stop'
    ) d

戻り値:

    1   start   08.00
    2   start   11.00
    3   start   12.00
    4   start   13.00
    1   stop    09.00
    2   stop    10.00
    3   stop    14.00
    4   stop    15.00

元の入力から:

id          time
start   08.00
stop    09.00
stop    10.00
start   11.00
start   12.00
start   13.00
stop    14.00
stop    15.00

これで、それらを独自の行番号で並べ替えるだけで済みます...それがrnです。

最後に、次のようになります。

1   start   08.00
1   stop    09.00
2   start   11.00
2   stop    10.00
3   start   12.00
3   stop    14.00
4   start   13.00
4   stop    15.00

@注:私の例の値はあなたのものに近いです...しかし架空のものです...

于 2013-01-29T08:13:40.383 に答える
2
 ;WITH cte AS
 (
  SELECT id AS pr, [time], ROW_NUMBER() OVER(ORDER BY [time]) AS Id,
         COUNT(*) OVER() AS cnt        
  FROM dbo.test21 t1
  ), cte2 AS
 (
  SELECT Id, pr, [time], pr AS prStart, [time] AS StopTime, pr AS prStop, [time] AS StartTime
  FROM cte
  WHERE Id = 1
  UNION ALL
  SELECT c1.Id, 
         CASE WHEN c1.pr != c2.pr OR c1.Id = c1.cnt THEN c1.pr ELSE c2.pr END,
         CASE WHEN c1.pr != c2.pr OR c1.Id = c1.cnt THEN c1.[time] ELSE c2.[time] END,
         c1.pr, c1.[time], c2.pr, c2.[time]
  FROM cte c1 JOIN cte2 c2 ON c1.Id = c2.Id + 1
  )
  SELECT pr, [time], MIN(StartTime) AS StartTime,
         MAX(DATEDIFF(minute, StartTime, [time])) AS Interval
  FROM cte2
  GROUP BY pr, [time]

SQLFiddle のデモ

于 2013-01-29T08:58:41.897 に答える
2

結果を別の形式で提供する代替手段があります。ただし、要求された情報は返されます。

SELECT
  MIN([main].[Start]) AS [Start],
  [main].[End] AS [Stop],
  DATEDIFF(minute, MIN([main].[Start]), [main].[End]) AS [Minutes]
FROM
(
  SELECT
    [sub].[Start],
    MIN([sub].[End]) AS [End]
  FROM
  (
    SELECT
      [start].[time] AS [Start],
      [start].[id] AS [StartingStatus],
      [end].[time] AS [End],
      [end].[id] AS [EndingStatus]
    FROM [Log] [start],  [Log] [end]
    WHERE [start].[id] = 'start' 
      AND [start].[time] < [end].[time]
      AND [start].[id] <> [end].[id]
  ) AS [sub]
  GROUP BY
    [sub].[Start],
    [sub].[StartingStatus]
) AS [main]
GROUP BY
  [main].[End]

基本的に、最初にすべてのレコードを選択しますwhere [id] = 'start'。次に、後の時刻と を持つすべてのレコードを検索しますwhere [id] <> 'start'

これらのレコードで、各「開始」ごとにグループ化し、最初の「停止」時間を決定します。次に、これらのレコードが再びグループ化され、各「停止」時間の最初の「開始」時間が検出されます。

結果は次のようになります。

+--------------------------------+--------------------------------+---------+
| START                          | STOP                           | MINUTES |
+================================+================================+=========+
| January, 29 2013 08:00:00+0000 | January, 29 2013 09:00:00+0000 | 60      |
+--------------------------------+--------------------------------+---------+
| January, 29 2013 09:30:00+0000 | January, 29 2013 11:30:00+0000 | 120     |
+--------------------------------+--------------------------------+---------+
| January, 29 2013 11:30:00+0000 | January, 29 2013 12:00:00+0000 | 30      |
+--------------------------------+--------------------------------+---------+

フィドルはここにあります

PS: この回答は、私の回答hereに基づいています。

于 2013-01-29T08:55:58.287 に答える
1

問題であることが判明しました。

これが SQL Server 2005+ であると仮定すると、次の方法を使用できます。

WITH partitioned AS (
  SELECT
    *,
    grp = ROW_NUMBER() OVER (ORDER BY time, CASE id WHEN 'stop' THEN 0 ELSE 1 END)
        - ROW_NUMBER() OVER (PARTITION BY id ORDER BY time)
  FROM atable
)
SELECT
  id,
  time = MIN(time)
FROM partitioned
GROUP BY
  id,
  grp
ORDER BY
  time
;
于 2013-01-29T09:07:35.910 に答える