2015-04-18 40 views
4

我想從兩個日期時間以及那些過濾行之間的單個表過濾行應該來下一個日期,例如如何過濾日期間行,而不使用循環中TSQL

我想所有的行(2015年3月16日上午6點)和(2015年3月17日上午6點)日期時間爲(2015年3月17日)日期和 (2015年3月17日上午6點)和(2015年3月18日上午6點)日期時間之間的日期等。

這是我的演示表

Id  Name LogTime 
1  mj  2015-03-16 01:28:03.257 
2  mj  2015-03-16 05:28:03.257 
3  mj  2015-03-16 06:28:03.257 
4  mj  2015-03-16 18:28:03.257 
5  mj  2015-03-17 01:28:06.677 
6  mj  2015-03-17 06:28:06.677 
7  mj  2015-03-17 16:28:07.460 
8  mj  2015-03-17 07:28:03.257 
9  mj  2015-03-18 01:28:08.193 
10  mj  2015-03-18 05:28:03.257 
11  mj  2015-03-18 06:28:03.257 
12  mj  2015-03-18 18:28:03.257 
13  mj  2015-03-19 01:28:06.677 
14  mj  2015-03-19 06:28:06.677 
15  mj  2015-03-19 16:28:07.460 
16  mj  2015-03-19 07:28:03.257 
17  mj  2015-03-20 01:28:08.193 
18  mj  2015-03-20 05:28:03.257 
19  mj  2015-03-20 06:28:03.257 
20  mj  2015-03-20 18:28:03.257 

下面是我使用的查詢。

DECLARE @i INT = 1 

DECLARE @from DATETIME 
    , @to DATETIME 

WHILE (@i <= 5) 
BEGIN 

    SET @from = CONVERT(DATETIME, CONVERT(VARCHAR(10), DATEADD(D, [email protected], '2015-03-20'), 102) + ' 6:00:00') 
    SET @to = CONVERT(DATETIME, CONVERT(VARCHAR(10), DATEADD(D, [email protected] + 1, '2015-03-20'), 102) + ' 6:00:00') 

    SELECT *, @to AS 'FetchedOn' 
    FROM Biometric 
    WHERE LogTime BETWEEN @from AND @to 
    ORDER BY LogTime 

    SET @i = @i + 1 

END 

產生以下結果。

Id Name LogTime    FetchedOn 
14 mj 2015-03-19 06:28:06.677 2015-03-20 06:00:00.000 
16 mj 2015-03-19 07:28:03.257 2015-03-20 06:00:00.000 
15 mj 2015-03-19 16:28:07.460 2015-03-20 06:00:00.000 
17 mj 2015-03-20 01:28:08.193 2015-03-20 06:00:00.000 
18 mj 2015-03-20 05:28:03.257 2015-03-20 06:00:00.000 

Id Name LogTime    FetchedOn 
11 mj 2015-03-18 06:28:03.257 2015-03-19 06:00:00.000 
12 mj 2015-03-18 18:28:03.257 2015-03-19 06:00:00.000 
13 mj 2015-03-19 01:28:06.677 2015-03-19 06:00:00.000 

Id Name LogTime    FetchedOn 
6 mj 2015-03-17 06:28:06.677 2015-03-18 06:00:00.000 
8 mj 2015-03-17 07:28:03.257 2015-03-18 06:00:00.000 
7 mj 2015-03-17 16:28:07.460 2015-03-18 06:00:00.000 
9 mj 2015-03-18 01:28:08.193 2015-03-18 06:00:00.000 
10 mj 2015-03-18 05:28:03.257 2015-03-18 06:00:00.000 

Id Name LogTime    FetchedOn 
3 mj 2015-03-16 06:28:03.257 2015-03-17 06:00:00.000 
4 mj 2015-03-16 18:28:03.257 2015-03-17 06:00:00.000 
5 mj 2015-03-17 01:28:06.677 2015-03-17 06:00:00.000 

Id Name LogTime    FetchedOn 
1 mj 2015-03-16 01:28:03.257 2015-03-16 06:00:00.000 
2 mj 2015-03-16 05:28:03.257 2015-03-16 06:00:00.000 

