別のSOの質問に答えようとしていたところ、突然次の問題に直面しました。ポイントは、各クラス ( ) の最高得点 ( mrk
) の 3 つのグループ ( ) に割り当てる必要があります。最高得点のグループは 5 ポイント、2 位のグループは 3 ポイント、3 位のグループは 1 ポイントを獲得します。その他はすべてに設定する必要があります。grp
sec
pts
null
| ID | SEC | GRP | MRK | PTS |
|----|-----|-----|-----|--------|
| 1 | cl2 | ge | 32 | (null) |
| 2 | cl1 | gb | 22 | (null) |
| 3 | cl1 | gd | 22 | (null) |
| 4 | cl1 | ge | 18 | (null) |
| 5 | cl2 | ga | 26 | (null) |
| 6 | cl1 | ga | 55 | (null) |
| 7 | cl2 | gb | 66 | (null) |
| 8 | cl2 | gc | 15 | (null) |
| 9 | cl1 | gc | 12 | (null) |
| 10 | cl2 | gf | 5 | (null) |
| 11 | cl2 | ge | 66 | (null) |
割り当てスキームに関して最大限の柔軟性を提供するユーザー定義変数を使用することを選択し、すぐに次の解決策を思いつきました。
SELECT id,sec,grp,mrk,
CASE WHEN @s=sec THEN -- whenever there is a new class ...
CASE WHEN @m=mrk THEN @i ELSE -- issue the same points for
-- identical scorers, otherwise ...
CASE WHEN IF(@m:=mrk,@i,@i)>2 THEN @i:=@i-2 -- store mrk in @mrk and
-- while @i>2 return points: 3 or 1 ...
ELSE @i:=null -- no points for the rest
END
END
ELSE NULLIF(@i:=5,(@s:=sec)=(@m:=mrk)) -- store sec in @s and mrk in @m
-- and return points: 5
END pts
FROM tbl ORDER BY sec,mrk desc
の説明NULLIF(@i:=5,(@s:=sec)=(@m:=mrk))
:
式@s:=sec
と@m:=mrk
の両方が評価され、それらの値が によって比較され=
ます。結果は0
(false) または(true) のいずれかになりますが、関数のもう 1 つの引数である とは1
明らかに等しくないため、最終的には最初の引数 ( ) のみが返されます。何も返さずに 2 つの変数の割り当てが行われるように構成を選択しました。5
NULLIF
5
OK、おそらく最も簡単な解決策ではないかもしれません;-)、しかし、「ユーザー変数を含む式の評価の順序は定義されていない」ため、処理中のレコードごとに各変数を1回だけ定義するように注意を払いました. 確かに私に希望を与えますselect
結果:
| ID | SEC | GRP | MRK | PTS |
|----|-----|-----|-----|--------|
| 6 | cl1 | ga | 55 | 5 |
| 2 | cl1 | gb | 22 | 3 |
| 3 | cl1 | gd | 22 | 3 |
| 4 | cl1 | ge | 18 | 1 |
| 9 | cl1 | gc | 12 | (null) |
| 7 | cl2 | gb | 66 | 5 |
| 11 | cl2 | ge | 66 | 5 |
| 1 | cl2 | ge | 32 | 3 |
| 5 | cl2 | ga | 26 | 1 |
| 8 | cl2 | gc | 15 | (null) |
| 10 | cl2 | gf | 5 | (null) |
さて、私の質問は次のとおりです。
UPDATE
上記の計算結果を列に格納する同じ行に沿ってステートメントを作成するにはどうすればよいpts
ですか?
これまでの私の試みはすべて失敗しました:
UPDATE tbl SET pts=
CASE WHEN @s=sec THEN
CASE WHEN @m=mrk THEN @i ELSE
CASE WHEN IF(@m:=mrk,@i,@i)>2 THEN @i:=@i-2
ELSE @i:=null
END
END
ELSE NULLIF(@i:=5,(@s:=sec)=(@m:=mrk))
END
ORDER BY sec,mrk desc
結果:
| ID | SEC | GRP | MRK | PTS |
|----|-----|-----|-----|-----|
| 6 | cl1 | ga | 55 | 5 |
| 2 | cl1 | gb | 22 | 5 |
| 3 | cl1 | gd | 22 | 5 |
| 4 | cl1 | ge | 18 | 5 |
| 9 | cl1 | gc | 12 | 5 |
| 7 | cl2 | gb | 66 | 5 |
| 11 | cl2 | ge | 66 | 5 |
| 1 | cl2 | ge | 32 | 5 |
| 5 | cl2 | ga | 26 | 5 |
| 8 | cl2 | gc | 15 | 5 |
| 10 | cl2 | gf | 5 | 5 |
update ステートメントが pts に対して単一の値 (5) しか取得しないのはなぜですか?!?
私のSQLfiddleですべてのデータと SQL ステートメントを見つけることができます。