時間を1時間または10分でグループ化する方法


167

私がするときのように

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date]

グループ期間を指定するにはどうすればよいですか?

MS SQL 2008

2回目の編集

私はしようとしています

SELECT MIN([Date]) AS RecT, AVG(Value)
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY (DATEPART(MINUTE, [Date]) / 10)
  ORDER BY RecT

%10を/ 10に変更しました。ミリ秒なしで日付を出力することは可能ですか?

回答:


213

最後に

GROUP BY
DATEPART(YEAR, DT.[Date]),
DATEPART(MONTH, DT.[Date]),
DATEPART(DAY, DT.[Date]),
DATEPART(HOUR, DT.[Date]),
(DATEPART(MINUTE, DT.[Date]) / 10)

11
私が作成したROUND((DATEPART(MINUTE, DT.[Date]) / 5),0,1) * 5ので、データを見ると、最も近いタイムスロットと相関しています
hdost

7
年、月、日はに簡略化できますDATE(DT.[Date])

@Keelanは機能しません-CONVERT(date、DT。[Date])は機能します。
Dan Parsonson、2018

datepart(hour, workingPolicy.workingHours)/2.0与え1.5ながらdatepart(hour, '1900-01-01 09:00:30.000')/2.0与え4.5、私はなぜ理解していませんか?注:workingPolicy.workingHours = 1900-01-01 09:00:30.000です。助けてください
affanBajwa

65

私はパーティーに超遅れていますが、これは既存の回答のいずれにも表示されません。

GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', date_column) / 10 * 10, '2000')
  • 用語は、任意の数に変更することができ、それぞれ。10MINUTEDATEPART
  • これはDATETIME値です。つまり
    • 長い時間間隔で正常に動作します。(年の間に衝突はありません。)
    • SELECTステートメントにそれを含めると、指定したレベルで切り捨てられたかなりの出力を持つ列が出力されます。
  • '2000'SQLが日付計算を実行する「アンカー日付」です。Jereonh は、最近の日付を秒またはミリ秒でグループ化すると、以前のアンカー()で整数オーバーフローが発生することを以下発見しました0
SELECT   DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
                                                               AS [date_truncated],
         COUNT(*) AS [records_in_interval],
         AVG(aa.[value]) AS [average_value]
FROM     [friib].[dbo].[archive_analog] AS aa
GROUP BY DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
ORDER BY [date_truncated]

あなたのデータスパン世紀た場合は、 2次またはミリ秒グループ化するための単一のアンカーの日付を使用すると、まだオーバーフローが発生します。それが発生している場合は、各行にビニング比較を独自の日付の午前0時に固定するよう依頼できます。

  • 上に表示されている場所ではDATEADD(DAY, DATEDIFF(DAY, 0, aa.[date]), 0)なく、代わりに使用してください'2000'。クエリは完全に読めなくなりますが、機能します。

  • 代替CONVERT(DATETIME, CONVERT(DATE, aa.[date]))として、代替品があります。

2 32 ≈4.29E + 9、ので、あなたの場合DATEPART、IS SECOND、あなたはどちらかの側に43億秒を取得、または「アンカー±136年。」同様に、2 32ミリ秒は≈49.7日です。
あなたのデータが実際に何世紀または千年にまたがり、ある場合には、まだ二またはミリ秒...お祝いに正確な!何をしていても、続けてください。


特定の開始日からこれを行うことは可能ですか?
Pylander

1
@pylanderもちろん。のwhere前に句を置くだけgroup byです。
マイケル-クレイシャーキーはどこですか

2
そうですか。これを変更する/ 20 * 20と、20分間隔でデータを収集するのと同じになりますか?申し訳ありませんが、私は今数学に苦労しています。
1

2
SECONDをDATEPARTとして使用すると、エラーメッセージ(The datediff function resulted in an overflow. The number of dateparts separating two date/time instances is too large. Try to use datediff with a less precise datepart.)が表示されます。MINUTEは、このアプローチで使用できる最小の日付部分のようです。
jeroenh

1
@jeroenh、あなたは正しいです。それについて話すセクションを追加しました。tldr:0'2000'(引用符が重要です!)に変更して、SECOND再試行してください。
マイケル-クレイシャーキーはどこですか

17

T-SQLでは次のことができます。

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date], DATEPART(hh, [Date])

または

分単位で DATEPART(mi, [Date])

または

10分までにDATEPART(mi, [Date]) / 10(ティモシーが示唆したように)


1
GROUP BY [日付]、DATEPART(hh、[日付])は混乱ではなく、ですか?
2011

1
@nCdy大丈夫である必要があります。そうでない場合は、エラーが発生します。「集計関数またはGROUP BY句のいずれにも含まれていないため、選択リストでは無効です」
tzup

1
日付全体と同じ時間の時間でどのようにグループ化しますか?私は単にMin Dateを使用しています。
2011

Min(Date)を使用する場合、もちろん、Group Byの日付を取り出すことができます。
tzup

3
分を10で割ると、10分間隔でグループ化されます。これが必要です。Modulo 10は意味がありません。
Tar

12

10分の間隔の場合、

GROUP BY (DATEPART(MINUTE, [Date]) / 10)