現在我想不使用循環得到相同的結果。 我正在使用SQL 2014,有沒有其他解決方案?

+0

您可以使用CLR表值函數。它可能比t-sql while循環更快。 – TcKs

+0

「相同結果」是指五個_separate_結果集,或者您會接受帶有「i」列的單個結果集以按日期對結果進行分組? – HABO

+0

只要它返回正確的結果集,no表對我來說不重要。 –

回答

2

可以基於所述LOGTIME場的時間部分計算FetchedOn:

SELECT B.*, dateadd(day, (iif(cast(LogTime as time) < '06:00:00', 0, 1)), cast(LogTime as date)) + cast('06:00:00' as datetime) as FetchedOn 
from Biometric B 
ORDER BY FetchedOn DESC, LogTime 

更新:

簡單公式來計算FetchedOn,並且還增加了對SQL2012 +兼容性強制轉換爲datetime

SELECT B.*, cast(cast(dateadd(hour, +18, LogTime) as date) as datetime) + cast('06:00:00' as datetime) as FetchedOn 
from Biometric B 
ORDER BY FetchedOn DESC, LogTime 
+0

到目前爲止所有其他答案都是簡單的代碼轉儲,沒有任何解釋。你的答案要短得多,但它解釋了(如果只是簡要地)一個工作解決方案背後的推理。 +1。 – stakx

+1

@stakx,你認真嗎?我會關閉所有東西,但這段代碼根本行不通。 –

+0

@GiorgiNakeuri:可能,*但*這是唯一一個解釋如何獲得工作解決方案的答案。對我來說,這比複製粘貼式的答案更有用。 – stakx

3

這是一些代碼。想法是從測試數據中獲得所有可能的不同範圍。這是CTE返回:

st      ed 
2015-03-15 06:00:00.000 2015-03-16 06:00:00.000 
2015-03-16 06:00:00.000 2015-03-17 06:00:00.000 
2015-03-17 06:00:00.000 2015-03-18 06:00:00.000 
2015-03-18 06:00:00.000 2015-03-19 06:00:00.000 
2015-03-19 06:00:00.000 2015-03-20 06:00:00.000 

這種簡單後加盟條件,其中數據的範圍介於:

DECLARE @t TABLE(ID INT, D DATETIME) 

INSERT INTO @t VALUES 
(1  ,'2015-03-16 01:28:03.257'), 
(2  ,'2015-03-16 05:28:03.257'), 
(3  ,'2015-03-16 06:28:03.257'), 
(4  ,'2015-03-16 18:28:03.257'), 
(5  ,'2015-03-17 01:28:06.677'), 
(6  ,'2015-03-17 06:28:06.677'), 
(7  ,'2015-03-17 16:28:07.460'), 
(8  ,'2015-03-17 07:28:03.257'), 
(9  ,'2015-03-18 01:28:08.193'), 
(10  ,'2015-03-18 05:28:03.257'), 
(11  ,'2015-03-18 06:28:03.257'), 
(12  ,'2015-03-18 18:28:03.257'), 
(13  ,'2015-03-19 01:28:06.677'), 
(14  ,'2015-03-19 06:28:06.677'), 
(15  ,'2015-03-19 16:28:07.460'), 
(16  ,'2015-03-19 07:28:03.257'), 
(17  ,'2015-03-20 01:28:08.193'), 
(18  ,'2015-03-20 05:28:03.257'), 
(19  ,'2015-03-20 06:28:03.257'), 
(20  ,'2015-03-20 18:28:03.257') 

; 
WITH cte 
      AS (SELECT DISTINCT 
         DATEADD(HOUR, -18, CAST(CAST(D AS DATE) AS DATETIME)) AS st , 
         DATEADD(HOUR, 6, CAST(CAST(D AS DATE) AS DATETIME)) AS ed 
       FROM  @t 
      ) 
    SELECT t.ID, t.D, c.ed 
    FROM cte c 
      JOIN @t t ON t.D BETWEEN c.st AND c.ed 

輸出:

