I have this table
select * from points
+---------+------+------+
| NAME | Type | RANK |
+---------+------+------+
| A | H | 90 |
| A | M | 100 |
| A | H | N/A |
| A | H | N/A |
| A | H | N/A |
| B | H | 100 |
| B | M | 100 |
| B | L | 100 |
| C | H | 85 |
| C | M | 100 |
+---------+------+------+
I’m using this query
SELECT name,
CAST(
( -- only have H, or only have M, or only have L:
CASE WHEN `# of H` = 0 AND `# of M` = 0 THEN 100 * `# of active L` / `# of L`
WHEN `# of H` = 0 AND `# of L` = 0 THEN 100 * `# of active M` / `# of M`
WHEN `# of M` = 0 AND `# of L` = 0 THEN 100 * `# of active H` / `# of H`
-- only have H & M, or only have H & L, or only have M & L:
WHEN `# of H` = 0 THEN 60 * `# of active M` / `# of M` + 40 * `# of active L` / `# of L`
WHEN `# of M` = 0 THEN 90 * `# of active H` / `# of H` + 20 * `# of active L` / `# of L`
WHEN `# of L` = 0 THEN 80 * `# of active H` / `# of H` + 20 * `# of active M` / `# of M`
-- have all three:
ELSE 70 * `# of active H` / `# of H` + 20 * `# of active M` / `# of M` + 10 * `# of active L` / `# of L`
END
) AS SIGNED ) AS score
FROM ( SELECT name,
SUM(IF( type = 'H', 1, 0)) AS `# of H`,
SUM(IF(rank AND type = 'H', 1, 0)) AS `# of active H`,
SUM(IF( type = 'M', 1, 0)) AS `# of M`,
SUM(IF(rank AND type = 'M', 1, 0)) AS `# of active M`,
SUM(IF( type = 'L', 1, 0)) AS `# of L`,
SUM(IF(rank AND type = 'L', 1, 0)) AS `# of active L`
FROM points
GROUP BY name
) t
ORDER
BY name
;
I get this Output
+---------+-------+
| NAME | SCORE |
+---------+-------+
| A | 60 | <--[(2xH)=40 + (1xM)=20] =60
| B | 100 | <--[(1xH)=70 + (1xM)=20 + (1xL)=10] =100
| C | 100 | <--[(1xH)=80 + (1xM)=20] =100
+---------+-------+
I need this Desired output
+---------+-------+
| NAME | SCORE |
+---------+-------+
| A | 36 | <--[70/4=(17.5 per H) therefore (17.5)*(rank of that h: 90%)=15.75 + (M values, which equals 20/1 =20 Therefore: rank of that m:100% * 20 = 100) = 36 rounded
| B | 100 | <--[(1xH)=70 + (1xM)=20 + (1xL)=10] =100
| C | 88 | <--[(1xH)=80 + (1xM)=20] =100
+---------+-------+
Computations required:
- Type can have only three values: {H, M, L};
-
When all values are present, they are graded as followed:
H=70 M=20 L=10
-
If an name has more than one kind of Type (H, M, or L) then points are distributed as followed:
-
H/(number of H) ; M/(number of M); L/(number of L)
— Example: A has 4 H therefore 70 / 4 = 17.5 for each H
-
But some names have a complete set with out having all ‘Types.
— example : C has Type values: ‘H&M` only -
Now Type ‘H’ and ‘M’ have to equal 100 for C.
So when only ‘H` and ‘M’ are present they are graded as followed:
H=80 M=20
- Equally if another animal comes along with only two Type values M & L they will be graded as followed:
M=60 L=40
- Equally if another animal comes along with only two Type values H & L they will be graded as followed:
H=90 L=10
And also
-
if only H is presnet H=100
-
if only M is presnet M=100
-
if only L is presnet L=100
This looks familiar. 🙂
Your description is inconsistent in a number of places — for example, your “desired output” for
Auses70and20, even though noAs have typeL— but if you mean what I think you do, then the main change you need is to changeSUM(IF(rank AND type = 'H', 1, 0)) AS `# of active H`toSUM(IF(type = 'H', rank / 100.0, 0)) AS `rank of H`(and likewise forMandL), and change all references to`# of active H`to refer to`rank of H`instead. This way each record will be included in proportion to its rank, rather than being an all-or-nothing thing.You’ll also want to use
ROUNDinstead ofCAST— or in addition toCAST— when converting yourscoreto an integer.