SQL Server - ВЫБЕРИТЕ ТОП 5 строк для каждого FK - PullRequest
5 голосов
/ 20 сентября 2009

У меня есть следующий запрос, который ищет ТОП 5 продуктов , соответствующих запросу. Каждый Продукт связан с Магазином

ВЫБРАТЬ ТОП 5 * ИЗ ПРОДУКТОВ p, магазины s ГДЕ p.ShopId = s.ShopId И p.ProductName LIKE '% Рождество%'

Мне нужно расширить это, чтобы оно возвращало мне ТОП 5 продуктов в каждый Магазин .

Может кто-нибудь дать мне знать, как можно изменить запрос для достижения этой цели? - т.е. выберите ТОП-5 товаров, соответствующих "% christmas%" в каждом магазине (а не текущий, который показывает ТОП-5 товаров, соответствующих "% chrismas%" в всех магазинах).

Ответы [ 4 ]

10 голосов
/ 20 сентября 2009

На самом деле вам не хватает ORDER BY, чтобы сделать ТОП значимым, или любое решение на основе ROW_NUMBER, для которого требуется ORDER BY.

SELECT
    *
FROM
    Shops s 
CROSS APPLY (
    SELECT TOP 5
        *
    FROM
        Products p
    WHERE
        p.ShopId = s.ShopId AND p.ProductName LIKE '%christmas%'
    ORDER BY --added on edit
        ???
) X
4 голосов
/ 20 сентября 2009

Попробуйте это:

select * from (
    select *, rn = row_number() over (partition by s.ShopId order by p.ProductName)
    from Products p, Shops s 
    where p.ShopId = s.ShopId AND p.ProductName LIKE '%christmas%'
) a where a.rn <= 5
1 голос
/ 27 июля 2013

Вот отличное решение, которое я только что нашел.

Выберите TOP n строк для каждой группы Арни Роуланд, 13 марта 2008 г.

Есть несколько строк для каждой категории, и есть желание ВЫБЕРИТЕ ТОЛЬКО две верхние (2) строки в каждой категории по цене. Например, из следующих данных:

RowID    Category    ID  Description     Price
1    Pot     A1  Small Saucepan  21.50
2    Pot     A2  1 Qt Saucepan   29.95
3    Pot     A3  1.5 Qt Saucepan     33.95
4    Pot     A4  Double Boiler   39.50
5    Pot     A5  Stewpot     49.50
6    Pot     A6  Pressure Cooker     79.95
7    Pan     B1  8" Pie  6.95
8    Pan     B2  8" Sq Cake  7.50
9    Pan     B3  Bundt Cake  12.50
10   Pan     B4  9x12 Brownie    7.95
11   Bowl    C1  Lg Mixing   27.50
12   Bowl    C2  Sm Mixing   17.50
13   Tools   T1  14" Spatula     9.95

Желаемый вывод:

RowID    Category    ID  Description     Price
11   Bowl    C1  Lg Mixing   27.50
12   Bowl    C2  Sm Mixing   17.50
9    Pan     B3  Bundt Cake  12.50
10   Pan     B4  9x12 Brownie    7.95
6    Pot     A6  Pressure Cooker     79.95
5    Pot     A5  Stewpot     49.50
13   Tools   T1  14" Spatula     9.95

Есть несколько методов для достижения желаемого результата. Эта демонстрация предоставляет решение для SQL Server 2005 / SQL Server 2008, а затем решение для SQL Server 2000.

Создание примера данных для обоих решений

-- Suppress data loading messages
SET NOCOUNT ON

-- Create Sample Data using a Table Varable
DECLARE @MyTable table
   (  RowID         int   IDENTITY, 
      Category      varchar(5),
      [ID]          varchar(5),
      [Description] varchar(25),
      Price         decimal(10,2)
   )

-- Load Sample Data

