2

DateTime値を保持するScheduledTime列を持つこのテーブルがあります。これらは3時間のテストの開始時間です。列は次のようになります。

SELECT ScheduledTime from Schedule;

2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-16 16:34:36.000
2012-03-20 09:14:48.000
2012-03-20 13:14:48.000
2012-03-20 17:14:48.000
2012-03-20 21:14:48.000
2012-04-14 17:13:19.000
2012-04-14 21:13:19.000
2012-04-15 01:13:19.000
2012-04-15 05:13:19.000
2012-04-15 09:13:19.000
2012-04-15 13:13:19.000
2012-04-15 17:13:19.000
2012-04-15 21:13:19.000
2012-04-16 01:13:19.000
2012-04-16 05:13:19.000
2012-04-16 13:13:19.000
2012-04-16 17:13:19.000
2012-04-17 01:13:19.000
2012-04-17 05:13:19.000
2012-04-17 13:13:19.000
2012-04-18 18:29:16.000
2012-04-19 15:48:12.000
2012-04-19 19:10:00.000
2012-04-19 23:47:00.000
2012-04-20 10:27:28.000
2012-04-20 17:27:00.000

上記の日時の値は、3時間のテストの開始時刻です。したがって、3時間のテストで次に利用可能なスロットを取得する必要があります。既存のテストまたはcurrentTime+1hr内に収容できる場合が最適です。

タスクは、ScheduledTime列から取得された3時間スロットの開始時間を保持する列(たとえばSlotsColumn)を生成することであり、SlotsColumn値は> {fn Now()}、つまりCurrentTimeです。

オプションとして、そのような値がない場合は、CurrentTime+1hrを指定する必要があります。

SQLServer2008の使用。

I have tried this:  
WITH rows AS 
        (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY [ScheduledTime] ) AS rn 
        FROM    [dbo].[Schedule]  
        WHERE [ScheduledTime] IS NOT NULL               
        ) 
SELECT  TOP(1)
DATEADD(second,10800, mc.ScheduledTime) AS NextTime 
FROM    rows mc 
JOIN    rows mp   
ON      mc.rn = mp.rn - 1   
WHERE (DATEDIFF(SECOND, mc.ScheduledTime, mp.ScheduledTime) - 10800) >= 10800 
order by mc.ScheduledTime DESC

クエリは、存在する場合にのみ、将来の1つの有効な開始時刻のリストを返します。

上記のサンプルデータに対して、「2012-04-20 03:47:00.000」が返されます。これは、「2012-04-20 17:27:00.000」に別のテストがあるとは見なされないため、間違っています。それらは重なってはいけません。必要な出力は次のとおりです。「2012-04-2012:27:00.000」のように、「2012-04-20 10:27:28.000」でのテスト後、「2012-04-2017」でのテスト前です。 27:00.000'なので、3時間のテストに最適なスロットです。私にとってのCurrentTimeは「2012-04-2011:45:23.393」です。

そのような有効な時間が存在しない場合、CurrentTime + 1hrが返されるようにするにはどうすればよいですか?

これはC#で実行できますが、SQLクエリを試してみてください。

ヘルプ/ヒントをお願いします。

4

2 に答える 2

1
DECLARE @now DATETIME2 = '2012-04-20 11:45:23.393'
DECLARE @schedule TABLE
        (
        ScheduledTime DATETIME2 NOT NULL
        )

INSERT
INTO    @schedule
VALUES 
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-16 16:34:36.000'),
('2012-03-20 09:14:48.000'),
('2012-03-20 13:14:48.000'),
('2012-03-20 17:14:48.000'),
('2012-03-20 21:14:48.000'),
('2012-04-14 17:13:19.000'),
('2012-04-14 21:13:19.000'),
('2012-04-15 01:13:19.000'),
('2012-04-15 05:13:19.000'),
('2012-04-15 09:13:19.000'),
('2012-04-15 13:13:19.000'),
('2012-04-15 17:13:19.000'),
('2012-04-15 21:13:19.000'),
('2012-04-16 01:13:19.000'),
('2012-04-16 05:13:19.000'),
('2012-04-16 13:13:19.000'),
('2012-04-16 17:13:19.000'),
('2012-04-17 01:13:19.000'),
('2012-04-17 05:13:19.000'),
('2012-04-17 13:13:19.000'),
('2012-04-18 18:29:16.000'),
('2012-04-19 15:48:12.000'),
('2012-04-19 19:10:00.000'),
('2012-04-19 23:47:00.000'),
('2012-04-20 10:27:28.000'),
('2012-04-20 17:27:00.000')

SELECT  COALESCE
        (
        (
        SELECT  TOP 1
                DATEADD(hour, 3, scheduledTime)
        FROM    @schedule s
        WHERE   s.scheduledTime >= DATEADD(hour, -3, @now)
                AND NOT EXISTS
                (
                SELECT  NULL
                FROM    @schedule sn
                WHERE   sn.scheduledTime > s.scheduledTime
                        AND sn.scheduledTime < DATEADD(hour, 6, s.scheduledTime)
                )

        ORDER BY
                scheduledTime
        ),
        DATEADD(hour, 1, @now)

-- This is redundant

        )
于 2012-04-20T11:15:50.027 に答える
0

最終的に機能し、目的の結果を達成したクエリは次のとおりです。

    WITH rows AS 
                (
                SELECT  *, ROW_NUMBER() OVER (ORDER BY [ScheduledTime] ) AS rn 
                FROM    Schedule
                WHERE [ScheduledTime] IS NOT NULL                     
                ) 
    SELECT  COALESCE 
            ( 
            (
            SELECT  Top 1
            DateAdd(SECOND,-10800,mp.ScheduledTime) AS NewNextTime
            FROM    rows mc 
            JOIN    rows mp   
            ON      mc.rn = mp.rn - 1   
            WHERE (DATEDIFF(SECOND, mc.ScheduledTime, mp.ScheduledTime) - 10800) >= 10800 
            And mp.ScheduledTime >= GETDATE()
            And DateAdd(SECOND,-10800,mp.ScheduledTime)>= GETDATE()
            order by mc.ScheduledTime
            ),
            ( 
            SELECT  TOP 1 
                    DATEADD(hour, 3, scheduledTime) AS NewNextTime 
            FROM    Schedule s 
            WHERE   s.scheduledTime >= DATEADD(hour, -3, GetDate()) 
                    AND NOT EXISTS 
                    ( 
                    SELECT  NULL 
                    FROM    Schedule sn 
                    WHERE   sn.scheduledTime > s.scheduledTime 
                            AND sn.scheduledTime < DATEADD(hour, 6, s.scheduledTime) 
                    ) 

            ORDER BY 
                    scheduledTime 
            ),
           (
                SELECT  TOP 1 
                DATEADD(SECOND, (3600), GetDate()) AS NewNextTime 
            )  
            )

これは、有効な時間、または最悪の場合、最後のテストの終了後の時間を返します。

SELECT COALESCE の最初の部分は、既存のスロット内からタイム スロットを返します。SELECT COALESCE の 2 番目の部分は、すべてのテスト スロットの最後のタイム スロットを返します。SELECT COALESCE の 3 番目の部分は、CurrentTime+1hr として返されます。

これについての皆さんの議論は、これに到達するのに非常に役立ちました。私はまだこれを使用するので、より良い提案を探します。

PSこのソリューションの投稿が遅れて申し訳ありません。

于 2012-04-23T08:43:41.973 に答える