我一直试图编写一个SQL查询,以选择每个用户每种类型的前3名,然后与每种用户另一种类型的前1名求和。如果听起来很复杂,我深表歉意,但我想不出更好的方式来形容它。该查询必须与MySQL 5.x兼容。
我一直在尝试适应以前的查询,但并不高兴。当前已设置为每位用户返回每种类型的前5行,每隔一行将其值1对待。我试图更改一些子句以产生期望的效果,而不会感到高兴。
SELECT
wsf_ref
,sum(wsf_value) as total
from (select
*,
( select count(*)
from individual u
where
t.wsf_ref = u.wsf_ref and
t.type = u.type and
t.wsf_value <= u.wsf_value
) as number
from individual t) t
where (number <= 3 and type <> 'blue' and status = 'Approved' and wsf_progress IN ('Day 1', 'Day 2', 'Day 3'))
or (number = 1 and type = 'blue' and status = 'Approved' and wsf_progress IN ('Day 1', 'Day 2', 'Day 3'))
group by wsf_ref
order by total desc
id wsf_ref status type wsf_progress wsf_value
1 001 Approved orange Day 1 5
2 001 Approved orange Day 1 10 *
3 001 Approved orange Day 1 20 *
4 001 Approved orange Day 1 10 *
5 001 Approved blue Day 1 10
6 001 Approved blue Day 1 25 *
7 002 Approved red Day 1 10
8 002 Approved red Day 1 20 *
9 002 Approved red Day 1 30 *
10 002 Approved red Day 1 20 *
11 002 Approved orange Day 1 10
12 002 Approved orange Day 1 20 *
13 002 Approved orange Day 1 15 *
14 002 Approved orange Day 1 40 *
15 002 Approved blue Day 1 20
16 002 Approved blue Day 1 35
17 002 Approved blue Day 1 50 *
* denotes rows to be summed in the example.
在此示例中,“蓝色”的类型仅是TOP 1。在此示例中,“状态”和“进度”并不是真正相关的,但我希望将它们作为WHERE标准。
Expected Results
----------------------
wsf_ref total
002 195
001 65
Current Results
----------------------
wsf_ref total
002 120
001 45
似乎只为每种类型选择前1个,而忽略数字<= 3子句。
答案 0 :(得分:1)
首先使用用户变量,您需要创建一个rn以获得type
和ref
的前3名
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 |
编辑:
询问了一下之后,我得到了一个简单的版本:
What boolean value return assign integer or string to a variable
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;