SQL DEMO
Сначала с пользовательскими переменными вам нужно создать rn, чтобы получить топ-3 для каждого type
и ref
SELECT t.*, @rn := if( @ref = `wsf_ref`,
if ( @type = `type`,
@rn + 1,
if( @type := `type`, 1, 1)
),
if ( (@ref := `wsf_ref`) or (@type := `type`), 1, 1)
) as rn,
@type,
@ref
FROM t
CROSS JOIN ( SELECT @rn := 0, @type := '', @ref := '') as var
ORDER BY `wsf_ref`, `type`, `wsf_value` DESC ;
Частичный результат
| id | wsf_ref | status | type | wsf_progress | wsf_value | rn | @type | @ref |
|----|---------|----------|--------|--------------|-----------|----|--------|------|
| 6 | 1 | Approved | blue | Day 1 | 25 | 1 | blue | 1 |
| 5 | 1 | Approved | blue | Day 1 | 10 | 2 | blue | 1 |
| 3 | 1 | Approved | orange | Day 1 | 20 | 1 | orange | 1 |
| 2 | 1 | Approved | orange | Day 1 | 10 | 2 | orange | 1 |
| 4 | 1 | Approved | orange | Day 1 | 10 | 3 | orange | 1 |
| 1 | 1 | Approved | orange | Day 1 | 5 | 4 | orange | 1 |
| 17 | 2 | Approved | blue | Day 1 | 50 | 1 | blue | 2 |
| 16 | 2 | Approved | blue | Day 1 | 35 | 2 | blue | 2 |
| 15 | 2 | Approved | blue | Day 1 | 20 | 3 | blue | 2 |
| 14 | 2 | Approved | orange | Day 1 | 40 | 1 | orange | 2 |
| 12 | 2 | Approved | orange | Day 1 | 20 | 2 | orange | 2 |
| 13 | 2 | Approved | orange | Day 1 | 15 | 3 | orange | 2 |
| 11 | 2 | Approved | orange | Day 1 | 10 | 4 | orange | 2 |
| 9 | 2 | Approved | red | Day 1 | 30 | 1 | red | 2 |
| 10 | 2 | Approved | red | Day 1 | 20 | 2 | red | 2 |
| 8 | 2 | Approved | red | Day 1 | 20 | 3 | red | 2 |
| 7 | 2 | Approved | red | Day 1 | 10 | 4 | red | 2 |
Тогда используйте условное SUM
SELECT wsf_ref, SUM( CASE WHEN type = 'blue' and rn = 1
THEN `wsf_value`
WHEN type <> 'blue' and rn in (1,2,3)
THEN `wsf_value`
ELSE 0
END
) as sum_total
FROM (
SELECT t.*, @rn := if( @ref = `wsf_ref`,
if ( @type = `type`,
@rn + 1,
if( @type := `type`, 1, 1)
),
if ( (@ref := `wsf_ref`) and (@type := `type`), 1, 1)
) as rn,
@type,
@ref
FROM t
CROSS JOIN ( SELECT @rn := 0, @type := '', @ref := '') as var
ORDER BY `wsf_ref`, `type`, `wsf_value` DESC
) t
GROUP BY `wsf_ref
ВЫХОД
| wsf_ref | sum_total |
|---------|-----------|
| 1 | 65 |
| 2 | 195 |
EDIT:
После расспросов у меня появилась более простая версия:
Какое логическое значение возвращает целое число или строку переменной
DEMO
SELECT t.*,
(@rn := if(@tr = CONCAT_WS(':', wsf_ref, type),
@rn + 1,
if(@tr := CONCAT_WS(':', wsf_ref, type), 1, 1
)
)
) as rn
FROM (SELECT t.*
FROM t
ORDER BY `wsf_ref`, `type`, `wsf_value` DESC
) t CROSS JOIN
(SELECT @rn := 0, @tr := '') params;