我有下表(SQFiddle, with sample data here):
|-------------------------------------------------------|
| id |data_date | value | score | created_at |
|-------------------------------------------------------|
| 1 | 2015-01-01 | 10 | 10 | 2016-07-01 09:00:00 |
| 2 | 2015-02-01 | 10 | 10 | 2016-07-01 09:00:00 |
| 3 | 2015-03-01 | 10 | 10 | 2016-07-01 09:00:00 |
| 4 | 2015-01-01 | 15 | 20 | 2016-07-02 09:00:00 |
| 5 | 2015-03-01 | 15 | 20 | 2016-07-02 09:00:00 |
| 6 | 2015-03-01 | 15 | 15 | 2016-07-03 09:00:00 |
|-------------------------------------------------------|
我想做的是,为每个data_data
返回一条记录,在给定的created_at
日期获得最高分。
2016-07-02结果的预期结果为:
|-------------------------------------------------------|
| id |data_date | value | score | created_at |
|-------------------------------------------------------|
| 4 | 2015-01-01 | 15 | 20 | 2016-07-02 09:00:00 |
| 2 | 2015-02-01 | 10 | 10 | 2016-07-01 09:00:00 |
| 5 | 2015-03-01 | 15 | 20 | 2016-07-02 09:00:00 |
|-------------------------------------------------------|
到目前为止,我所取得的成绩是为每个data_data
返回单个最高得分记录,但我似乎无法添加正确的条件来考虑created_at
字段。
select `my_table`.*
from `my_table`
left outer join `my_table` as `t2`
on `my_table`.`data_date` = `t2`.`data_date` AND
(
(`my_table`.`score` < `t2`.`score`) OR
(`my_table`.`score` = `t2`.`score` AND `my_table`.`id` < `t2`.`id`)
)
where `t2`.`data_date` is null
order by `my_table`.`data_date` asc
返回以下结果:
|-------------------------------------------------------|
| id |data_date | value | score | created_at |
|-------------------------------------------------------|
| 4 | 2015-01-01 | 15 | 20 | 2016-07-02 09:00:00 |
| 2 | 2015-02-01 | 10 | 10 | 2016-07-01 09:00:00 |
| 6 | 2015-03-01 | 15 | 15 | 2016-07-03 09:00:00 |
|-------------------------------------------------------|
使用如下所示的查询,获取在7月2日或之前创建的所有记录,得分最高:
select `my_table`.*
from `my_table`
left outer join `my_table` as `t2`
on `my_table`.`data_date` = `t2`.`data_date` AND
(
(`my_table`.`score` < `t2`.`score`) OR
(`my_table`.`score` = `t2`.`score` AND `my_table`.`id` < `t2`.`id`)
) AND
DATE_FORMAT(my_table.created_at, '%Y-%m-%d') <= '2016-07-02' AND
DATE_FORMAT(t2.created_at, '%Y-%m-%d') <= '2016-07-02'
where `t2`.`data_date` is null
order by `my_table`.`data_date` asc
返回以下错误结果(不应返回第6行):
|-------------------------------------------------------|
| id |data_date | value | score | created_at |
|-------------------------------------------------------|
| 4 | 2015-01-01 | 15 | 20 | 2016-07-02 09:00:00 |
| 2 | 2015-02-01 | 10 | 10 | 2016-07-01 09:00:00 |
| 5 | 2015-03-01 | 15 | 20 | 2016-07-02 09:00:00 |
| 6 | 2015-03-01 | 15 | 15 | 2016-07-03 09:00:00 |
|-------------------------------------------------------|
总结
对于单个data_date
,可能会有多条记录,每条记录都有不同的value
和不同的score
。我想为每个data_data
返回单行,该score
具有在给定日期或之前创建的最高data_date
。即如果data_data
在每周的每一天(周一至周五)创建了一条记录,我可能希望每周tk_getOpenFile
获得最高得分值。
答案 0 :(得分:1)
做这种事情的小提琴是(ab)使用GROUP_CONCAT函数。您可以按需要分组的字段进行分组,并在每个其他字段上使用GROUP_CONCAT,按您希望最大值的字段降序排序。这可以获得连接在一起的每个值的所有值。
然后,您可以使用SUBSTRING_INDEX获取每个值的第一个值。
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY score DESC), ',', 1),
data_date,
SUBSTRING_INDEX(GROUP_CONCAT(value ORDER BY score DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY score DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(created_at ORDER BY score DESC), ',', 1)
FROM my_table
GROUP BY data_date
在这个例子中很容易。当你有可能包含逗号的文本字段,或者你有NULL值时,它会变得有点复杂。
这可能会以更有效的方式为您提供现有结果。但我不确定你是如何尝试将created_at日期考虑在内,除非你的意思是你只想考虑某个created_at日期之前的所有记录: -
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY score DESC), ',', 1),
data_date,
SUBSTRING_INDEX(GROUP_CONCAT(value ORDER BY score DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(score ORDER BY score DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(created_at ORDER BY score DESC), ',', 1)
FROM my_table
WHERE created_at <= '2016-07-02 23:59:59'
GROUP BY data_date
编辑
第二个查询是在指定日期结束之前获取所有记录(我使用了这种方式的日期/时间,而不是从列中的值中提取日期部分,因为这允许日期的索引/ time要使用,同时提取日期部分可以防止使用任何索引,并且还强制在表的每一行上使用函数。对于所有匹配的记录,它按data_date字段对它们进行分组。对于id,value,score和created_at字段,它使用GROUP_CONCAT对每个data_date的所有值进行分组,每个值用逗号分隔(默认值),按分数降序排序。
在2015-01-01的data_date阶段,id字段将包含' 4,1 ',值将包含' 15,10 ',得分将包含' 20,10 ',created_at将包含' 2016-07-02 09:00:00,2016-07-01 09:00:00 '。< / p>
然后使用SUBSTRING_INDEX获取每个字段的第一个逗号的所有内容。由于它们按降序排列顺序,因此将获得与最高分相对应的每个值。
答案 1 :(得分:1)
SELECT x.*
FROM my_table x
JOIN
( SELECT a.data_date
, a.created_at
, MAX(a.score) score
FROM my_table a
JOIN
( SELECT data_date
, MAX(created_at) created_at
FROM my_table
WHERE created_at <= '2016-07-02 23:59:59'
GROUP
BY data_date
) b
ON b.data_date = a.data_date
AND b.created_at = a.created_at
GROUP
BY a.data_date
, a.created_at
) y
ON y.data_date = x.data_date
AND y.created_at = x.created_at
AND y.score = x.score;
答案 2 :(得分:-1)
以下查询将在您的案例中正常工作
select max(id), data_date, max(value), max(score), max(created_at)
from
my_table
where score in (select max(score) from my_table group by data_date)
group by data_date;