Записи SQL-запросов в пределах диапазона и максимум / мин за пределами диапазона - PullRequest
3 голосов
/ 11 июня 2011

У меня есть три простых запроса 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 ]

3 голосов
/ 11 июня 2011

Как вы хотите, без 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).

Думай из коробки:)

1 голос
/ 11 июня 2011

Второй и третий запросы в вашем посте не имеют особого смысла, потому что

WHERE timestamp > @startDT

и

WHERE timestamp < @endDT

приводят к отметкам времени INSIDE диапазона,но ваши описания

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

Приведенный выше график просто показывает записи * s как мои обязательные записи, а | ... |это границы.

означает что-то другое.

Итак, следуя описаниям и используя следующее отображение

myTable = Posts
value = score
timestamp  = creationdate 

Я написал этот запрос на data.stackexchange.com (изменено из ответа 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)

Примечаниекак первая и последняя строки находятся за пределами диапазона

1 голос
/ 11 июня 2011

U может использовать макс / мин, чтобы получить значение, которое вам нужно. Order by + top 1 не лучший способ получить максимальное значение, что я вижу в ваших запросах. Чтобы отсортировать n элементов по O (n в степень 2), максимальное значение должно быть только O (n)

1 голос
/ 11 июня 2011
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
0 голосов
/ 11 июня 2011

Вы можете поместить эти упорядоченные запросы в подзапросы, чтобы обойтись без возможности 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...