tzupとPieter888ですでに述べたように...時間間隔を実行するには、

GROUP BY DATEPART(HOUR, [Date])

2
しかし、ここでは、1980年の分と2011年の分をグループ化します。
2011

%は正しい数学でしょうか?10個のグループが作成されることはありません。例:1%10 = 9 2%10 = 8これは、必ずしも正しい年代順のグループ化であるとは限りません。通常の除算だけで正しいと思います。%がSQLの剰余除算でない場合を除きます。
スティーブン

12
分を10で割ると、10分間隔でグループ化されます。これが必要です。Modulo 10は意味がありません。
Tar

タールに同意する。グループ化は意味がありません。
MikeMurko

7

のようなものでなければなりません

select timeslot, count(*)  
from 
    (
    select datepart('hh', date) timeslot
    FROM [FRIIB].[dbo].[ArchiveAnalog]  
    ) 
group by timeslot

(構文については100%確実ではありません-私はOracleのような人です)

Oracleの場合:

SELECT timeslot, COUNT(*) 
FROM
(  
    SELECT to_char(l_time, 'YYYY-MM-DD hh24') timeslot 
    FROM
    (
        SELECT l_time FROM mytab  
    )  
) GROUP BY timeslot 

6

著者の最初の答えはかなりうまくいきます。このアイデアを拡張するために、次のようなことができます

group by datediff(minute, 0, [Date])/10

これにより、60分より長いグループ、たとえば720、つまり半日などでグループ化できます。


1
上記のMySQLクエリは何ですか?
Biranchi 2016

4

MySqlの場合:

GROUP BY
DATE(`your_date_field`),
HOUR(`your_date_field`),
FLOOR( MINUTE(`your_date_field`) / 10);

1

私の解決策は、関数を使用して日付間隔を持つテーブルを作成し、このテーブルを、テーブル内の日付間隔を使用してグループ化するデータに結合することです。その後、データを表示するときに日付間隔を簡単に選択できます。

CREATE FUNCTION [dbo].[fn_MinuteIntervals]
    (
      @startDate SMALLDATETIME ,
      @endDate SMALLDATETIME ,
      @interval INT = 1
    )
RETURNS @returnDates TABLE
    (
      [date] SMALLDATETIME PRIMARY KEY NOT NULL
    )
AS
    BEGIN
        DECLARE @counter SMALLDATETIME
        SET @counter = @startDate
        WHILE @counter <= @endDate
            BEGIN
                INSERT INTO @returnDates VALUES ( @counter )
                SET @counter = DATEADD(n, @interval, @counter)
            END
        RETURN
    END

1
declare @interval tinyint
set @interval = 30
select dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0), sum(Value_Transaction)
from Transactions
group by dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0)

8
Stackoverflowへようこそ。あなたはあなたの答えを完全に説明する必要があります、そしてこれがすでにサイトにある他の10の答えに何を追加するか。
Simon.SA

0

SQL Server 2012の場合、SQL Server 2008R2で機能すると思いますが、次のアプローチを使用して、時間をミリ秒にスライスします。

DATEADD(MILLISECOND, -DATEDIFF(MILLISECOND, CAST(time AS DATE), time) % @msPerSlice, time)

これは次の方法で機能します。

  • 固定小数点とターゲット時間の間のミリ秒数を取得します。
    @ms = DATEDIFF(MILLISECOND, CAST(time AS DATE), time)
  • これらのミリ秒をタイムスライスに分割する残りの部分を取り上げます。
    @rms = @ms % @msPerSlice
  • 残りのマイナスをターゲット時間に追加して、スライス時間を取得します。
    DATEADD(MILLISECOND, -@rms, time)

残念ながら、これはマイクロ秒以下の単位でオーバーフローするため、より大きくてより細かいデータセットでは、不便な固定小数点を使用する必要があります。

私はこれを厳密にベンチマークしていませんし、ビッグデータにもないので、マイレージは異なるかもしれませんが、パフォーマンスは当社の機器やデータセットで試した他の方法よりも著しく悪くはありませんでした。私たちのために。


0
select from_unixtime( 600 * ( unix_timestamp( [Date] ) % 600 ) ) AS RecT, avg(Value)
from [FRIIB].[dbo].[ArchiveAnalog]
group by RecT
order by RecT;

2つの600を、グループ化する任意の秒数に置き換えます。

これが頻繁に必要で、テーブルが変更されない場合、Archiveという名前が示すように、日付(&時間)をunixtimeとしてテーブルに変換して保存する方がおそらく高速です。


0

私はこれでショーに遅れるのを知っていますが、私はこれを使用しました-かなりシンプルなアプローチ。これにより、丸めの問題なしに60分のスライスを取得できます。

Select 
   CONCAT( 
            Format(endtime,'yyyy-MM-dd_HH:'),  
            LEFT(Format(endtime,'mm'),1),
            '0' 
          ) as [Time-Slice]

0
select dateadd(minute, datediff(minute, 0, Date), 0),
       sum(SnapShotValue)
FROM [FRIIB].[dbo].[ArchiveAnalog]
group by dateadd(minute, datediff(minute, 0, Date), 0)

1
質問に答える際に、いくつかの説明を提供してください。
Shizzen83
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.