在group by上使用case

时间:2016-01-14 19:27:04

标签: mysql group-by case

我有一个表,想根据session_id的值对行进行分组。如果会话小于零,则按user_id,file_id和session_id对其进行分组,如果没有,则按user_id对其进行分组,file_id

我提出的查询

select user_id, file_id, session_id
from memo
group by file_id, user_id, case 
    when session_id < 0 then 'session_id'
end

select user_id, file_id, session_id
from memo
group by case 
    when session_id < 0 then 'file_id, user_id, session_id'
    else 'file_id, user_id'
end

两个查询的结果都是

user_id     file_id     session_id
8710        1896366041  -1452797155
8710        1896366041  1452797185914

我想要的是只有一个正值的session_id,同时具有每个唯一的负值。我现在的解决方法是使用2个查询,每个查询使用不同的where语句来处理session_id的负值和正值。但是,它感觉不对,因为我认为使用案例是正确的方式

一些示例数据

CREATE TABLE IF NOT EXISTS `memo` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`file_id` int(11) NOT NULL,
`page_id` int(11) NOT NULL,
`content` text NOT NULL,
`last_update` int(11) NOT NULL,
`session_id` bigint(20) NOT NULL DEFAULT '0',
`object_id` varchar(30) DEFAULT NULL,
`evaluated_id` int(11) DEFAULT '0',
PRIMARY KEY (`id`)
)
INSERT INTO `memo` (`id`, `user_id`, `file_id`, `page_id`, `last_update`, `session_id`, `object_id`, `evaluated_id`) VALUES
    (1585, 8710, 1896366041, 0, 1452797202, -1452797155, '1452797152590_63', 0),
    (1586, 8710, 1896366041, 0, 1452797202, -1452797155, '1452797153301_61', 0),
    (1588, 8710, 1896366041, 0, 1452797202, -1452797172, '1452797169976_46', 0),
    (1589, 8710, 1896366041, 0, 1452797202, -1452797172, '1452797170590_24', 0),
    (1591, 8710, 1896366041, 0, 1452797202, 1452797185914, '1452797186652_24', 0),
    (1592, 8710, 1896366041, 0, 1452797202, 1452797185914, '1452797187329_8', 0),
    (1594, 8710, 1896366041, 0, 1452797202, 1452797200154, '1452797201237_32', 0),
    (1595, 8710, 1896366041, 0, 1452797202, 1452797200154, '1452797201682_11', 0),
    (1596, 8710, 1896366041, 0, 1452797202, 1452797200154, '1452797201931_93', 0);

如果有人可以帮助我,那将是很好的,谢谢

3 个答案:

答案 0 :(得分:3)

正如其他答案所指出的那样,还有其他查询模式可能会让您获得您所追求的结果。但是我看到了您所在的曲目,并且可以使用CASE中的GROUP BY表达式来实现指定的结果。

看起来你真正想要的是在GROUP BY子句中指定三个表达式。 (GROUP BY中的表达式在执行时不能有条件地修改。它是一个静态的表达式列表。)

前两个表达式只是列名file_iduser_id

这是您想要进行条件测试的第三个表达式。如果session_id为负数,则您希望返回session_id的值。否则,您希望返回常量值,因此所有具有非负值的行将组合在一起。

这样的事情:

 GROUP BY file_id
        , user_id
        , CASE WHEN session_id < 0 THEN session_id ELSE NULL END

请注意,CASE表达式返回。它不会返回标识符或标识符列表。

答案 1 :(得分:0)

case不要那样工作。您应该将两个条件数据分组,然后使用UNION

进行组合
(select 
    user_id, file_id, session_id
from 
    memo
group by 
    file_id, user_id, session_id
where 
    session_id < 0)

UNION

(select 
    user_id, file_id, session_id
from 
    memo
group by 
    file_id, user_id
where 
    session_id > 0)

答案 2 :(得分:0)

案件对你想要的东西有点过分,试试这个:

select user_id, file_id, IF(session_id<0, session_id, 1) AS session_group
from memo
group by file_id, user_id, session_group

另外,您是group而不是使用SELECT DISTINCT

的原因