SQL查询记录范围内的范围和最大/最小范围

时间:2011-06-10 20:10:01

标签: sql tsql

我有以下三个简单的T-SQL查询。第一个是获取一系列边界内的记录(DATETIME类型):

 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获取数据的任何有效方法?

5 个答案:

答案 0 :(得分:3)

如你所愿,没有UNION。

MySQL( TESTED

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( NOT TESTED

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)。

开箱即用:)

答案 1 :(得分:1)

你可以使用max / min来获得你需要的价值。 Order by + top 1不是获取最大价值的最佳方式,我可以在您的查询中看到。要对n项进行排序,其O(n到幂2),得到max应该只是O(n)

答案 2 :(得分: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

答案 3 :(得分: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)

注意第一行和最后一行是如何超出范围的限制

答案 4 :(得分:0)

您可以将这些有序查询放入子查询中,以便无法直接UNION它们。有点烦人,但它会让你得到你想要的东西。

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