【问题标题】:MySQL GROUP BY UNIX TIMESTAMPMySQL GROUP BY UNIX 时间戳
【发布时间】:2012-02-18 10:17:47
【问题描述】:

我正在尝试从 MySQL 数据库中获取一些行,并按发布日期对它们进行分组。

最终结果我想要以下..

星期一 -第1条 -第2条 -第3条

星期二 -第1条 -第2条

星期三 -第1条 -第2条 - 第 3 条 -第四条

等等,我不确定这是否可以在没有 PHP 做额外工作的情况下单独在 MySQL 中完成。

这是我目前的查询,但似乎没有按天分组。

SELECT 
cms_news.news_id,
cms_news.news_title,
cms_news.news_date,
cms_news.news_category,
cms_news.news_source,
cms_news.news_type,
cms_news.news_content
FROM 
cms_news cms_news,
GROUP BY 
DAYOFMONTH(FROM_UNIXTIME(cms_news.news_date)) 
ORDER BY 
cms_news.news_date DESC

谢谢。

【问题讨论】:

  • 去掉 GROUP BY 前的逗号,查询就会生效。
  • 此查询将只给出每天匹配的第一行。 GROUP_CONCAT() 是可行的,但结果不容易重用。为什么不能用php?
  • 你应该通过 PHP 来完成。大多数仅 MySQL 的解决方案将使用 GROUP_CONCAT() 函数,该函数将列的大小限制为 1KB。如果您有几十篇文章,则此类查询不会为您提供完整的图片。
  • @SalmanA 也适用于GROUP_CONCAT()的大小限制

标签: php mysql group-by timestamp aggregate-functions


【解决方案1】:

您上面的查询确实有效,除了当您GROUP BY 一列时,您必须以某种方式聚合所有其他列。

例如,GROUP BY Day 每天返回一条记录。如果每天输入多条记录并且您请求它们的idtitlecategory 等,MySQL 怎么知道要显示的多个记录中的哪一个,因为它只会显示一行? (它通常显示每天的“第一”行,因为它们出现在 "SELECT * FROM mytable" 中,但您不应该依赖它)。

解决方案是您以某种方式将所有这些单独的属性(例如 id)聚合到每组一个字符串中。您可以按照@narcisradu 的建议使用GROUP_CONCAT

SELECT 
GROUP_CONCAT(cms_news.news_id),
GROUP_CONCAT(cms_news.news_title),
DAYOFMONTH(FROM_UNIXTIME(cms_news.news_date)) as Day,
GROUP_CONCAT(cms_news.news_category),
GROUP_CONCAT(cms_news.news_source),
GROUP_CONCAT(cms_news.news_type),
GROUP_CONCAT(cms_news.news_content)
FROM 
cms_news cms_news,
GROUP BY 
DAYOFMONTH(FROM_UNIXTIME(cms_news.news_date)) 
ORDER BY 
cms_news.news_date DESC

这会给你例如:

1,4     Story 1 Title, Story 2 Title       <Day1>       Funny,Sad    ....

即id、title、category、sources、types 和 content 每天都会变成一个逗号分隔的字符串。

但是,这似乎不太适合您的目的(用一个字符串包含当天所有文章的内容似乎很荒谬)。

我认为你应该提出问题:

SELECT 
cms_news.news_id,
cms_news.news_title,
DAYNAME(FROM_UNIXTIME(cms_news.news_date)) AS Day,
cms_news.news_category,
cms_news.news_source,
cms_news.news_type,
cms_news.news_content
FROM 
cms_news cms_news,
ORDER BY news_date DESC

(请注意,我将您的 DAYOFMONTH 更改为 DAYOFWEEK,因为它似乎更符合您的原始问题。)

变化在于没有分组 - 只是按日期排序。

由于您的输出按日期排序,因此日期名称也将按顺序排列。

然后你可以在你的 php 中做这样的事情:

$prevday='';
while($row = mysql_fetch_array($res)) {
   if ( $row['Day'] != $prevday ) {
       // day has changed!
       // make a new row. e.g:
       echo "<br/> \n" . $row['Day'];
   } 
   // now just list your article name
   echo " - " . $row['news_title'];
   $prevday = $row['Day'];
}

【讨论】:

    【解决方案2】:

    此查询与GROUP_CONCAT()

    SELECT 
      news_id
    , news_date AS "date"
    , GROUP_CONCAT(news_title) AS "articles"
    FROM cms_news
    GROUP BY news_date
    ORDER BY news_date DESC
    ;
    

    但是和limited in size(默认1kB)之后不好用。

    这个简单的查询

    SELECT 
      news_id
    , news_date AS "date"
    , news_title AS "article"
    FROM cms_news
    ORDER BY news_date DESC
    ;
    

    您可以轻松地使用 php 重新索引。

    // Day Index
    $data = array();
    while ($row = mysql_fetch_assoc($result)) {
      $data[$row['date']][] = $row;
    }
    // Display
    foreach ($data as $date => $row) {
      echo ($date.' : '.implode(' - ', $row['article']));
    }
    

    【讨论】:

      【解决方案3】:

      使用这样的查询以正确的顺序获取数据:

      SELECT
      DAYNAME(FROM_UNIXTIME(cms_news.news_date)) AS DayName,
      cms_news.*
      FROM cms_news
      ORDER BY DAYOFWEEK(FROM_UNIXTIME(cms_news.news_date)), cms_news.news_date
      

      DAYOFWEEK 返回一个介于 1 和 7 之间的数字(1 = 星期日),因此您的结果将从星期日到星期六进行排序。 DAYNAME 返回当天的文字名称(星期日、星期一、...)。然后,您可以使用 PHP 对数据进行分组和显示:

      $DayName = "";
      while($row = mysql_fetch_assoc($query)) {
          if ($DayName != $row['DayName']) {
              $DayName  = $row['DayName']; 
              echo "<br>\n" . $DayName . ": ";
          } 
          echo $row['news_title'] . ", ";
      }
      

      【讨论】:

        【解决方案4】:

        我想你可以试试 GROUP_CONCAT(cms_news.news_title SEPARATOR '-')。更多信息请访问:http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

        一些实际解决问题的未经测试的查询:

        SELECT 
          cms_news.news_id,
          CONCAT(
            DAYNAME(FROM_UNIXTIME(cms_news.news_date)),
            ' - ',
            GROUP_CONCAT(cms_news.news_title SEPARATOR ' - ')
          ) as result,
        cms_news.news_date
        FROM 
        cms_news cms_news
        GROUP BY 
        DAYOFMONTH(FROM_UNIXTIME(cms_news.news_date)) 
        ORDER BY 
        cms_news.news_date DESC
        

        【讨论】:

          【解决方案5】:

          不幸的是 MySQL 做这些事情非常慢,因为你不能为这个排序创建索引。 我建议你使用 Postgres ;-) 但是在您的情况下,您应该在 PHP 端对结果进行分组,但避免使用大量数据,PHP 会占用太多内存来存储它。

          【讨论】:

          • 不幸的是 MySQL 做这样的事情。
          • 但是非常慢!我刚刚在少于 3KK 行的表上对其进行了测试,尽管数据库位于内存中,但响应时间为 2 分 22.64 秒!
          • 确实!慢,但确实如此。无论如何,我确信他不需要处理全部数据量,而且这种查询可能会被缓存。最后,这可能是他的问题的解决方案。
          猜你喜欢
          • 2013-01-07
          • 1970-01-01
          • 1970-01-01
          • 2019-03-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多