2012-01-25 2 views
7

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

Конечный результат я хочу, чтобы эта ..

понедельник -Статья 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 

Спасибо.

+0

удалите запятую перед GROUP BY и запрос будет работать. –

+0

Этот запрос даст только первую строку, соответствующую каждому дню. Это можно сделать с помощью команды GROUP_CONCAT() ', но результат нелегко повторить. Почему вы не можете использовать php? –

+1

Вы должны сделать это через PHP. Большинство решений только для MySQL будут использовать функцию GROUP_CONCAT(), которая ограничивает размер столбца до 1 КБ. Если у вас есть несколько десятков статей, такие запросы не дадут вам полной картины. –

ответ

1

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

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

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

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

+1

К сожалению, MySQL ДОЛЖЕН БЫТЬ такими. –

+0

но очень медленно! Я только что проверил его на столе с строками менее 3KK, а время отклика - 2 минуты 22,64 секунды, несмотря на то, что база данных находится в памяти! – n0nSmoker

+0

Действительно! Медленно, но это так. В любом случае, я уверен, что ему не нужно обрабатывать весь объем данных, и этот запрос может быть кэширован. В конце концов, это может быть решением его проблемы. –

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'])); 
} 
4

Ваш запрос выше делает работу, за исключением что, когда вы 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, потому что кажется, чтобы соответствовать вашему вопросу лучше.)

Изменение в том, что нет никакой группировки - просто заказывая по дате.

Поскольку ваш результат заказан по дате, названия дней также будут в порядке.

Вы можете сделать что-то вроде этого в РНР, то:

$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']; 
}