Ранжирование перед группировкой проблемы в SQL Server 2005 - PullRequest
1 голос
/ 12 февраля 2010

HI

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

В основном у меня есть 2 таблицы "Категории" и "Предметы"

Категория
ID
CategoryName

Продукты
ID
CategoryID ItemName
Фото
Оценка

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

Итак, я попытался соединить категории с элементами и сгруппировать по CategoryID. Проблема в том, что я хочу упорядочить элементы так, чтобы элементы с наивысшим баллом были наверху, прежде чем они будут группироваться, чтобы убедиться, что фотография относится к текущему элементу с наивысшим баллом в этой категории. Если я выберу MAX (I.score), я смогу получить наивысшую оценку, но я не уверен, как получить сопроводительную фотографию, поскольку MAX (фотография), очевидно, даст мне фотографию с самым высоким именем файла в алфавитном порядке.

Надеюсь, я хорошо это объяснил.

Ответы [ 5 ]

2 голосов
/ 12 февраля 2010

Вы можете попробовать что-то вроде (Полный пример)

DECLARE @Categories TABLE(
    ID INT,
    CategoryName VARCHAR(50)
)

DECLARE @Items TABLE(
    ID INT,
    CategoryID INT,
    ItemName VARCHAR(50),
    Photo VARCHAR(50),
    Score FLOAT
)

INSERT INTO @Categories (ID,CategoryName) SELECT 1, 'Cat1'
INSERT INTO @Categories (ID,CategoryName) SELECT 2, 'Cat2'

INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 1, 1, 'Item1', 'PItem1', 1
INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 2, 1, 'Item2', 'PItem2', 2
INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 3, 1, 'Item3', 'PItem3', 3

INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 4, 2, 'Item4', 'PItem4', 5
INSERT INTO @Items (ID,CategoryID,ItemName,Photo,Score) SELECT 5, 2, 'Item5', 'PItem5', 2

SELECT  *
FROM    (
            SELECT  c.ID,
                    c.CategoryName,
                    i.Photo,
                    i.Score,
                    ROW_NUMBER() OVER(PARTITION BY i.CategoryID ORDER BY i.Score DESC) RowID
            FROM    @Categories c INNER JOIN
                    @Items i ON c.ID = i.CategoryID
        ) CatItems
WHERE   RowID = 1

Используя ROW_NUMBER , вы можете выбрать нужные элементы.

1 голос
/ 12 февраля 2010

Это довольно распространенная проблема, которая не очень хорошо решается SQL Server. Что-то вроде этого должно сработать, хотя:

select
    c.ID,
    c.CategoryName,
    item.*

from Categories c

join (
    select 
        ID, 
        CategoryID, 
        ItemName, 
        Photo, 
        Score, 
        (row_number() over order by CategoryID, Score desc) - 
            (rank() over order by CategoryID) as rownum 

        from Items) item on item.CategoryID = c.CategoryID and item.rownum = 0

Хотя явного предложения group by нет, это (для практических целей) группирует записи Categories и дает оператор join ed, позволяющий просматривать любое свойство элемента с самым высоким показателем.

1 голос
/ 12 февраля 2010

Сначала вам нужно объединиться и присоединиться обратно, как это. (Если вы измените группировку, вам нужно изменить JOIN)

SELECT
 ...
FROM
    (
    select
        max(Score) AS MaxScore,
        CategoryID
    FROM
        Items
    GROUP BY
        CategoryID
    ) M
    JOIN 
    Items I ON M.CategoryID = I.CategoryID AND M.MaxScore = I.Score
    JOIN
    Categories C ON I.CategoryID = C.CategoryID
0 голосов
/ 12 февраля 2010

Точно так, как вы это сформулировали: «Идентификатор категории, название категории и фотография, которая относится к элементу с самым высоким баллом». - Теперь я полагаю, что вы действительно имели в виду «... лучший результат в этой категории», нет?)

  Select CategoryID, c.Categoryname, Photo
  From items i Join Categoiries c
      On c.ID = i.CategoryId
  Where Score = (Select Max(Score) From Items
                 Where CategoryID = i.CategoryId)

Если вы действительно имели в виду самый высокий балл в таблице предметов, просто пропустите предикат в подзапросе

  Select CategoryID, c.Categoryname, Photo
  From items i Join Categoiries c
      On c.ID = i.CategoryId
  Where Score = (Select Max(Score) From Items)

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

0 голосов
/ 12 февраля 2010

Вы можете использовать номера строк для ранжирования элементов по категории:

select *
from (
    select 
        row_number() over (partition by c.id order by i.score desc) rn
    ,    *
    from Categories c
    join Items i on c.ID = i.CategoryID
) sub
where rn = 1

В SQL 2005 нельзя напрямую ссылаться на row_number() в where, поэтому он заключен в подзапрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...