关于php:MySQL GROUP BY UNIX TIMESTAMP

MySQL GROUP BY UNIX TIMESTAMP

我正在尝试从MySQL数据库中获取许多行,并在发布之日对它们进行分组。

最终结果我想要以下..

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

星期二
-第1条
- 第2条

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

依此类推,如果没有PHP做额外的工作,我不确定是否可以在MySQL中完成。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 BY Day每天返回一条记录。如果每天输入多个记录并且您正在请求他们的idtitlecategory等,那么MySQL如何知道向您显示的多个记录,因为它只会向您显示一行? (它通常显示每天的"第一"行,因为它们出现在"SELECT * FROM mytable"中,但你不应该依赖于此)。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
1,4     Story 1 Title, Story 2 Title       <Day1>       Funny,Sad    ....

即ids,标题,类别,来源,类型和内容将每天变成一个以逗号分隔的字符串。

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

我想你应该提出你的疑问:

1
2
3
4
5
6
7
8
9
10
11
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中执行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
$prevday='';
while($row = mysql_fetch_array($res)) {
   if ( $row['Day'] != $prevday ) {
       // day has changed!
       // make a new row. e.g:
       echo"<br/>
"
. $row['Day'];
   }
   // now just list your article name
   echo" -" . $row['news_title'];
   $prevday = $row['Day'];
}

此查询使用GROUP_CONCAT()

1
2
3
4
5
6
7
8
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
;

但之后不易使用且尺寸有限(默认为1kB)。

这个简单的查询

1
2
3
4
5
6
7
SELECT
  news_id
, news_date AS"date"
, news_title AS"article"
FROM cms_news
ORDER BY news_date DESC
;

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

1
2
3
4
5
6
7
8
9
// 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']));
}


使用此类查询以正确的顺序获取数据:

1
2
3
4
5
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对数据进行分组和显示:

1
2
3
4
5
6
7
8
9
$DayName ="";
while($row = mysql_fetch_assoc($query)) {
    if ($DayName != $row['DayName']) {
        $DayName  = $row['DayName'];
        echo"
"
. $DayName .":";
    }
    echo $row['news_title'] .",";
}

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


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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