2011-06-10 22 views
3

我有以下三個簡單的T-SQL查詢。第一個是一個範圍邊界(DATETIME型)中得到記錄:在一系列邊界內的SQL查詢記錄以及範圍之外的最大/最小值

SELECT value, timestamp 
FROM myTable 
WHERE timestamp BETWEEN @startDT AND @endDT 

第二個是讓最接近記錄@startDT(DATETIME型)

SELECT TOP 1 
    value, timestamp 
FROM myTable 
WHERE timestamp > @startDT 
ORDER BY timestamp DESC 

,最後一個是@endDT後得到的最接近記錄:

SELECT TOP 1 
    value, timestamp 
FROM myTable 
WHERE timestamp < @endDT 
ORDER BY timestamp ASC 

我想獲得以上三個查詢的所有記錄的一組記錄。我試圖使用UNION,但似乎UNION中的子查詢不允許ORDER BY子句。有沒有有效的方法來獲得我的結果?

. . * | * * * * * | * . . . 
     start  end 

上面的圖表只顯示了* s的記錄作爲我所需的記錄,而| ... |是界限。

順便說一下,myTable中的數據量是巨大的。我對UNION的理解並不是從UNION獲取數據的有效方法。任何有效的方式來獲取數據沒有UNION?

+0

您確定使用'ORDER BY value,timestamp'從這些查詢中獲得了期望的結果嗎?根據你的描述,我想你只想在時間戳上訂購。否則,你會得到最接近邊界的最小值。 – 2011-06-10 20:14:29

+0

你說得對,我只是通過時間戳來改變它。 – 2011-06-10 20:16:24

+0

很高興看到這麼多答案滿足我的需求。 @Piotr Auguscik提到在性能方面,min/max比Order + top 1要好。是對的嗎?根據答案,我找到了「最小/最大+分組依據」的解決方案。不知道哪一個更好。請記住myTable在我的情況下包含大量的記錄。 – 2011-06-11 00:16:36

回答

3

如你所願,沒有UNION。

的MySQL(檢測過

SELECT 
    dv1.timestamp, dv1.values 
FROM 
    myTable AS dv1 
WHERE 
    dv1.timestamp 
    BETWEEN (
      SELECT dv2.timestamp 
      FROM myTable AS dv2 
      WHERE dv2.timestamp < '@START_DATE' 
      ORDER BY dv2.timestamp DESC 
      LIMIT 1 
      ) 
    AND (SELECT dv3.timestamp 
      FROM myTable AS dv3 
      WHERE dv3.timestamp > '@END_DATE' 
      ORDER BY dv3.timestamp ASC 
      LIMIT 1 
     ) 

編輯對不起,我忘了通知一下T-SQL。

T-SQL(未測試

SELECT 
    dv1.timestamp, dv1.values 
FROM 
    myTable AS dv1 
WHERE 
    dv1.timestamp 
    BETWEEN (
      SELECT TOP 1 dv2.timestamp 
      FROM myTable AS dv2 
      WHERE dv2.timestamp > @START_DATE 
      ORDER BY dv2.timestamp DESC 
      ) 
    AND (SELECT TOP 1 dv3.timestamp 
      FROM myTable AS dv3 
      WHERE dv3.timestamp < @END_DATE 
      ORDER BY dv3.timestamp ASC 
     ) 

如果結果是不正確的,你可以只更換子查詢(即運營商,以及ASC/DESC)。

跳出框框:)

+0

不錯。我不是100%確定聯合會是否效率較低。真的嗎? – 2011-06-10 21:04:17

+1

順便說一下,T-SQL不支持LIMIT 1。我認爲它應該是TOP 1呢? – 2011-06-10 21:18:25

+0

有人說是的。事先,您可以使用'EXPLAIN the_query'來比較查詢執行時間:)但是,在某些情況下,UNION似乎很有用,但我更願意避免它。 – exodream 2011-06-10 21:23:15

0

您可以將這些有序查詢放入子查詢中以避免不能直接聯合它們。有點煩人,但它會讓你得到你想要的。

SELECT value, timestamp 
FROM myTable 
WHERE timestamp BETWEEN @startDT AND @endDT 
UNION 
SELECT value, timestamp 
FROM (
SELECT TOP 1 
    value, timestamp 
FROM myTable 
WHERE timestamp > @startDT 
ORDER BY value, timestamp DESC 
) x 
UNION 
SELECT value, timestamp 
FROM (
SELECT TOP 1 
    value, timestamp 
FROM myTable 
WHERE timestamp < @endDT 
ORDER BY value, timestamp ASC 
) x 
1

U可以使用最大/最小值來獲得您需要的值。 Order by + top 1不是獲得最大值的最佳方式,我可以在你的查詢中看到。爲了排序n個項目其O(n到2),獲得最大應該只有O(n)

+0

然後我必須使用GROUP BY,如果我使用max/min。我的查詢是簡化的。實際上,記錄中有兩個以上的字段,例如value1,value2,...,timestamp。 – 2011-06-10 20:29:48

1
SELECT value, timestamp 
FROM myTable 
WHERE timestamp BETWEEN @startDT AND @endDT 
union 
select A.Value, A.TimeStamp 
From (
SELECT TOP 1 
    value, timestamp 
FROM myTable 
WHERE timestamp > @startDT 
ORDER BY value, timestamp DESC) A 
Union 
Select A.Value, A.TimeStamp 
From (
SELECT TOP 1 
    value, timestamp 
FROM myTable 
WHERE timestamp < @endDT 
ORDER BY value, timestamp ASC) A 
1

的在您的文章的第二個和第三個查詢沒有太大的意義,因爲

WHERE timestamp > @startDT 

WHERE timestamp < @endDT 

結果時間戳INSIDE的範圍,但您的描述

. . * | * * * * * | * . . . 
     start  end 

上面的圖表只顯示* s的記錄作爲我所需的記錄,而| ... |是界限。

意味着不同的東西。

所以下面的說明,並使用下面的映射

myTable = Posts 
value = score 
timestamp = creationdate 

我寫了一篇關於data.stackexchange.com this query(從exodream的答案,但與比較運營商在 正確 相反的方向修改)

DECLARE @START_DATE datetime 
DECLARE @END_DATE datetime 
SET @START_DATE = '2010-10-20' 
SET @END_DATE = '2010-11-01' 

SELECT score, 
     creationdate 
FROM posts 
WHERE creationdate BETWEEN (SELECT TOP 1 creationdate 
          FROM posts 
          WHERE creationdate < @START_DATE 
          ORDER BY creationdate DESC) 
          AND 
            (SELECT TOP 1 creationdate 
            FROM posts 
            WHERE creationdate > @END_DATE 
            ORDER BY creationdate ASC) 
ORDER by creationDate 

,輸出

score creationdate   
----- ------------------- 
4  2010-10-19 23:55:48 
3  2010-10-20 2:24:50 
6  2010-10-20 2:55:54 
... 
... 
7  2010-10-31 23:14:48 
4  2010-10-31 23:18:17 
4  2010-10-31 23:18:48 
0  2010-11-01 3:59:38 

(382 row(s) affected) 

請注意第一行和最後一行如何超出範圍限制

相關問題