2012-01-25 49 views
7

Tôi đang cố tìm nạp một số hàng từ cơ sở dữ liệu MySQL và nhóm chúng theo ngày chúng được đăng.MySQL GROUP BY UNIX TIMESTAMP

Kết quả cuối cùng tôi muốn sau ..

thứ hai -Article 1 -Article 2 -Article 3

thứ ba -Article 1 -Article 2

thứ tư - Điều 1 -Article 2 -Article 3 -Article 4

Và như vậy, tôi không chắc chắn nếu điều này có thể được thực hiện trong MySQL một mình mà không cần PHP làm thêm công việc.

Đây là truy vấn tôi có cho đến nay nhưng dường như không được nhóm theo ngày.

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 

Cảm ơn.

+0

xóa dấu phẩy trước GROUP BY và truy vấn sẽ hoạt động. –

+0

Truy vấn này sẽ chỉ cung cấp hàng đầu tiên phù hợp cho mỗi ngày. Nó có thể thực hiện được với 'GROUP_CONCAT()' nhưng kết quả không dễ sử dụng lại. Tại sao bạn không thể sử dụng php? –

+1

Bạn nên làm điều đó thông qua PHP. Hầu hết các giải pháp chỉ có MySQL sẽ sử dụng hàm 'GROUP_CONCAT()' để giới hạn kích thước của cột thành 1KB. Nếu bạn có một vài chục bài viết truy vấn như vậy sẽ không cung cấp cho bạn bức tranh hoàn chỉnh. –

Trả lời

1

Sử dụng một truy vấn như thế này để có được những dữ liệu theo thứ tự đúng:

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 trả về một số giữa 1 và 7 (1 = Chủ Nhật) để kết quả của bạn sẽ được sắp xếp từ Chủ Nhật đến Thứ Bảy. DAYNAME trả về tên chữ trong ngày (Chủ Nhật, Thứ Hai, ...). Sau đó, bạn có thể nhóm và hiển thị dữ liệu của mình bằng cách sử dụng PHP:

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

Tôi nghĩ bạn có thể thử GROUP_CONCAT (cms_news.news_title SEPARATOR '-'). Thông tin chi tiết tại địa chỉ: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

Một số truy vấn chưa được kiểm tra mà thực sự giải quyết vấn đề:

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

Thật không may MySQL làm những việc như vậy veeeery chậm, bởi vì bạn không thể tạo chỉ mục cho đặt hàng này. Tôi khuyên bạn nên sử dụng Postgres ;-) Nhưng trong trường hợp của bạn, bạn nên nhóm các kết quả về phía PHP, nhưng tránh sử dụng các phần dữ liệu khổng lồ, PHP sẽ ăn quá nhiều bộ nhớ để lưu trữ nó.

+1

Thật không may là MySQL DO những thứ như vậy. –

+0

nhưng cực kỳ chậm! Tôi vừa thử nghiệm nó trên bảng với ít hơn 3KK hàng và thời gian đáp ứng là 2 phút 22,64 giây mặc dù thực tế là cơ sở dữ liệu nằm trong bộ nhớ! – n0nSmoker

+0

Thật vậy! Chậm, nhưng nó có. Dù sao, tôi chắc chắn anh ta không cần phải xử lý toàn bộ số lượng dữ liệu và cũng có thể lưu trữ loại truy vấn này. Cuối cùng, nó có thể là một giải pháp cho vấn đề của anh ta. –

2

Truy vấn này với 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 
; 

Nhưng không dễ dàng để sử dụng sau và limited in size (1KB mặc định).

Truy vấn này đơn giản

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

Bạn có thể dễ dàng reindex với 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

truy vấn trên của bạn không làm việc, trừ rằng khi bạn GROUP BY một cột, bạn phải bằng cách nào đó tổng hợp tất cả những người khác.

Ví dụ: GROUP BY Day trả về một bản ghi cho mỗi ngày. Nếu có nhiều bản ghi được nhập cho mỗi ngày và bạn đang yêu cầu id, title, category, v.v., làm cách nào để MySQL biết được đa số nào để hiển thị cho bạn vì nó chỉ hiển thị cho bạn một hàng? (Nó thường hiển thị hàng "đầu tiên" cho mỗi ngày khi chúng xuất hiện trong "SELECT * FROM mytable", nhưng bạn không nên dựa vào điều này).

Giải pháp là bạn bằng cách nào đó tổng hợp tất cả các thuộc tính riêng lẻ đó như id thành một chuỗi cho mỗi nhóm. Bạn có thể sử dụng GROUP_CONCAT cho điều này như gợi ý @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 

này sẽ cung cấp cho bạn ví dụ .:

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

Tức là các id, tiêu đề, danh mục, nguồn, loại và nội dung sẽ biến thành một chuỗi được phân cách bằng dấu phẩy mỗi Ngày.

Tuy nhiên có vẻ như điều này không hoàn toàn phù hợp với mục đích của bạn (có một chuỗi với nội dung của tất cả các bài viết vào ngày đó dường như vô nghĩa).

Tôi nghĩ rằng bạn nên thực hiện truy vấn của bạn:

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 

(Chú ý tôi đã thay đổi DAYOFMONTH của bạn để DAYOFWEEK vì nó có vẻ phù hợp với câu hỏi ban đầu của bạn tốt hơn.)

Sự thay đổi là không có nhóm - chỉ cần sắp xếp theo ngày.

Vì đầu ra của bạn được sắp xếp theo ngày, tên ngày cũng sẽ theo thứ tự.

Bạn có thể làm một cái gì đó như thế này trong php của bạn sau đó:

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