MySQL查询问题。根据参考,每种类型前3名和每组前1名的总和
我一直在尝试编写一个SQL查询,以选择每个用户每种类型的前3名,并与每个用户另一种类型的前1名相加。如果听起来很复杂,我道歉,但我想不出更好的方式来描述它。该查询必须与MySQL 5.x兼容 我一直在毫无乐趣地尝试适应之前的一个问题。目前已将其设置为每个用户返回每个类型的前5行,并将其他每行视为值1。我试图修改一些条款,以产生预期的效果,但毫无乐趣MySQL查询问题。根据参考,每种类型前3名和每组前1名的总和,mysql,sql,Mysql,Sql,我一直在尝试编写一个SQL查询,以选择每个用户每种类型的前3名,并与每个用户另一种类型的前1名相加。如果听起来很复杂,我道歉,但我想不出更好的方式来描述它。该查询必须与MySQL 5.x兼容 我一直在毫无乐趣地尝试适应之前的一个问题。目前已将其设置为每个用户返回每个类型的前5行,并将其他每行视为值1。我试图修改一些条款,以产生预期的效果,但毫无乐趣 SELECT wsf_ref ,sum(wsf_value) as total from (select *, ( select count(*)
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
在本例中,“蓝色”的类型仅为顶部1。“状态”和“进度”在本例中并不真正相关,但我希望将它们作为WHERE标准包括在内
Expected Results
----------------------
wsf_ref total
002 195
001 65
Current Results
----------------------
wsf_ref total
002 120
001 45
看起来它只是为每种类型选择了前1名,而忽略了数字
首先,对于用户变量,您需要创建一个rn,以便为每个类型
和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
编辑:
在四处询问之后,我得到了一个更简单的版本:
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;
为什么蓝色是第一名?请解释一下对我没有帮助的逻辑@strawberry对不起,我需要(每种类型前3个wsf_值,其中类型!=blue)+(每种类型前1个wsf_值,其中类型=blue)按wsf_ref分组。你能相应地编辑这个问题吗?如果你说前3个为什么002有7行标记为sum?几乎在那里,但实际上它似乎也是对重复项求和,它为第一种类型添加了一个额外的行。所以对于橙色,rn是1,1,2,3,而不是1,2,3,4。那一行的@type也是空的。只有第一行是空的,所以非常接近。你说的额外一行是什么意思?我得到了你想要的结果,我今晚会公布结果。与您提供的代码相同,在dB fiddle中运行良好,但在我的服务器上通过PHP执行操作时,它会添加一行额外的内容。它选择了前3个代表红色,前1个代表蓝色,这是正确的。然而,橙色有四行。有两个橙色的rn=1,但其中一个@type为空,另一个为橙色。莫名其妙!好的,不要使用PHP在测试中添加其他层,直接在mysql上测试它。我真的不知道两个橙色的rn=1会是什么样子。我将等待你的答复。尝试更改sqlfiddle中的数据,以便我可以复制它。
| wsf_ref | sum_total |
|---------|-----------|
| 1 | 65 |
| 2 | 195 |
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;