0

との間にある時間の数だけ各行をコピーする必要がStartTimeありEndTimeます。

データ例:

SQLFIDDLEExample

TimeKey HourKey SensorKey   IdleTimeMinute  StartTime   EndTime
20121017    8   45  110 2012.10.17 08:31    2012.10.17 10:21
20121017    10  45  25  2012.10.17 10:26    2012.10.17 10:51
20121017    12  45  5   2012.10.17 12:21    2012.10.17 12:26
20121017    12  45  60  2012.10.17 12:41    2012.10.17 13:41
20121017    13  45  55  2012.10.17 13:51    2012.10.17 14:46
20121017    15  45  5   2012.10.17 15:11    2012.10.17 15:16
20121017    15  45  35  2012.10.17 15:46    2012.10.17 16:21
20121017    18  45  5   2012.10.17 18:51    2012.10.17 18:56

説明

たとえば、最初の行は8、9、および10時間にまたがっています。3つの出力行のそれぞれで、IdleTimeMinuteその時間内の分の期間である必要があります。

期待される結果:

TimeKey HourKey SensorKey   IdleTimeMinute  StartTime   EndTime
20121017    8   45  29  2012.10.17 08:31    2012.10.17 10:21
20121017    9   45  60  2012.10.17 08:31    2012.10.17 10:21
20121017    10  45  21  2012.10.17 08:31    2012.10.17 10:21
20121017    10  45  25  2012.10.17 10:26    2012.10.17 10:51
20121017    12  45  5   2012.10.17 12:21    2012.10.17 12:26
20121017    12  45  19  2012.10.17 12:41    2012.10.17 13:41
20121017    13  45  41  2012.10.17 12:41    2012.10.17 13:41
20121017    13  45  9   2012.10.17 13:51    2012.10.17 14:46
20121017    14  45  46  2012.10.17 13:51    2012.10.17 14:46
20121017    15  45  5   2012.10.17 15:11    2012.10.17 15:16
20121017    15  45  14  2012.10.17 15:46    2012.10.17 16:21
20121017    16  45  21  2012.10.17 15:46    2012.10.17 16:21
20121017    18  45  5   2012.10.17 18:51    2012.10.17 18:56

小さな例

最初の2行からの小さな例:

TimeKey HourKey SensorKey   IdleTimeMinute  StartTime   EndTime
20121017    8   45  110 2012.10.17 08:31    2012.10.17 10:21
20121017    10  45  25  2012.10.17 10:26    2012.10.17 10:51

最初の行には時間があります8:31 - 10:21ので、8時間29分、9時間60分、10時間21分です。

期待される小さな結果:

TimeKey HourKey SensorKey   IdleTimeMinute  StartTime   EndTime
20121017    8   45  29  2012.10.17 08:31    2012.10.17 10:21
20121017    9   45  60  2012.10.17 08:31    2012.10.17 10:21
20121017    10  45  21  2012.10.17 08:31    2012.10.17 10:21
20121017    10  45  25  2012.10.17 10:26    2012.10.17 10:51
4

4 に答える 4

0

SQLFiddle

WITH    q(n) AS
        (
        SELECT  0
        UNION ALL
        SELECT  n + 1
        FROM    q
        WHERE   n <23
        )
select TimeKey,
       q.n as HourKey,
       SensorKey,
       (select min(V) from 
         (select ETime-q.n*60 as V
          union all
          select ((q.n+1)*60)-sTime as V
          union all 
          select 60 as V          
         )  x
       ) as IdleTimeMinute,
       StartTime,
       EndTime
from q 
join 
(
select *,
DATEPART(HOUR, starttime)*60
   +DATEPART(MINUTE, starttime) sTime,
DATEPART(HOUR, Endtime)*60
   +DATEPART(MINUTE, Endtime) eTime
from 
table1 
) t1
on q.n*60 between (t1.sTime/60)*60 and t1.eTime
order by TimeKEy,SensorKey,HourKey,StartTime
于 2013-01-31T05:43:34.733 に答える
0

これは少し混乱していますが、SQLフィドルに基づいて実行できます

CREATE TABLE #Temp (RowNumber INT Identity(1,1),[TimeKey] int, [HourKey] int, 

[SensorKey] int, [IdleTimeMinute] int, [StartTime] datetime, [EndTime] datetime)

INSERT INTO #Temp
SELECT *
FROM Table1

