2016-08-30 30 views
0

我有一个表,看起来像这样:获取最常见/频繁的价值每个月

id | age |  date 
----|-----|-------------------- 
1 | 18 | 2016-07-1 00:00:00 
2 | 20 | 2016-07-1 00:00:00 
3 | 20 | 2016-07-1 00:00:00 
4 | 22 | 2016-08-1 00:00:00 
5 | 22 | 2016-08-1 00:00:00 
6 | 30 | 2016-08-1 00:00:00 
7 | 25 | 2016-09-1 00:00:00 

,我需要得到每月+一年中最常见的年龄。

我有这个疑问至今:

$ages = User::selectRaw('age, MONTH(date) as month, YEAR(date) as year, count(*) as count') 
     ->groupBy(['age', 'month', 'year']) 
     ->orderBy('year', 'asc') 
     ->orderBy('month', 'asc') 
     ->get(); 

这只能得到数各年龄每个月+一年。我需要的东西,看起来像这样:

[ 
    { 
    "age": 20, 
    "month": 7, 
    "year": 2016, 
    }, 
    { 
    "age": 22, 
    "month": 8, 
    "year": 2016, 
    }, 
    { 
    "age": 25, 
    "month": 9, 
    "year": 2016, 
    } 
] 

即七月(月== 7)二零一六年,有两个20岁和一名年满18,所以20是最常见的年龄。对于2016年8月,最常见的是22,依此类推......

对此有什么好的查询?谢谢。

回答

0
select substr(max(concat(lpad(count,10,'0'),age)),11) as age, month, year 
    from (
    select age, MONTH(date) as month, YEAR(date) as year, count(*) as count 
    from test6 
    group by age, MONTH(date), YEAR(date) 
) A 
group by month, year 
order by year, month 

substr(max(concat(lpad(count,10,'0'),age)),11)总合字符串 “算年龄”,获取最大(行最大COUNT(*)),并切断了 “时代” 了。

0

尝试这个

$ages = User::selectRaw('age, MONTH(date) as month, YEAR(date) as year, count(*) as count') 
    ->groupBy(['age', 'month', 'year']) 
    ->orderBy('year', 'asc') 
    ->orderBy('month', 'asc') 
    ->havingRaw('count = MAX(count)') 
    ->get(); 
0

此操作是在MySQL有点困难。这里有三个选择:

  • 制订对确实聚集两次
  • 使用变量一个复杂的查询
  • 拍摄的“黑客”

第三看起来像这样的优势:

select yyyy, mm, 
     substring_index(group_concat(age order by cnt desc), ',', 1) as mode 
from (select age, year(date) as yyyy, month(date) as mm, 
      count(*) as cnt 
     from test6 t 
     group by age, MONTH(date), YEAR(date) 
    ) t 
group by yyyy, mm; 

第一个看起来像这样:

select year(date), month(date), age 
from test6 t 
group by year(date), month(date) 
having count(*) = (select count(*) 
        from test6 t2 
        where year(t2.date) = year(t.date) and 
         month(t2.date) = month(t.date) 
        group by age 
        order by count(*) desc 
        limit 1 
       ); 

请注意,这会返回与第一个查询稍有不同的结果。如果多个年龄段最常见,此版本将返回重复项。

+0

是否确定substring_index必须返回正确的结果?我问,因为它似乎有点反直觉,它是在GROUP BY之后工作的。 – Strawberry

+0

@Strawberry。 。 。 “GROUP BY”后的含义是什么?第一个查询中有两个聚合。 –

+0

我想我在问你的'黑客'解决方案比我的'黑客'解决方案还少'黑客'。 – Strawberry

0

我不知道如何重新格式化,但是,在MySQL中,一个有效的查询可能是这样的:

SELECT a.* 
    FROM 
    (SELECT DATE_FORMAT(date,'%Y-%m') yearmonth 
      , age 
      , COUNT(*) total 
     FROM my_table 
     GROUP 
      BY yearmonth 
      , age 
    ) a 
    JOIN 
    (SELECT yearmonth 
      , MAX(total) total 
     FROM 
      (SELECT DATE_FORMAT(date,'%Y-%m') yearmonth 
        , age 
        , COUNT(*) total 
       FROM my_table 
       GROUP 
        BY yearmonth 
        , age 
      ) x 
     GROUP 
      BY yearmonth 
    ) b 
    ON b.yearmonth = a.yearmonth 
    AND b.total = a.total; 

在两个年龄在顶部特定月份的捆绑,这查询将返回两。

如果“黑客”的解决方案是允许的,这里是一个谎言......

SELECT yearmonth 
    , age 
    FROM 
    (SELECT DATE_FORMAT(date,'%Y-%m') yearmonth 
      , age 
     FROM my_table 
     GROUP 
      BY yearmonth 
      , age 
     ORDER 
      BY yearmonth 
      , COUNT(*) DESC 
    ) x 
GROUP 
    BY yearmonth; 

在并列结果的情况下,该解决方案将挑不确定的方式一个结果。根据文件,也不能保证产生正确的结果。虽然在实践中它总是这样,但我更喜欢第一种解决方案。