SQL Server: ВЫБЕРИТЕ запрос, чтобы получить ОТЛИЧНОЕ и МАКСИМАЛЬНОЕ значение порядка отображения

#sql #sql-server #greatest-n-per-group #window-functions #hierarchical-data

#sql #sql-сервер #наибольшее число на группу #окно-функции #иерархический-данные

Вопрос:

У меня есть таблица продуктов, таблица категорий и таблица сопоставления. Категория, сохраненная в виде дерева категорий. Если один продукт сопоставлен с последней категорией в иерархии третьего уровня. Все уровни, сохраненные в таблице сопоставления с тем же идентификатором продукта.

например: предположим, что есть категория, подобная этой Electronic> Ноутбуки> DELL, и когда идентификатор продукта = 1, присвоенный категории ‘DELL’, сопоставление сохранится как [1, Electronic], [1, Ноутбуки], [1, DELL]

Когда я получаю данные с помощью запроса выбора, все уровни категории отображаются с одинаковым идентификатором продукта.

Моя проблема в том, что мне нужно получить данные как [ProductID, ProductName, LastCategortLevel, CategoryName, CategoryID].

Смотрите фактический результат ниже. Мне просто нужно выбрать выделенный продукт с последним уровнем категории, который является самым высоким уровнем заказа категории.

введите описание изображения здесь

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

Фактические таблицы базы данных очень большие. Но я попытался реализовать тот же сценарий с небольшими временными таблицами. смотрите приведенные ниже запросы.

 DECLARE @Products TABLE (ProductId INT NOT NULL)

INSERT INTO @Products(ProductId)  
    SELECT ProductId 
    FROM (VALUES (1), (2), (3), (4)) as x (ProductId)

DECLARE @Categories TABLE (CategoId INT NOT NULL,
                           Name VARCHAR(MAX) NOT NULL,
                           ParentCategoryId INT NOT NULL,
                           DisplayOrder INT NOT NULL)

-- 1st category tree
INSERT INTO @Categories VALUES (10, 'Electronic', 0, 1)
INSERT INTO @Categories VALUES (11, 'LapTops', 10, 2)
INSERT INTO @Categories VALUES (12, 'DELL', 11, 3)
INSERT INTO @Categories VALUES (13, 'HP', 11, 3)

-- 2st category tree
INSERT INTO @Categories VALUES (14, 'Clothes', 0, 1)
INSERT INTO @Categories VALUES (15, 'T-Shirts', 14, 2)
INSERT INTO @Categories VALUES (16, 'Red', 15, 3)
INSERT INTO @Categories VALUES (17, 'Denim', 14, 2)
INSERT INTO @Categories VALUES (18, 'Levise', 17, 3)

DECLARE @Product_Category_Mappings TABLE(MappingId INT NOT NULL,
                                         ProductId INT NOT NULL,
                                         CategoryId INT NOT NULL)

INSERT INTO @Product_Category_Mappings VALUES (100, 1, 10)
INSERT INTO @Product_Category_Mappings VALUES (101, 1, 11)
INSERT INTO @Product_Category_Mappings VALUES (102, 1, 12)

INSERT INTO @Product_Category_Mappings VALUES (103, 2, 10)
INSERT INTO @Product_Category_Mappings VALUES (104, 2, 11)
INSERT INTO @Product_Category_Mappings VALUES (105, 2, 12)

INSERT INTO @Product_Category_Mappings VALUES (106, 3, 14)
INSERT INTO @Product_Category_Mappings VALUES (107, 3, 15)
INSERT INTO @Product_Category_Mappings VALUES (108, 3, 16)

INSERT INTO @Product_Category_Mappings VALUES (109, 4, 14)
INSERT INTO @Product_Category_Mappings VALUES (110, 4, 17)
INSERT INTO @Product_Category_Mappings VALUES (111, 4, 18)

SELECT * 
FROM @Products  P
INNER JOIN @Product_Category_Mappings M ON M.ProductId = P.ProductId
INNER JOIN @Categories C ON C.CategoId = M.CategoryId
WHERE M.ProductId = P.ProductId 
ORDER BY P.ProductId, C.DisplayOrder
  

Результат приведенного выше сценария. Как я получаю выделенные строки?

введите описание изображения здесь

Ответ №1:

Для каждого ProductId вам нужна строка с наибольшим DisplayOrder значением. Вы можете использовать функции окна:

 SELECT *
FROM (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY P.ProductId ORDER BY C.DisplayOrder DESC) rn
    FROM @Products  P
    INNER JOIN @Product_Category_Mappings M ON M.ProductId = P.ProductId
    INNER JOIN @Categories C ON C.CategoId = M.CategoryId
    WHERE M.ProductId = P.ProductId 
) t
WHERE rn = 1
ORDER BY P.ProductId, C.DisplayOrder
  

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

1. Спасибо. Я внес некоторые изменения в атрибут. Потому что показал дублирующуюся ошибку ProductID, и это сработало после этого небольшого исправления. Я отредактировал ваш ответ с правильным запросом для будущих ссылок.