6

毎秒作成されるレコードを含む大きなテーブルがあり、過去 2 か月間、毎正時に作成されたレコードのみを選択したいと考えています。したがって、過去 60 日間、毎日 24 の選択されたレコードを取得します。

テーブル構造は、Dateandtime、Value1、Value2 などです。

どうもありがとう

4

6 に答える 6

3

group by日付部分 ( cast(col1 as date)) と時間部分( ) を使用できdatepart(hh, col1)ます。次に、各時間の最小日付を選択し、それをフィルター処理します。

select  *
from    YourTable yt
join    (
        select  min(dateandtime) as dt
        from    YourTable
        where   datediff(day, dateandtime, getdate()) <= 60
        group by
                cast(dateandtime as date)
        ,       datepart(hh, dateandtime)
        ) filter
on      filter.dt = yt.dateandtime

または、日付と時間のみを含む日付形式でグループ化することもできます。たとえば、 をconvert(varchar(13), getdate(), 120)返します2013-05-11 18

        ...
        group by
                convert(varchar(13), getdate(), 120)
        ) filter
        ...
于 2013-05-11T16:28:18.773 に答える
2

わかりやすくするために、おそらく2段階のCTEベースのアプローチを使用します(これはSQL Server 2005以降で機能します-使用しているSQL Serverのバージョンを明確に指定していませんでした。 2000 年のような古いバージョンではありません):

-- define a "base" CTE to get the hour component of your "DateAndTime" 
-- column and make it accessible under its own name
;WITH BaseCTE AS
(
    SELECT  
        ID, DateAndTime,
        Value1, Value2, 
        HourPart = DATEPART(HOUR, DateAndTime)
    FROM dbo.YourTable
    WHERE DateAndTime >= @SomeThresholdDateHere
), 
-- define a second CTE which "partitions" the data by this "HourPart",
-- and number all rows for each partition starting at 1. So each "last"
-- event for each hour is the one with the RN = 1 value
HourlyCTE AS 
(
    SELECT ID, DateAndTime, Value1, Value2, 
        RN = ROW_NUMBER() OVER(PARTITION BY HourPart ORDER BY DateAndTime DESC)
    FROM BaseCTE
)
SELECT *
FROM HourlyCTE
WHERE RN=1

また、「時間の先頭」とは正確には何を意味するのかわかりませんでした-各時間の開始時に作成された行(たとえば、04:00:00)-または、その時間の期間に作成された最後の行ですか?各時間の最初のものを意味する場合は、に変更する必要がありORDER BY DateAndTime DESCますORDER BY DateAndTime ASC

于 2013-05-11T16:37:54.517 に答える
2

EXISTS 演算子でオプションを使用できます

SELECT *
FROM dbo.tableName t 
WHERE t.DateAndTime >= @YourDateCondition
  AND EXISTS (
              SELECT 1
              FROM dbo.tableName t2
              WHERE t2.Dateandtime >= DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime), 0)
                      AND t2.Dateandtime < DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime)+1, 0)
              HAVING MAX(t2.Dateandtime) = t.Dateandtime
              )

OR オプションと CROSS APPLY演算子

SELECT *
FROM dbo.test83 t CROSS APPLY (
                               SELECT 1
                               FROM dbo.test83 t2
                               WHERE t2.Dateandtime >= DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime), 0)
                                     AND t2.Dateandtime < DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime)+1, 0)
                               HAVING  MAX(t2.Dateandtime) = t.Dateandtime                            
                               ) o(IsMatch)
WHERE t.DateAndTime >= @YourDateCondition 

パフォーマンスを改善するには、次のインデックスを使用します。

CREATE INDEX x ON dbo.test83(DateAndTime) INCLUDE(Value1, Value2)
于 2013-05-11T21:42:33.860 に答える
1

これにはウィンドウ関数を使用できます。

select dateandtime, val1, val2, . . .
from (select t.*,
             row_number() over (partition by cast(dateandtime as date), hour(dateandtime)
                                order by dateandtime
                               ) as seqnum
      from t
     ) t
where seqnum = 1

この関数は、句で定義された各グループ (この場合は毎日の各時間) にrow_number()連続番号を割り当てます。partitionこのグループ内では、dateandtime値によって順序付けられるため、時間の先頭に最も近いものが 1 の値を取得します。外側のクエリは、グループごとにこの 1 つのレコードを選択するだけです。

過去 60 日間のレコードを取得するには、追加のフィルター句が必要になる場合があります。サブクエリでこれを使用します。

where dateandtime >= getdate() - 60
于 2013-05-11T16:32:13.720 に答える
0

試す:

select * from mytable
where datepart(mi, dateandtime)=0 and 
      datepart(ss, dateandtime)=0 and
      datediff(d, dateandtime, getdate()) <=60
于 2013-05-11T16:34:06.720 に答える