Как выбрать последовательную дату в SQL - PullRequest
3 голосов
/ 19 марта 2019

Вот данные, с которыми я хочу работать

create table weather(
    id int,
    recorddate date,
    temp int,
    primary key (id)
);

insert into weather values (1, '2015-01-01', 10);
insert into weather values (2, '2015-01-02', 15);
insert into weather values (3, '2015-01-03', 20);

Я хочу выбрать дату, которая имеет более высокую температуру, чем предыдущий день, и я использовал этот запрос:

select id
from weather a
where id = (select id from weather b where datediff(a.recorddate, b.recorddate) = -1 and b.temp > a.temp)

Запрос возвращает 0 записей, и я знаю, что логика подзапроса верна, но по какой-то причине он не работает.

Обновление

Я не ищу альтернативный способ написания этого запроса, я хочу знать, что не так с запросом выше?

Обновление

Часть, в которой я ошибся, заключается в том, что я думал присвоить значение id, написав where id=...

Ответы [ 6 ]

1 голос
/ 19 марта 2019

Я рекомендую вам использовать функцию LAG, используя ее, вы можете получить температуру предыдущего дня, а затем просто добавить предложение where, сравнивающее фактическую температуру строки с результатом функции LAG.Вот хороший пример его использования: http://www.mysqltutorial.org/mysql-window-functions/mysql-lag-function/. Например:

SELECT id
FROM (
SELECT id, temp, LAG(temp,1) OVER (ORDER BY recorddate ASC) AS prev_temp, 
LAG(recorddate,1) OVER (ORDER BY recorddate ASC) AS prev_recorddate
FROM weather
)
WHERE prev_temp < temp
AND datediff(recorddate, prev_recorddate) = -1

Имейте в виду, что эта функция поддерживается до MySQL 8.0, но вы можете смоделировать ее, как показано в этом посте Имитация функции задержки в MySQL

1 голос
/ 19 марта 2019

Я не понимаю, почему способ, которым я написал, не работает

Поскольку вы сравниваете a.id = b.id, но ваши условия гарантируют, что они никогда не будутравны.

Вот демонстрация, показывающая строки, которые вы, вероятно, намереваетесь найти, потому что они имеют datediff = -1 и b.temp> a.temp, но в обоих случаях идентификаторы различаются.

mysql> select a.id as a_id, b.id as b_id, 
  datediff(a.recorddate, b.recorddate) as datediff, 
  b.temp > a.temp, a.id = b.id 
from weather a cross join weather b;
+------+------+----------+-----------------+-------------+
| a_id | b_id | datediff | b.temp > a.temp | a.id = b.id |
+------+------+----------+-----------------+-------------+
|    1 |    1 |        0 |               0 |           1 |
|    2 |    1 |        1 |               0 |           0 |
|    3 |    1 |        2 |               0 |           0 |
|    1 |    2 |       -1 |               1 |           0 | <--
|    2 |    2 |        0 |               0 |           1 |
|    3 |    2 |        1 |               0 |           0 |
|    1 |    3 |       -2 |               1 |           0 |
|    2 |    3 |       -1 |               1 |           0 | <--
|    3 |    3 |        0 |               0 |           1 |
+------+------+----------+-----------------+-------------+

Единственный способ a.id = b.id - это если вы сравниваете одну и ту же строку (id является первичным ключом, поэтому только одна строка может иметь это значение), но в этих случаях datediff будет естественным образомбудет 0, и ни один temp не будет больше другого - они будут равны, потому что это один и тот же ряд.

0 голосов
/ 19 марта 2019

Используйте это: это работает для меня

Select recorddate from weather where temp>
(Select temp from weather where id =
(Select max(id) from weather)-1)
0 голосов
/ 19 марта 2019

Я вижу, что вопрос был обновлен (или я пропустил эту часть, когда читал его), поэтому вот мой обновленный ответ:

Ваш запрос пытается найти две строки, которые имеюттот же идентификатор, но разные значения для даты и температуры, что, конечно, невозможно, учитывая, что идентификатор уникален.Идентификатор не может быть просто частью условия «равно».


Старый ответ и возможный способ сделать это.

Использовать простое соединение на основе сравнения температуры и DATEDIFF один между двумя рядами

SELECT *
FROM weather w
JOIN weather w2 ON w.temp > w2.temp AND DATEDIFF( w.recorddate, w2.recorddate) = 1
0 голосов
/ 19 марта 2019

Сначала необходимо получить запись предыдущей даты, соединив эту же таблицу с этой датой, а затем применить временное условие:

select w.recorddate from weather w
join weather w2 on ( w.recorddate = DATE_ADD( w2.recorddate, INTERVAL 1 DAY ) )
where w.temp > w2.temp;
0 голосов
/ 19 марта 2019

Ваш запрос возвращает ноль строк, потому что условие WHERE всегда false.

Позволяет переписать следующее:

where a.id = (select b.id from weather b where datediff(a.recorddate, b.recorddate) = -1 and b.temp > a.temp)

Требуется, чтобы a.id было таким же, как b.id, но в то же время datediff(a.recorddate, b.recorddate) = -1 and b.temp > a.temp, что, очевидно, невозможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...