Показать количество меньших и больших значений в SQL

#mysql #sql #mariadb

Вопрос:

У меня есть определенная проблема при попытке создать SQL. У меня есть таблица со следующим форматом и данными.

ID ценность Дата
12 3 2020-06-01
12 4 2020-06-09
12 1 2020-06-20
5 4 2020-06-11
5 5 2020-06-17

Моя цель-сделать что-то подобное:

ID ниже выше
12 1 1
5 0 1

Это ищет значение самой старой строки В определенном интервале (например, 100 дней)и сравнивает его со всеми последующими датами, если их значения выше и ниже, и возвращает счетчик.

У меня есть кое-что, что работает, но для этого требуется больше запросов: один для группировки принимает все идентификаторы с датами в интервале xx дней

 SELECT id FROM table
WHERE date >= CURDATE() - INTERVAL 30 DAY GROUP BY id
ORDER BY id ASC;
 

А затем я перебираю каждую строку и получаю ее более низкие и более высокие значения.

 SELECT
*
FROM
(
  SELECT
    COUNT(*) AS higher, id
  FROM
    `table`
  WHERE
      id = 12 AND date > CURDATE() - INTERVAL 30 DAY AND value > (
      SELECT value FROM table 
      WHERE table.date >= CURDATE() - INTERVAL 30 DAY AND id = 12 
      ORDER BY `table`.`date` ASC LIMIT 1
      )
) AS t1,(
  SELECT
    COUNT(*) AS deteriorated_placements
  FROM
    `table`
  WHERE
      id = 12 AND date > CURDATE() - INTERVAL 30 DAY AND value < (
      SELECT value FROM table 
      WHERE table.date >= CURDATE() - INTERVAL 30 DAY AND id = 12 
      ORDER BY `table`.`date` ASC LIMIT 1
    )
) AS t2;
 

Проблема в том, что я делаю еще около 40 запросов. Я знаю, что, может быть, это и не большая проблема, но
Есть ли способ каким-то образом объединить эти 2 запроса?

Комментарии:

1. Можете ли вы использовать оконные функции?

2. @SalmanA Да, я знаю. Я думаю, что данный ответ мне поможет, мне просто нужно добавить предложение where и посмотреть, работает ли оно.

Ответ №1:

Воспользуйся first_value() :

 select id,
       sum(value < value_1) as lower,
       sum(value > value_1) as higher
from (select t.*,
             first_value(value) over (partition by id order by date) as value_1
      from t
     ) t
group by id;
 

Комментарии:

1. @Slavian . . . Просто добавьте where предложение в подзапрос. Логика на самом деле не меняется.

2. Предложение where должно быть включено во внутренний запрос к вашему сведению.

3. @GordonLinoff Да, я сделал это, я просто не был знаком с first_value, разделением по предметам, так как я никогда не использовал их раньше. Большое спасибо 😀 Я чувствую себя совершенно глупым и должен больше сосредоточиться на своем SQL.