2016-09-22 89 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 

听,我们通过对类型来完成订单因为角色符合我们的要求,如果有任何其他文本,那么只要在该领域的基础上添加案例和排序。