Max() и Min() имеют разное поведение?

Почему поведение min() отличается от поведения max()?

Select 
max(My_Date) over (order by My_Date) as Max_Datum 
, min(My_Date) over (order by My_Date) as Min_Datum 
From 
    (
    Select dateadd(m,-1,getdate()) as My_Date
    Union all 
    Select getdate() as My_Date
    Union all 
    Select dateadd(m,1,getdate()) as My_Date
    Union all 
    Select dateadd(m,2,getdate()) as My_Date
) t1

Результат:

Max_Datum               Min_Datum
2024-08-02 16:20:39.733 2024-08-02 16:20:39.733
2024-09-02 16:20:39.733 2024-08-02 16:20:39.733
2024-10-02 16:20:39.733 2024-08-02 16:20:39.733
2024-11-02 16:20:39.733 2024-08-02 16:20:39.733

Поскольку рамка окна по умолчанию заканчивается в текущей строке, как только вы добавляете порядок. Таким образом, максимум — не видеть более поздние даты, если вы не добавите rows between unbounded preceding and unbounded following

shawnt00 02.09.2024 16:24

Что вы пытаетесь найти для начала? Какие ценности вы ожидали? Если вы хотите найти общую максимальную или минимальную дату, вам не нужен OVER. Используйте SELECT MIN(My_Date), MAX(My_Date) FROM (...)

Panagiotis Kanavos 02.09.2024 16:27

Время педантичных комментариев: Datum — это единственная форма слова «данные», оно не относится конкретно к дате!

DavidG 02.09.2024 16:41

@DavidG6 Извините, я адаптировал запрос с немецкого. В Германии мы используем «Datum» для обозначения даты. Морген не может найти датум? --> Какое число завтра?

Merlin Nestler 02.09.2024 16:48

Ха, честное слово, я откажусь от своего педантичности!

DavidG 02.09.2024 16:49

Было бы полезно, если бы вы конкретно объяснили, какого поведения ожидает Исния.

Dale K 02.09.2024 21:43
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Проблема не в функциях, а в вашем предложении OVER. Вы добавили предложение OVER с предложением ORDER BY My_Date, которое, согласно документации , по умолчанию соответствует окну RANGE UNBOUNDED PRECEDING AND CURRENT ROW. В результате значение MAX всегда будет значением текущей строки, потому что именно в этом порядке расположены данные.

Возьмем, к примеру, следующие упрощенные данные:

ИДЕНТИФИКАТОР SomeNumber 1 2 2 3 3 1 4 5 5 4

Теперь предположим, что у вас есть аналогичный запрос:

SELECT MIN(SomeNumber) OVER (ORDER BY SomeNumber) AS MinSomeNumber,
       MAX(SomeNumber) OVER (ORDER BY SomeNumber) AS MaxSomeNumber
FROM dbo.SomeTable
ORDER BY ID;

Это приведет к результатам:

MinSomeNumber MaxSomeNumber 1 2 1 3 1 1 1 5 1 4

Фактически в каждой строке вы задаете следующее:

  1. Наименьшее число между 1 и 1 и наибольшее число между 1 и 1.
  2. Наименьшее число между 1 и 2 и наибольшее число между 1 и 2.
  3. Наименьшее число между 1 и 3 и наибольшее число между 1 и 3.
  4. Наименьшее число от 1 до 4 и наибольшее число от 1 до 4.
  5. Наименьшее число от 1 до 5 и наибольшее число от 1 до 5.

Итак, вы можете видеть, что MAX будет отличаться, а MIN — нет.

Вероятно, вы хотите изменить ORDER, указать окно как весь набор данных или не указывать окно:

SELECT MIN(SomeNumber) OVER (ORDER BY SomeNumber) AS MinSomeNumber,
       MAX(SomeNumber) OVER (ORDER BY SomeNumber DESC) AS MaxSomeNumber,
       MIN(SomeNumber) OVER (ORDER BY SomeNumber ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MinSomeNumber,
       MAX(SomeNumber) OVER (ORDER BY SomeNumber ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MaxSomeNumber,
       MIN(SomeNumber) OVER () AS MinSomeNumber,
       MAX(SomeNumber) OVER () AS MaxSomeNumber
FROM dbo.SomeTable;

Последнее, вероятно, имеет здесь наибольший «смысл», поскольку размещение данных для MIN/MAX в порядке значения, для которого вы получаете MIN/MAX, ничего не дает. Если бы вы упорядочивали по другому столбцу, это имело бы больше смысла.

db<>рабочий пример

Функция МИН смотрит назад (включая текущую строку и все предыдущие строки), поэтому она продолжает возвращать самую раннюю дату, которую она видела.

Функция MAX также смотрит назад, но продолжает обновляться до последнего максимального значения, с которым она столкнулась.

MAX(): при перемещении по строкам он просматривает текущую строку и все строки перед ней. Он всегда выбирает самую большую (последнюю) дату, которую он когда-либо видел.

MIN(): при перемещении по строкам он также просматривает текущую строку и все строки перед ней. Но он всегда выбирает самую маленькую (самую раннюю) дату, которую он видел до сих пор.

Ваши данные У вас есть такие даты:

2024-08-02 2024-09-02 2024-10-02 2024-11-02 Для МАКС():

Начинается со 2 августа 2024 г. Переходит к 2 сентября 2024 г.: «Что больше? 02 сентября 2024 г. или 02 августа 2024 г.?» Он сохраняется 2 сентября 2024 г.

Далее идет 2024-10-02: «Что больше? 2024-10-02 или 2024-09-02?» Он сохраняется 02.10.2024.

Наконец, 02.11.2024: «Что больше? 02.11.2024 или 02.10.2024?» Он сохраняется 02.11.2024. Для МИН():

Начинается со 2 августа 2024 г. Переходит к 2 сентября 2024 г.: «Что меньше? 02 сентября 2024 г. или 02 августа 2024 г.?» Он сохраняется 2 августа 2024 г.

Далее следует 02.10.2024: «Что меньше? 02.10.2024 или 02.08.2024?» Он все еще сохраняется 2 августа 2024 г.

Наконец, 02.11.2024: «Что меньше? 02.11.2024 или 02.08.2024?» Он все еще сохраняется 2 августа 2024 г.

Подводя итог, можно сказать, что и min(), и max() просматривают все предыдущие строки в упорядоченном окне, но min() сохраняет самую раннюю дату, а max() обновляет до самой последней. Вот почему вы видите описанное вами поведение.

Функции MAX/MIN не имеют никакого отношения к проблеме, это оконное управление. LAST_VALUE/FIRST_VALUE демонстрируют такое же поведение. AVG бы. Любая оконная функция с ORDER BY подойдет, потому что проблема в окне, а не в функции.

Thom A 02.09.2024 16:41

Честно говоря, для меня это немного напоминает LLM.

Thom A 02.09.2024 16:42

Другие вопросы по теме

Похожие вопросы