ID D      ed 
1 2015-03-16 01:28:03.257 2015-03-16 06:00:00.000 
2 2015-03-16 05:28:03.257 2015-03-16 06:00:00.000 
3 2015-03-16 06:28:03.257 2015-03-17 06:00:00.000 
4 2015-03-16 18:28:03.257 2015-03-17 06:00:00.000 
5 2015-03-17 01:28:06.677 2015-03-17 06:00:00.000 
6 2015-03-17 06:28:06.677 2015-03-18 06:00:00.000 
7 2015-03-17 16:28:07.460 2015-03-18 06:00:00.000 
8 2015-03-17 07:28:03.257 2015-03-18 06:00:00.000 
9 2015-03-18 01:28:08.193 2015-03-18 06:00:00.000 
10 2015-03-18 05:28:03.257 2015-03-18 06:00:00.000 
11 2015-03-18 06:28:03.257 2015-03-19 06:00:00.000 
12 2015-03-18 18:28:03.257 2015-03-19 06:00:00.000 
13 2015-03-19 01:28:06.677 2015-03-19 06:00:00.000 
14 2015-03-19 06:28:06.677 2015-03-20 06:00:00.000 
15 2015-03-19 16:28:07.460 2015-03-20 06:00:00.000 
16 2015-03-19 07:28:03.257 2015-03-20 06:00:00.000 
17 2015-03-20 01:28:08.193 2015-03-20 06:00:00.000 
18 2015-03-20 05:28:03.257 2015-03-20 06:00:00.000 
+1

誰降低了這一點? –

+0

我做到了。我想你的回答是不正確的,但讓我困擾的是沒有任何解釋「某些代碼」的作用。如果它不僅僅是一個代碼/結果轉儲,而且它們至少伴隨着對其背後思想的簡要解釋,那麼你的答案將會非常有用。如果問題是相應編輯的,我很樂意回覆。 – stakx

+0

我會更新,但我真的認爲沒有什麼可以評論的。在這種情況下,代碼是自選的 –

1

這裏是一個要爲之工作的公式SQL Server 2005+:DATEADD(HOUR, 6, CAST(CAST(DATEADD(HOUR, 18, A.LogTime) AS DATE) AS DATETIME))。我們只需將18小時添加到LogTime,濫用CAST即可截斷時間片,然後將6小時添加到此值。

完整的例子(基於原):

DECLARE @i INT = 5 
DECLARE @endDate DATETIME = '2015-03-20 06:00:00.000'; 
DECLARE @startDate DATETIME = DATEADD(d, [email protected], @endDate); 

SELECT * 
FROM (
    SELECT A.Id 
     , A.LogTime 
     , FetchedOn = DATEADD(HOUR, 6, CAST(CAST(DATEADD(HOUR, 18, A.LogTime) AS DATE) AS DATETIME)) 
    FROM(VALUES 
     (1, '2015-03-16 01:28:03.257') 
     , (2, '2015-03-16 05:28:03.257') 
     , (3, '2015-03-16 06:28:03.257') 
     , (4, '2015-03-16 18:28:03.257') 
     , (5, '2015-03-17 01:28:06.677') 
     , (6, '2015-03-17 06:28:06.677') 
     , (7, '2015-03-17 16:28:07.460') 
     , (8, '2015-03-17 07:28:03.257') 
     , (9, '2015-03-18 01:28:08.193') 
     , (10, '2015-03-18 05:28:03.257') 
     , (11, '2015-03-18 06:28:03.257') 
     , (12, '2015-03-18 18:28:03.257') 
     , (13, '2015-03-19 01:28:06.677') 
     , (14, '2015-03-19 06:28:06.677') 
     , (15, '2015-03-19 16:28:07.460') 
     , (16, '2015-03-19 07:28:03.257') 
     , (17, '2015-03-20 01:28:08.193') 
     , (18, '2015-03-20 05:28:03.257') 
     , (19, '2015-03-20 06:28:03.257') 
     , (20, '2015-03-20 18:28:03.257') 
    ) A (Id, LogTime) 
    WHERE A.LogTime BETWEEN @startDate AND @endDate 
) A 
ORDER BY A.FetchedOn DESC, A.LogTime ASC; 
相關問題