MySQL GROUP BY UNIX TIMESTAMP - PullRequest
       11

MySQL GROUP BY UNIX TIMESTAMP

7 голосов
/ 25 января 2012

Я пытаюсь получить количество строк из базы данных MySQL и сгруппировать их по дням их публикации.

Конечный результат Мне бы хотелось следующее ..

Понедельник -Статья 1 - Статья 2 - Статья 3

Вторник - Статья 1 - Статья 2

Среда - Статья 1 - Статья 2 - Статья 3 - Статья 4

И так далее,Я не уверен, что это можно сделать только в MySQL, если PHP не выполняет дополнительную работу.

Это запрос, который у меня есть, но, похоже, я не группирую его по дням.

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

Спасибо.

Ответы [ 5 ]

4 голосов
/ 25 января 2012

Ваш вышеупомянутый запрос работает, за исключением , что, когда вы GROUP BY один столбец, вы должны каким-то образом объединить все остальные.

Например, GROUP BY Day возвращает одну запись для каждого дня. Если в каждый день вводится несколько записей, и вы запрашиваете их id, title, category и т. Д., Как MySQL узнает, какой из нескольких показывать вам, поскольку он показывает только одну строку ? (Обычно он показывает «первую» строку для каждого дня в том виде, в каком они отображаются в "SELECT * FROM mytable", но на это не следует полагаться).

Решение состоит в том, что вы каким-то образом объединяете все эти отдельные свойства, такие как id, в одну строку на группу. Вы можете использовать GROUP_CONCAT для этого, как подсказывает @narcisradu.

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    ....

т.е. идентификаторы, заголовки, категории, источники, типы и содержимое будут превращаться в одну строку через день, разделенную запятыми.

Однако кажется, что это не совсем соответствует вашим целям (наличие одной строки с содержанием всех статей в этот день кажется бессмысленным).

Я думаю, что вы должны сделать свой запрос:

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 голосов
/ 25 января 2012

Этот запрос с 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
;

Но не прост в использовании после и ограничен в размере (по умолчанию 1 КБ).

Этот простой запрос

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']));
}
1 голос
/ 25 января 2012

Используйте запрос, подобный этому, чтобы получить данные в правильном порядке:

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'] . ", ";
}
1 голос
/ 25 января 2012

К сожалению, MySQL делает такие вещи очень медленно, потому что вы не можете создать индекс для этого заказа.Я бы посоветовал вам использовать Postgres ;-) Но в вашем случае вы должны группировать результаты на стороне PHP, но избегая использования огромных порций данных, PHP потребляет слишком много памяти для его хранения.

1 голос
/ 25 января 2012

Я думаю, вы можете попробовать 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
...