INSERT INTO @MyTable VALUES ( 'Pot', 'A1', 'Small Saucepan', 21.50 )
INSERT INTO @MyTable VALUES ( 'Pot', 'A2', '1 Qt Saucepan', 29.95 )
INSERT INTO @MyTable VALUES ( 'Pot', 'A3', '1.5 Qt Saucepan', 33.95 )
INSERT INTO @MyTable VALUES ( 'Pot', 'A4', 'Double Boiler', 39.50 )
INSERT INTO @MyTable VALUES ( 'Pot', 'A5', 'Stewpot', 49.50 )
INSERT INTO @MyTable VALUES ( 'Pot', 'A6', 'Pressure Cooker', 79.95 )
INSERT INTO @MyTable VALUES ( 'Pan', 'B1', '8"" Pie', 6.95 )
INSERT INTO @MyTable VALUES ( 'Pan', 'B2', '8"" Sq Cake', 7.50 )
INSERT INTO @MyTable VALUES ( 'Pan', 'B3', 'Bundt Cake', 12.50 )
INSERT INTO @MyTable VALUES ( 'Pan', 'B4', '9x12 Brownie', 7.95 )
INSERT INTO @MyTable VALUES ( 'Bowl', 'C1', 'Lg Mixing', 27.50 )
INSERT INTO @MyTable VALUES ( 'Bowl', 'C2', 'Sm Mixing', 17.50 )
INSERT INTO @MyTable VALUES ( 'Tools', 'T1', '14"" Spatula', 9.95 )
Return to Top

SQL Server 2005 / SQL Server 2008 Solution

--Query to Retrieve Desired Data
SELECT
   RowID,
   Category,
   [ID],
   [Description],
   Price
FROM (SELECT
         ROW_NUMBER() OVER ( PARTITION BY Category ORDER BY Price DESC ) AS 'RowNumber',
         RowID,
         Category,
         [ID],
         [Description],
         Price
      FROM @MyTable
      ) dt
WHERE RowNumber <= 2

-- Results
RowID Category  ID Description     Price
11    Bowl      C1 Lg Mixing       27.50
12    Bowl      C2 Sm Mixing       17.50
9     Pan       B3 Bundt Cake      12.50
10    Pan       B4 9x12 Brownie    7.95
6     Pot       A6 Pressure Cooker 79.95
5     Pot       A5 Stewpot         49.50
13    Tools     T1 14" Spatula     9.95
Return to Top

SQL Server 2005 / SQL Server 2008 Solution с использованием CTE (Добавлено: Джейкоб Себастьян)

-- Define a CTE with the name "dt" 
;WITH dt AS (
     SELECT
         ROW_NUMBER() OVER ( PARTITION BY Category ORDER BY Price DESC ) AS 'RowNumber',
         RowID,
         Category,
         [ID],
         [Description],
         Price
      FROM @MyTable
)
-- and select the data from the CTE
SELECT
   RowID,
   Category,
   [ID],
   [Description],
   Price
FROM dt
WHERE RowNumber <= 2

-- Results
RowID Category  ID Description     Price
11    Bowl      C1 Lg Mixing       27.50
12    Bowl      C2 Sm Mixing       17.50
9     Pan       B3 Bundt Cake      12.50
10    Pan       B4 9x12 Brownie    7.95
6     Pot       A6 Pressure Cooker 79.95
5     Pot       A5 Stewpot         49.50
13    Tools     T1 14" Spatula     9.95
Return to Top

Решение SQL 2000

--Query to Retrieve Desired Data
SELECT DISTINCT
   RowID,
   Category,
   [ID],
   [Description],
   Price
FROM @MyTable t1
WHERE RowID IN (SELECT TOP 2
                   RowID
                FROM @MyTable t2
                WHERE t2.Category = t1.Category
                ORDER BY Price DESC
               )
ORDER BY 
   Category,
   Price DESC

-- Results
RowID Category  ID Description     Price
11    Bowl      C1 Lg Mixing       27.50
12    Bowl      C2 Sm Mixing       17.50
9     Pan       B3 Bundt Cake      12.50
10    Pan       B4 9x12 Brownie    7.95
6     Pot       A6 Pressure Cooker 79.95
5     Pot       A5 Stewpot         49.50
13    Tools     T1 14" Spatula     9.95

От: Выберите TOP n строк для каждой группы

1 голос
/ 08 июня 2011

Попробуйте это

SELECT DISTINCT 
        A.Product_Group_code
        ,B.Sub_Product_Group_code
        ,A.Product_code
        ,A.Product_name
FROM dbo.A A
    LEFT JOIN dbo.B B
        ON A.Product_code = B.Product_code
WHERE  B.Product_code IN
                (
                    SELECT TOP 5 E.Product_code
                    FROM dbo.A D
                        LEFT JOIN dbo.B E
                            ON D.Product_code = E.Product_code
                    WHERE E.Sub_Product_Group_code = B.Sub_Product_Group_code
                )
        AND B.Sub_Product_Group_code IS NOT NULL
ORDER BY B.Sub_Product_Group_code,A.Product_name
...