Перекрестный запрос на получение цены на последнюю дату из таблицы

У меня есть три таблицы:

Человек

Группа продуктов

Цена каждой группы продуктов для человека с датой

Мне нужен результат ниже, который показывает цену последней даты каждой группы продуктов.

Помогите мне, пожалуйста.

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

Но я хочу это в одном запросе

Найдите «условную агрегацию». Если вам все еще нужна помощь с вашим запросом после поиска техники, вам следует публиковать данные в виде текста, а не изображений. Почему?

Sean Lange 16.08.2024 20:54

Если группы A–C многочисленны или переменны, вам придется изучить Dynamic SQL или перейти на уровень представления.

John Cappelletti 16.08.2024 20:59

Этот вопрос похож на: Получите по 1 верхней строке каждой группы. Если вы считаете, что это другое, отредактируйте вопрос, поясните, чем он отличается и/или как ответы на этот вопрос не помогают решить вашу проблему.

T N 16.08.2024 21:33

Пожалуйста, не используйте изображения для данных, используйте уценку таблицы.

Dale K 16.08.2024 21:48

К вашему сведению, в базах данных есть строки и столбцы, а не ячейки.

Dale K 16.08.2024 21:56
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
3
6
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать PIVOT, чтобы получить результаты в одном запросе.

select 
     isnull(MAX([Group C]),'') as [Group C]
  ,  isnull(MAX([Group B]),'') as [Group B]
  ,  isnull(MAX([Group A]),'') as [Group A]
  ,FullName, PersonID
from
(
SELECT PGP.*, P.FullName, PG.ProductGroupName, CONVERT(varchar(10),Pricedate,112) + '-' + Price as DatePrice
FROM ProductGroupPrice PGP
INNER JOIN ProductGroup PG ON PG.ProductGroupID=PGP.ProductGroupID
INNER JOIN person P ON P.PersonID=PGP.PersonID
) x
pivot
(
  max(DatePrice)
  for ProductGroupName in([Group A], [Group B], [Group C])
)p
  GROUP BY FullName, PersonID

рабочий пример

Это возвращает максимальную цену, я думаю, ОП хотел иметь последнюю цену за дату.

siggemannen 16.08.2024 21:28

@siggemannen легко исправить. Я просто добавлю к цене дату. Затем я могу просто удалить первые 11 символов для презентации. Я оставлю этот шаг Мохаммаду Кермани

Bart McEndree 16.08.2024 21:40

Возможно, вы захотите снова удалить дату. Кроме того, это не сработает, если Price не является VARCHAR, а это, вероятно, не так. Не надо торопиться, лучше сделай все правильно

siggemannen 16.08.2024 21:42
Ответ принят как подходящий

Логику выбора последней Price для каждой комбинации ProductGroupID и PersonID см. в разделе Получить 1 верхнюю строку каждой группы. Общий метод заключается в использовании оконной функции ROW_NUMBER() для нумерации строк внутри каждой группы, а затем фильтрации по номеру строки = 1.

После этого останется лишь выполнить операцию PIVOT.

SELECT PVT.[GROUP C], PVT.[GROUP B], PVT.[GROUP A], PVT.FullName, PVT.PersonId
FROM (
    SELECT PG.ProductGroupName, PGP.Price, P.FullName, P.PersonId
    FROM (
        SELECT
            *,
            ROW_NUMBER()
                OVER(PARTITION BY ProductGroupID, PersonID ORDER BY PriceDate DESC)
                AS RowNum
        FROM ProductGroupPrice
    ) PGP
    JOIN ProductGroup PG
        ON PG.ProductGroupID = PGP.ProductGroupID
    JOIN person P
        ON P.PersonID = PGP.PersonID
    WHERE PGP.RowNum = 1
) Q
PIVOT (
    MAX(Q.Price)
    FOR Q.ProductGroupName IN ([GROUP C], [GROUP B], [GROUP A])
) PVT
ORDER BY PVT.PersonId

Альтернативой использованию PIVOT является условная агрегация, при которой вы определяете элементы выбора, например MAX(CASE WHEN <condition> THEN <value> END) AS <column>.

SELECT
    MAX(CASE WHEN PG.ProductGroupName = 'GROUP C' THEN PGP.Price END) AS [GROUP C],
    MAX(CASE WHEN PG.ProductGroupName = 'GROUP B' THEN PGP.Price END) AS [GROUP B],
    MAX(CASE WHEN PG.ProductGroupName = 'GROUP A' THEN PGP.Price END) AS [GROUP A],
    P.FullName,
    P.PersonId
FROM (
    SELECT
        *,
        ROW_NUMBER()
            OVER(PARTITION BY ProductGroupID, PersonID ORDER BY PriceDate DESC)
            AS RowNum
    FROM ProductGroupPrice
) PGP
JOIN ProductGroup PG
    ON PG.ProductGroupID = PGP.ProductGroupID
JOIN person P
    ON P.PersonID = PGP.PersonID
WHERE PGP.RowNum = 1
GROUP BY P.FullName, P.PersonId
ORDER BY P.PersonId

Промежуточные результаты:

Название группы продуктов Цена Полное имя идентификатор человека Группа А 250 Карел 1 Группа А 120 Али 3 Группа А 100 Эмран 4 Группа Б 150 Карел 1 Группа Б 200 Джек 2 Группа С 150 Карел 1 Группа С 100 Джек 2 Группа С 105 Хана 5

Окончательные результаты:

ГРУППА С ГРУППА Б ГРУППА А Полное имя идентификатор человека 150 150 250 Карел 1 100 200 нулевой Джек 2 нулевой нулевой 120 Али 3 нулевой нулевой 100 Эмран 4 105 нулевой нулевой Хана 5

См. эту db<>fiddle для демонстрации обоих подходов.

спасибо, это работает. очень хорошо

mohammad kermany 16.08.2024 23:12

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