我有以下三个简单的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获取数据的任何有效方法?
答案 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