Nhóm theo tháng và năm trong MySQL


95

Cho một bảng có dấu thời gian trên mỗi hàng, bạn sẽ định dạng truy vấn như thế nào để phù hợp với định dạng đối tượng json cụ thể này.

Tôi đang cố gắng tổ chức một đối tượng json thành năm / tháng.

json để làm cơ sở cho truy vấn:

{
  "2009":["August","July","September"],
  "2010":["January", "February", "October"]
}

Đây là truy vấn tôi có cho đến nay -

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY MONTH(t.summaryDateTime) DESC";

Truy vấn đang bị phá vỡ vì nó (có thể dự đoán được) gộp lại với nhau vào những năm khác nhau.

Câu trả lời:


185
GROUP BY YEAR(t.summaryDateTime), MONTH(t.summaryDateTime) DESC;

là những gì bạn muốn.


60
+1: Một giải pháp thay thế khác sử dụng DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponies

3
Hơn nữa về vấn đề này, FROM_UNIXTIME là cần thiết nếu bạn có một dấu thời gian UNIX trong DB của bạnDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo

Cảm ơn @OMGPonies, với cú pháp của bạn, tôi có thể thực hiện GROUP BY có điều kiện.
Henry

Hiệu suất ... thử nghiệm của tôi GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 mili giây) và GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 mili giây) trên bảng InnoDB với> 300.000 mục nhập cho thấy câu trả lời trước (câu trả lời được đánh dấu cho câu hỏi này) mất ~ một nửa thời gian so với phần sau.
ow3n

77
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')

Chào mừng bạn đến với StackOverflow! Đây là một câu hỏi cũ và đã được trả lời. Chúng tôi sẽ rất vui nếu bạn cũng có thể đóng góp cho những câu hỏi cấp bách hơn. Bạn có thể tìm thấy các mẹo để cung cấp câu trả lời hay tại đây .
Mifeet

Xem nhận xét của tôi về câu trả lời ở trên ... Trên các bảng lớn, phương pháp này mất gấp đôi thời gian.
ow3n

9

tôi thích

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY EXTRACT(YEAR_MONTH FROM t.summaryDateTime) DESC";

8
SELECT MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM trading_summary t
GROUP BY YEAR(t.summaryDateTime) DESC, MONTH(t.summaryDateTime) DESC

Nên sử dụng DESC cho cả NĂM và Tháng để có thứ tự chính xác.


7

Tôi biết đây là một câu hỏi cũ, nhưng cách sau sẽ hoạt động nếu bạn không cần tên tháng ở cấp DB:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month;

Xem tài liệu về hàm EXTRACT

Bạn có thể sẽ thấy điều này hoạt động tốt hơn .. và nếu bạn đang xây dựng một đối tượng JSON trong lớp ứng dụng, bạn có thể thực hiện định dạng / sắp xếp khi bạn chạy qua các kết quả.

NB Tôi không biết rằng bạn có thể thêm DESC vào mệnh đề GROUP BY trong MySQL, có lẽ bạn đang thiếu mệnh đề ORDER BY:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month
ORDER BY summary_year_month DESC;

1
xin lưu ý rằng sản lượng từ EXTRACT(YEAR_MONTH FROM summaryDateTime)201901
Edgar Ortega

@EdgarOrtega Yep, nhưng điều đó đủ để tạo đối tượng JSON mong muốn trong câu hỏi ban đầu bằng cách sử dụng logic ứng dụng. Giả sử rằng một số dạng lặp qua kết quả truy vấn đã xảy ra, cách tiếp cận của tôi nhằm mục đích lấy thông tin yêu cầu tối thiểu từ DB một cách đơn giản và nhanh chóng nhất có thể
Arth

1
Bạn nói đúng, vậy là đủ. Nhận xét của tôi chỉ để cho biết kết quả đầu ra từ chức năng đó như thế nào, có thể ai đó không thích định dạng đó.
Edgar Ortega

@EdgarOrtega Không phải lo lắng, cảm ơn, một đóng góp xứng đáng!
Arth

2

Bạn phải làm một cái gì đó như thế này

SELECT onDay, id, 
sum(pxLow)/count(*),sum(pxLow),count(`*`),
CONCAT(YEAR(onDay),"-",MONTH(onDay)) as sdate 
FROM ... where stockParent_id =16120 group by sdate order by onDay

2

Bạn cũng làm điều này

SELECT  SUM(amnt) `value`,DATE_FORMAT(dtrg,'%m-%y') AS label FROM rentpay GROUP BY YEAR(dtrg) DESC, MONTH(dtrg) DESC LIMIT 12

để đặt hàng theo năm và tháng. Giả sử bạn muốn đặt hàng từ năm nay và từ tháng này trở lại 12 tháng


1

sử dụng hàm EXTRACT như thế này

mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
       -> 2009

1

Đây là cách tôi làm điều đó:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);


0
SELECT YEAR(t.summaryDateTime) as yr, GROUP_CONCAT(MONTHNAME(t.summaryDateTime)) AS month 
FROM trading_summary t GROUP BY yr

Tuy nhiên, bạn sẽ cần phải xử lý nó trong tập lệnh bên ngoài để có được chính xác cấu trúc mà bạn đang tìm kiếm.

Ví dụ: sử dụng PHP's bùng nổ để tạo một mảng từ danh sách tên tháng và sau đó sử dụng json_encode ()


-2

Sử dụng

GROUP BY year, month DESC";

Thay vì

GROUP BY MONTH(t.summaryDateTime) DESC";

mặc dù có vẻ như GROUP BY MONTH (t.summaryDateTime) DESC không đặt những tháng đúng đối với một số lý do ...
Derek Adair
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.