2012-06-26 41 views
3

我有一個表,看起來像這樣複雜或者可能排序問題

Group Recipe Priority 
0  A   400 
0  A   200 
0  B   500 
0  B   100 
1  C   300 
1  C   300 
1  D   600 

重要性「由序」是「集團」>「優先級」>「配方」

0組已去第一。 在第0組中,優先級500必須先執行(因爲優先級較高),但爲了提高效率,所有配方必須先執行。

排序後, 它應該是這樣的

Group Recipe Priority 
0  B   500 
0  B   100 
0  A   400 
0  A   200 
1  D   600 
1  C   300 
1  C   300 

我已經嘗試了所有不同的方式「按訂單」的事,但找不到正確的方法。

感謝您的幫助

+2

順便說一句,'group'是一個列的_bad_名稱,如果可能的話儘量避免保留字。 – Ben

+0

@我們的評論是不正確的。以配方asc爲例,前兩行是相反的。 –

回答

12

問題是微妙的。您希望不按優先順序排序,而是按給定組/配方組合的最大優先順序排序。也就是說,您希望根據這個最大優先級將所有配方保持在一起。

下做到這一點:有可用的分析功能

select t.Group, t.Recipe, t.Priority, 
     max(priority) over (partition by t.group, t.recipe) as maxpriority 
from tablename t 
order by t.Group asc, 4 desc, t.Recipe, priority desc 
+0

你的意思是'按t.Group asc排序,4 desc,t.Recipe,maxpriority desc' –

+0

@MoslemBenDhaou。 。 。 'order by'的第二部分按最大優先級進行排序。 –

2

在舊版本的Oracle,之前,我們將返回使用查詢像這樣指定的結果集:

SELECT f.group 
    , f.recipe 
    , f.priority 
    FROM foo f 
    JOIN (SELECT g.group 
       , g.recipe 
       , MAX(g.priority) AS max_priority 
      FROM foo g 
      GROUP BY g.group, g.recipe 
     ) m 
    ON m.group = f.group AND m.recipe = f.recipe 
ORDER BY f.group 
     , m.max_priority DESC 
     , f.recipe 
     , f.priority DESC 

這種方法適用於沒有分析功能的其他數據庫,如MySQL。

注意:上面的查詢不是NULL安全的,因爲JOIN謂詞將消除組或配方列具有NULL值的行。它可以做成NULL安全的,但它使SQL複雜一點。

SELECT f.group 
    , f.recipe 
    , f.priority 
    FROM foo f 
    JOIN (SELECT g.group 
       , g.recipe 
       , MAX(g.priority) AS max_priority 
      FROM foo g 
      GROUP BY g.group, g.recipe 
     ) m 
    ON (m.group = f.group OR COALESCE(m.group,f.group) IS NULL) 
     AND (m.recipe = f.recipe OR COALESCE(m.recipe,f.recipe) IS NULL) 
ORDER BY f.group 
     , m.max_priority DESC 
     , f.recipe 
     , f.priority DESC 

的等效結果也可以在SELECT列表使用相關子查詢獲得的,除了該結果集包含在結果集中一個額外的「MAX_PRIORITY」列。

SELECT f.group 
    , f.recipe 
    , f.priority 
    , (SELECT MAX(g.priority) 
      FROM foo g 
     WHERE (g.group = f.group OR COALESCE(g.group,f.group) IS NULL) 
      AND (g.recipe = f.recipe OR COALESCE(g.recipe,f.recipe) IS NULL) 
     ) AS max_priority 
    FROM foo f 
ORDER BY f.group 
     , 4 DESC 
     , f.recipe 
     , f.priority DESC 

(我沒有測試是否是相關子查詢可從SELECT列表中刪除,並完全轉移到ORDER BY子句。如果這樣的工作,我們會消除返回額外的列,但該查詢看起來真的很奇怪。)另一種選擇(省略額外的列)是將此查詢(作爲內嵌視圖)封裝在另一個查詢中。

SELECT e.group 
    , e.recipe 
    , e.priority 
    FROM (
     SELECT f.group 
      , f.recipe 
      , f.priority 
      , (SELECT MAX(g.priority) 
        FROM foo g 
       WHERE (g.group = f.group OR COALESCE(g.group,f.group) IS NULL) 
        AND (g.recipe = f.recipe OR COALESCE(g.recipe,f.recipe) IS NULL) 
       ) AS max_priority 
      FROM foo f 
     ) e 
ORDER BY e.group 
     , e.max_priority DESC 
     , e.recipe 
     , e.priority DESC