Полу-хитрый SQL-запрос - PullRequest
       5

Полу-хитрый SQL-запрос

5 голосов
/ 22 октября 2008

Я пытаюсь написать запрос для SQL Server 2005, но не могу понять, как это сделать. У меня есть таблица со следующими полями:

MessageID int
CategoryID int
Приоритет tinyint
MessageText NVARCHAR (MAX)

Мне нужен запрос, который будет возвращать * для каждой строки, имеющей наивысший приоритет в категории. Например, если у меня были следующие данные:

MessageID, CategoryID, Priority, MessageText
1, 100, 1, ошибка № 1234 произошла
2, 100, 2, ошибка № 243 произошла
3, 100, 3, ошибка № 976 произошла
4, 200, 4, ошибка № 194 произошла
5, 200, 1, ошибка № 736 произошла
6, 300, 3, ошибка № 54 произошла
7, 300, 2, ошибка № 888 произошла

тогда результат будет:

MessageID, CategoryID, Priority, MessageText
3, 100, 3, ошибка № 976 произошла
4, 200, 4, ошибка № 194 произошла
6, 300, 3, ошибка № 54 произошла

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

Может кто-нибудь сказать мне, как я могу написать этот запрос?

Ответы [ 8 ]

6 голосов
/ 22 октября 2008

Проверено:

SELECT
    highest_priority_messages.*
FROM
(
    SELECT
    m.MessageID
    , m.CategoryID
    , m.Priority
    , m.MessageText
    , Rank() OVER 
        (PARTITION BY m.CategoryID ORDER BY m.Priority DESC) AS p_rank
    FROM [Message] m
    GROUP BY 
        m.CategoryID 
        , m.Priority
        , m.MessageID
        , m.MessageText
) highest_priority_messages
WHERE 
    p_rank = 1
1 голос
/ 23 октября 2010
select distinct query1.* from

(select categoryId,msgText,max(priorityId) as MAX_PRIORITY
 from message
  group by categoryId,msgText
 order by categoryId
) query1,


(select categoryId,max(priorityId) as MAX_PRIORITY
 from message
  group by categoryId
 order by categoryId
) query2

where query1.MAX_PRIORITY = query2.MAX_PRIORITY

order by query1.categoryId
1 голос
/ 23 октября 2008

Если вы хотите сделать это без всех подзапросов:

SELECT
     MessageID,
     CategoryID,
     Priority,
     MessageText
FROM
     dbo.Messages M1
LEFT OUTER JOIN dbo.Messages M2 ON
     M2.CategoryID = M1.CategoryID AND
     M2.Priority > M1.Priority
WHERE
     M2.MessageID IS NULL

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

1 голос
/ 22 октября 2008

Я считаю, что это должно работать, имя таблицы принимается как Сообщения

SELECT
    M.MessageId,
    M.CategoryId,
    M.Priority,
    M.MessageText
FROM 
(
    SELECT 
        CategoryId,
        MAX(Priority) AS Priority
    FROM Messages
    GROUP BY CategoryId
) AS MaxValues
    INNER JOIN Messages M
        ON (MaxValues.CategoryId = M.CategoryId
                AND MaxValues.Priority = M.Priority)

Примечание

Единственная «ошибка» в этом методе заключается в том, что если у вас более одного максимального приоритета ...

0 голосов
/ 15 ноября 2011
SELECT DISTINCT CategoryId,PS.Priority,MessageID,MessageText
FROM Priority_Scene PS
JOIN (SELECT MAX(Priority) AS Priority FROM Priority_Scene GROUP BY CategoryId) A
ON A.Priority   = PS.Priority
0 голосов
/ 23 октября 2008

У меня недостаточно высокий рейтинг (пока), чтобы оставлять комментарии, поэтому я хотел бы добавить к решению cfeduke:

SELECT
    highest_priority_messages.*
FROM
(
    SELECT
    m.MessageID
    , m.CategoryID
    , m.Priority
    , m.MessageText
    , Rank() OVER 
        (PARTITION BY m.CategoryID ORDER BY m.Priority DESC, m.MessageID DESC) AS p_rank
    FROM [Message] m
    GROUP BY 
        m.CategoryID 
        , m.Priority
        , m.MessageID
        , m.MessageText
) highest_priority_messages
WHERE 
    p_rank = 1

Если вы добавите еще одно сообщение CategoryID 100 с приоритетом 3, исходное решение вернет 2 строки, добавив еще одно условие заказа, и мы исключим вероятность того, что два элемента ранжируются одинаково.

Вот копия строки, которую я вставил, чтобы проверить это.

insert into [Message] (MessageID, CategoryID, Priority, MessageText)
select 8, 100, 3, 'Error #976-2 occurred'
0 голосов
/ 22 октября 2008

Это короче и легче для чтения (imo).

select ms.*
from 
  messages ms
 ,(
  select ms1.categoryid, max(ms1.priority) as max_priority
  from messages ms1
  group by ms1.categoryid
  ) tmp
where ms.categoryid = tmp.categoryid
  and ms.priority = tmp.max_priority;
0 голосов
/ 22 октября 2008
SELECT
    Messages.MessageID
    , Messages.CategoryID
    , Messages.Priority
    , Messages. MessageText
FROM
    Messages
    INNER JOIN
    (
        SELECT 
            CategoryID
            , MAX(Priority) AS Priority
        FROM 
            Messages
        GROUP BY
            CategoryID
    ) AS MaxResults
    ON
        (
            Messages.CategoryID = MaxResults.CategoryID
            AND
            Messages.Priority = MaxResults.Priority
        )

Похоже, это в основном тот же ответ, который дан выше ... с тем же предостережением.

Хотя этот сработает сразу.

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