Имитировать функцию задержки в MySQL
| time | company | quote |
+---------------------+---------+-------+
| 0000-00-00 00:00:00 | GOOGLE | 40 |
| 2012-07-02 21:28:05 | GOOGLE | 60 |
| 2012-07-02 21:28:51 | SAP | 60 |
| 2012-07-02 21:29:05 | SAP | 20 |
Как сделать задержку в этой таблице в MySQL для печати разницы в кавычках, например:
GOOGLE | 20
SAP | 40
Ответы
Ответ 1
Это мой любимый взлом MySQL.
Вот как вы эмулируете функцию задержки:
SET @quot=-1;
select time,company,@quot lag_quote, @quot:=quote curr_quote
from stocks order by company,time;
-
lag_quote
содержит значение предыдущей строки. Для первой строки @quot -1.
-
curr_quote
содержит значение текущей строки.
Примечания:
-
order by
важно здесь, как и в обычном
оконная функция.
- Вы также можете использовать lag для
company
, чтобы быть уверенным, что вы вычисляете разницу в кавычках одного и того же company
.
- Вы также можете реализовать счетчики строк таким же образом
@cnt:[email protected]+1
Приятная вещь в этой схеме заключается в том, что она очень скудна по сравнению с некоторыми другими подходами, такими как использование агрегатных функций, хранимых процедур или обработки данных на сервере приложений.
ИЗМЕНИТЬ:
Теперь приступим к вашему вопросу получения результата в указанном вами формате:
SET @quot=0,@latest=0,company='';
select B.* from (
select A.time,A.change,IF(@comp<>A.company,1,0) as LATEST,@comp:=A.company as company from (
select time,company,[email protected] as change, @quot:=quote curr_quote
from stocks order by company,time) A
order by company,time desc) B where B.LATEST=1;
Вложения не связаны друг с другом, поэтому не так плохо (вычислительно), как выглядит (синтаксически):)
Сообщите мне, нужна ли вам помощь.
Ответ 2
Из MySQL 8.0 и выше нет необходимости моделировать LAG
. Он поддерживается,
Функция окна:
Возвращает значение expr из строки, которая отстает (предшествует) текущей строке на N строк в своем разделе. Если такой строки нет, возвращаемое значение будет по умолчанию. Например, если N равно 3, возвращаемое значение является значением по умолчанию для первых двух строк. Если N или значение по умолчанию отсутствует, значения по умолчанию равны 1 и NULL соответственно.
SELECT
company,
quote,
LAG(quote) OVER(PARTITION BY company ORDER BY time) AS prev_quote
FROM tab;
Демоверсия DBFiddle
Ответ 3
Чтобы достичь желаемого результата, сначала вам нужно найти последние и последние последние временные метки для каждой компании. Это довольно просто со следующим запросом:
SELECT c.company, c.mts, max(l.ts) AS lts
FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
LEFT JOIN cq l
ON c.company = l.company AND c.mts > l.ts
GROUP BY c.company, c.mts;
Теперь вам нужно присоединиться к этому подзапросу с исходной таблицей, чтобы получить желаемые результаты:
SELECT c.company, l.quote, coalesce(l1.quote, 0),
(l.quote - coalesce(l1.quote, 0)) AS result
FROM (SELECT c.company, c.mts, max(l.ts) AS lts
FROM (SELECT company, max(ts) AS mts FROM cq GROUP BY company) AS c
LEFT JOIN cq l
ON c.company = l.company AND c.mts > l.ts
GROUP BY c.company, c.mts) AS c
LEFT JOIN cq AS l ON l.company = c.company AND l.ts = c.mts
LEFT JOIN cq AS l1 ON l1.company = c.company AND l1.ts = c.lts;
Вы можете увидеть результаты SQL Fiddle.
Этот запрос использует только стандартные возможности SQL и должен работать на любой РСУБД.