DECLARE @i INT = 1
DECLARE @StartTime DATETIME, @EndTime DATETIME
DECLARE @Total INT = (SELECT COUNT(*) FROM #Temp)
DECLARE @x INT = 1
DECLARE @TotalHours INT = 0
WHILE @i <= @Total + 1
BEGIN

SET @StartTime = (SELECT StartTime FROM #temp WHERE RowNumber = @i)
SET @EndTime = (SELECT EndTime FROM #temp WHERE RowNumber = @i)               
SET @x = 1
SET @TotalHours = (SELECT DATEDIFF(Hour,@StartTime,@EndTime))

WHILE @x <= @TotalHours
BEGIN
INSERT INTO Table2 SELECT * FROM #Temp WHERE RowNumber = @i
SET @x = @x + 1
END
SET @i = @i + 1
END

SELECT * FROM Table2

これは、このレイアウトの 2 番目のテーブルがあることを前提としています

CREATE TABLE Table2
    (RowNumber INT, [TimeKey] int, [HourKey] int, [SensorKey] int, [IdleTimeMinute] int, [StartTime] datetime, [EndTime] datetime)
;
于 2013-01-30T13:37:33.527 に答える
0

どうぞ。これにより、時間帯が午前 0 時を過ぎたり、数日を超える場合にも対応できます。それは非常にうまく機能するはずです。

SqlFiddle を参照してください。

DECLARE @MaxHour int = IsNull((SELECT Max(DateDiff(hour, StartTime, EndTime)) + 1 FROM dbo.Table1), 0);

WITH L0 AS (SELECT 1 N UNION ALL SELECT 1),
L1 AS (SELECT 1 N FROM L0, L0 B),
L2 AS (SELECT 1 N FROM L1, L1 B),
L3 AS (SELECT 1 N FROM L2, L2 B),
L4 AS (SELECT 1 N FROM L3, L3 B),
L5 AS (SELECT 1 N FROM L4, L4 B),
Nums AS (SELECT Num = Row_Number() OVER (ORDER BY (SELECT 1)) FROM L5)
SELECT
   TimeKey = Convert(int, Convert(char(8), S.HourStartTime, 112)),
   HourKey = DatePart(hour, S.HourStartTime),
   T.SensorKey,
   IdleTimeMinute = DateDiff(minute, S.HourStartTime, E.HourEndTime),
   T.StartTime,
   T.EndTime,
   S.HourStartTime,
   E.HourEndTime
FROM
   dbo.Table1 T
   CROSS APPLY (
      SELECT AnchorHour = DateAdd(hour, DateDiff(hour, 0, T.StartTime) + N.Num - 1, 0)
      FROM Nums N
      WHERE
         DateDiff(hour, T.StartTime, T.EndTime) + 1 >= N.Num
         AND N.Num <= @MaxHour
   ) D
   CROSS APPLY (
      SELECT HourStartTime = Max(StartTime)
      FROM (VALUES (D.AnchorHour), (T.StartTime)) S (StartTime)
   ) S
   CROSS APPLY (
      SELECT HourEndTime = Min(EndTime)
      FROM (VALUES (DateAdd(hour, 1, D.AnchorHour)), (T.EndTime)) E (EndTime)
   ) E
ORDER BY
   TimeKey,
   StartTime,
   HourKey;

選択した時間の新しいタイムスパンを含めました。そのタイムスパンを次の時間では:59なく で終了させたい場合は、3 番目の節で を変更して末尾に追加します。:00CROSS APPLYDateAdd(hour, 1, D.AnchorHour)DateAdd(minute, 59, D.AnchorHour)+ 1DateDiff(minute, S.HourStartTime, E.HourEndTime)SELECT

私の意見では:

  • CTE を使用して、最大の差まで自分の道を段階的に追加することは最適ではありません。私が使用する CTE は、最大数に達するとすぐに保釈され、4294967296 まで上がる可能性があります。
  • 新しい TimeKey を計算しないソリューションは、真夜中を超えることができないという明言されていない仮定に依存しているため、脆弱です。
  • ギャップのない単調に増加する ID を持つようにテーブルを変更することに依存するソリューションは、実際のデータに適合する可能性は低いです。

注: @MaxHour 変数を宣言する理由は、使用しているオンザフライ数値テーブル CTE が定数を必要とするためです。まあ、それは正確ではありませんが、要するに、定数がなければ、高速なクエリを取得するために必要な場所で行を制限しない実行計画を選択できるということです。私はこれを計算することを選択DateDiffしましたが、実際には、IdleTimeMinute にインデックスがあれば、これはおそらくより高速であり、間違いなく高速になることがわかりました。

DECLARE @MaxHour int = IsNull((SELECT (Max(IdleTimeMinute) + 118) / 60 FROM dbo.Table1), 0);

2 つの異なる時間にまたがる最小の時間範囲は 2 分 (11:59 から 12:00 など) であるため、少なくとも 2 時間を確保するには 118 分を追加する必要があります。

于 2013-01-31T06:43:20.087 に答える
0

これを試すことができます。シーケンスを生成するための制限。IdleTimeMinute予想外の素晴らしい場合は、CTE から使用する必要がありますOPTION (MAXRECURSION n)。クエリは SQL Server 2005 以降から実行できます。古いバージョンでは、独自のシーケンス生成メカニズムを使用する必要があります。

;WITH Times
AS
(
  SELECT 1 Id
  UNION ALL
  SELECT Id + 1 
  FROM Times
  WHERE Id < 100
)
SELECT
  R.* ,
  CASE WHEN (IDLETIMEMINUTE - 60 * (T.Id - 1)) / 60 > 0 
      THEN 60
      ELSE (IDLETIMEMINUTE % 60)
   END IDLETIMEMINUTE_New
FROM Table1 R
  JOIN Times T
     ON T.Id <= CEILING(R.[IdleTimeMinute]/60.0)

SQL フィドルのデモ

于 2013-01-30T14:02:44.100 に答える