2008-10-22 5 views
5

Tôi đang cố viết truy vấn cho SQL Server 2005 nhưng tôi không thể tìm ra cách thực hiện. Tôi có một bảng với các lĩnh vực sau:Truy vấn SQL bán khó hiểu

MessageID int
CategoryID int
tinyint ưu tiên
messagetext NVARCHAR (MAX)

Tôi cần một truy vấn mà sẽ trở lại * cho mỗi hàng có ưu tiên cao nhất trong Danh mục. Ví dụ, nếu tôi có các dữ liệu sau:

MessageID, CategoryID, ưu tiên, messagetext
1, 100, 1, Lỗi # 1234 xảy ra
2, 100, 2, Lỗi # 243 xảy ra
3 , 100, 3, Lỗi # 976 xảy ra
4, 200, 4, Lỗi # 194 xảy ra
5, 200, 1, Lỗi # 736 xảy ra
6, 300, 3, Lỗi # 54 xảy ra
7, 300 , 2, Lỗi # 888 xảy ra

thì kết quả sẽ là:

MessageID, CategoryID, ưu tiên, messagetext
3, 100, 3, Lỗi # 976 xảy ra
4, 200, 4, Lỗi # 194 xảy ra
6, 300, 3, Lỗi số 54 xảy ra

Lưu ý rằng nó trả về một hàng cho mỗi danh mục và là hàng có mức độ ưu tiên cao nhất cho Danh mục đó.

Có ai có thể cho tôi biết cách tôi có thể viết truy vấn này không?

+0

Bạn có thể viết nó xa dễ dàng hơn bằng chức năng phân tích trong Oracle. :) – TheSoftwareJedi

+0

Hoặc sử dụng các chức năng phân tích trong SQL Server và không phải chuyển sang Oracle. – cfeduke

Trả lời

6

xác minh:

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 
+0

Bạn cũng sẽ muốn thêm một CreatedDate và hình vào phương trình để đặt hàng tôi chắc chắn. – cfeduke

+0

Bạn có chắc chắn không có cách nào để sử dụng PARTITION tại đây mà không sử dụng Xếp hạng()? – skb

+0

Bạn có thể làm MAX (m.Priority) OVER (PARTITION BY m.CategoryID) AS MaxPriority, nhưng sau đó WHERE sẽ phải so sánh mức độ ưu tiên với MaxPriority. Nó cũng phụ thuộc vào việc bạn muốn bội số của ưu tiên hàng đầu hay không. –

1

Tôi tin rằng điều này sẽ làm việc, tên bảng giả định là tin nhắn

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) 

LƯU Ý

duy nhất "Gotcha" trong phương pháp này là nếu bạn có nhiều hơn một ưu tiên tối đa .. .

0
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 
     ) 

Dường như đây về cơ bản là cùng một câu trả lời được đưa ra ở trên ... với cùng một Caveat.

Mặc dù cái này sẽ hoạt động ngay lập tức.

+0

Chà, tôi không nhận thấy rằng bí danh của tôi bị tước đi .... –

0

Đây là ngắn hơn và dễ đọc hơn (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; 
1

Nếu bạn muốn làm điều đó mà không cần tất cả các truy vấn con:

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 

Bạn có thể phải điều chỉnh truy vấn tùy thuộc vào cách bạn muốn xử lý các mối quan hệ. Bạn không có bất kỳ ví dụ như vậy, vì vậy tôi đã không chắc chắn.

0

Tôi không phải là đủ thứ hạng khá cao (chưa) để viết bình luận, vì vậy tôi muốn thêm vào của cfeduke giải pháp:

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 

Nếu bạn thêm một CategoryID 100 tin nhắn với ưu tiên 3, giải pháp ban đầu sẽ mang lại 2 hàng, bằng cách thêm điều kiện thứ tự khác, chúng tôi loại bỏ cơ hội của hai mục xếp hạng giống nhau.

Đây là bản sao của hàng mà tôi đã chèn để kiểm tra điều này.

insert into [Message] (MessageID, CategoryID, Priority, MessageText) 
select 8, 100, 3, 'Error #976-2 occurred' 
1
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 
0
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 
+1

Nếu cùng danh mục có hai mức độ ưu tiên trên cùng cấp độ và mức cao nhất thì nó cũng sẽ hoạt động – Kamy