2016-09-22 136 views
3

我有一個用戶獎勵表,它可以是各種不同的類型。SQL或子句優先級

例如,這裏有資質ID 94的記錄:

因此,大家可以看到,有2個用戶,一個有記錄的獎勵類型的「平均」,「分鐘「,」最大「和」最終「,另一個具有相同但沒有」最終「獎。

我想要的是每個用戶只得到1行。如果他們有「最終」類型的獎項,那麼我想要的是「平均」,我根本不需要「最小」或「最大」。

因此,作爲一個例子,這裏只是一個簡單的查詢IN子句:

enter image description here

所以此基礎上,我想要得到的結果是爲用戶34562我想要的行獲得「最終」獎項,對於用戶6256,我希望該行獲得「平均」獎,因爲他們沒有「最終」記錄。

我相信這應該是相當簡單的,但我今天早上悲慘地失敗。

我想我應該可以選擇最終的記錄,然後做一個聯盟,但我似乎無法在我的腦海中解決它。任何人都可以將我指向正確的方向嗎?

我應該指出,雖然這對我來說是MySQL,但它需要與其他數據庫平臺兼容。

謝謝。

+0

做一個GROUP BY,用例表達式來做條件聚合。 – jarlh

+0

你能否快速測試我的查詢來查看它是否有效。如果沒有,我會刪除它。 –

回答

2

一個簡單的方法是檢查是否在where子句中存在的平均條目:

SELECT * FROM Table t 
WHERE qualid = 94 
and (type = 'average' AND 
    not exists(SELECT * FROM Table t2 
     WHERE t.qualid=t2.qualid AND t.userid=t2.userid AND type = 'final') 
    OR type = 'final') 
+0

感謝,似乎是最簡單的方法。我早些時候嘗試過,但似乎無法得到不存在的查詢很正確。 –

+1

順便說一下,如果你想改變未來的觀衆,你有一個錯字,你把「不存在」,而不是「不存在」,而不是「存在」。 –

0

您可以使用MySQL user defined variables來實現這個功能,這將更具可擴展性。

SELECT 
t.* 
FROM 
(
    SELECT 
    *, 
    IF(@sameUser = userid, @rn := @rn + 1, 
     IF(@sameUser := userid, @rn := 1,@rn := 1) 
    ) AS row_number 
    FROM moodle.mdl_bcgt_user_qual_awards 
    CROSS JOIN (SELECT @sameUser := -1, @rn := 1) AS var 
    WHERE qualid = 94 
    AND type IN ('final','average') 
    ORDER BY userid, 
     CASE WHEN type = 'final' THEN 0 ELSE 1 END 
) AS t 
WHERE t.row_number <= 1 
ORDER BY t.userid 

編輯:使用

NOT EXISTS & UNION ALL

SELECT 
* 
FROM your_table 
WHERE qualid = 94 
AND type = 'final' 

UNION ALL 

SELECT 
* 
FROM your_table A 
WHERE qualid = 94 
AND type = 'average' 
AND NOT EXISTS (
SELECT 1 FROM your_table B WHERE A.qualid = B.qualid AND B.userid = A.userid AND B.type = 'final' 
) 
+0

這不會與其他數據庫引擎不兼容嗎?我們在這裏使用MySQL,但該軟件還支持PostgreSQL,SQL Server等,所以一些使用它的地方不會在MySQL上。 –

+0

然後你可以嘗試其他查詢 – 1000111

+0

是的,也許@TimBiegeleisen – 1000111

0

這裏是一個純的MySQL溶液,這也應該是通常符合ANSI在大多數RDBMS:

SELECT t1.* 
FROM yourTable t1 
INNER JOIN 
(
    SELECT qualid, 
      CASE WHEN MAX(CASE WHEN type = 'final' THEN 100 
           WHEN type = 'average' THEN 10 
           ELSE 1 
         END) = 100 THEN 'final' 
       WHEN MAX(CASE WHEN type = 'final' THEN 100 
           WHEN type = 'average' THEN 10 
           ELSE 1 
         END) = 10 THEN 'average' 
       ELSE NULL 
      END AS type 
    FROM yourTable 
    GROUP BY qualid 
) t2 
    ON t1.qualid = t2.qualid AND 
     t1.type = t2.type 

該查詢採用了一種技巧,根據是否存在finalaverage或兩者都不存在,爲每個qualid組合計總和。我爲final,10分配100的值爲average1。這使我們可以爲每個組分配一個type

+0

嗨,不,它似乎不工作很正確,我現在接受了其他人的答案,所以不用擔心 –

+0

@ConnWarwicker對不起,我在那裏有一個拼寫錯誤,現在起作用。 –

0

你可以試試這個爲SQL Server

Select * from (
    SELECT *,ROW_NUMBER() over(PARTITION BY type ORDER BY type) rowNo 
    FROM mdl_bcgt_user_qual_awards 
    WHERE qualid = 94 
    AND type in ('final','average') 
    Order By type 
) as t 
Where rowNo=1 

聽,我們通過對類型來完成訂單因爲角色符合我們的要求,如果有任何其他文本,那麼只要在該領域的基礎上添加案例和排序。