MySQL Query GROUP จำแนกตามวัน / เดือน / ปี


649

เป็นไปได้ไหมที่จะทำแบบสอบถามง่ายๆเพื่อนับจำนวนระเบียนที่ฉันมีในช่วงเวลาที่กำหนดเช่นปีเดือนหรือวันที่มีTIMESTAMPเขตข้อมูลเช่น:

SELECT COUNT(id)
FROM stats
WHERE record_date.YEAR = 2009
GROUP BY record_date.YEAR

หรือแม้กระทั่ง:

SELECT COUNT(id)
FROM stats
GROUP BY record_date.YEAR, record_date.MONTH

เพื่อให้ได้สถิติรายเดือน

ขอบคุณ!


1
ฉันเดาว่าควรจะอยู่GROUP BY record_date.MONTHในข้อมูลโค้ดแรกของคุณ
chiccodoro

คำตอบ:


1012
GROUP BY YEAR(record_date), MONTH(record_date)

ตรวจสอบฟังก์ชันวันที่และเวลาใน MySQL


27
คุณอาจต้องการเพิ่มคอลัมน์พิเศษเพื่อเพิ่มความชัดเจนในบางกรณีเช่นที่ระเบียนมีระยะเวลาหลายปี เลือก COUNT (event_id), DATE_FORMAT (event_start, '% Y /% m')
Ric

ตัวอย่างที่สมบูรณ์แบบง่าย: SELECT count(*), record_date FROM anytable WHERE anytable.anycolumn = 'anycondition' GROUP BY YEAR(record_date), month(record_date);หมายเหตุ: record_date เป็นประเภทวันที่ TIMESTAMP
ค่าใหม่

น่าจะเป็นที่กล่าวถึงว่านี่ไม่ได้ทำงานบน MySQL 5.7 ของฉันด้วยคอลัมน์ชื่อแทน COUNT (ไม่มีข้อผิดพลาดฉันได้ผลลัพธ์เป็นศูนย์) เมื่อฉันเปลี่ยนเพื่อเลือกฟิลด์เหล่านั้นด้วยนามแฝงฉันสามารถจัดกลุ่มตามชื่อแทนได้ นี่เป็นอิมเมจ Docker มาตรฐาน MySQL 5.7 ที่ใช้งานในสภาพแวดล้อมท้องถิ่นดังนั้นฉันจึงไม่รู้ว่าทำไมจึงไม่มีข้อผิดพลาดหรือส่งคืนผลลัพธ์
MrMesees

3
โอ้พระเจ้าถ้าฉันรู้เรื่องนี้ก่อนหน้านี้ ... มี PHP หลายบรรทัดที่ต้องทำสิ่งที่ MySQL สามารถทำได้ในบรรทัดเดียว
คืน

230
GROUP BY DATE_FORMAT(record_date, '%Y%m')

หมายเหตุ (โดยหลักแล้วจะเป็นผู้ลงคะแนนที่มีศักยภาพ) ปัจจุบันนี้อาจไม่ได้มีประสิทธิภาพเท่าคำแนะนำอื่น ๆ แต่ถึงกระนั้นฉันก็ปล่อยให้มันเป็นทางเลือกและอีกทางหนึ่งที่สามารถให้บริการในการเห็นว่าโซลูชั่นอื่น ๆ ได้เร็วขึ้น (สำหรับคุณไม่สามารถบอกได้อย่างรวดเร็วจากช้าจริง ๆ จนกว่าคุณจะเห็นความแตกต่าง) นอกจากนี้เมื่อเวลาผ่านไปการเปลี่ยนแปลงอาจเกิดขึ้นกับเครื่องยนต์ของ MySQL เกี่ยวกับการปรับให้เหมาะสมเพื่อที่จะแก้ปัญหานี้ในบางครั้ง จุดที่ห่างไกล) ในอนาคตจะมีประสิทธิภาพเทียบเท่ากับคนอื่น ๆ


3
ฉันรู้สึกว่าสิ่งนี้จะทำงานได้ไม่ดีนักเนื่องจากฟังก์ชันการจัดรูปแบบจะไม่สามารถใช้ดัชนีในคอลัมน์วันที่ได้
ซันนี่

@Stv: คุณอาจต้องการที่จะต้องพิจารณา@ คำตอบ FU-ไคของแล้ว เท่าที่ผมสามารถบอกการแสดงออกการจัดกลุ่มทั้งในคำตอบที่และเหมืองประเมินถึงสิ่งเดียวกัน แต่อาจจะมีประสิทธิภาพมากกว่าEXTRACT() DATE_FORMAT()(ฉันไม่มี MySQL สำหรับการทดสอบที่เหมาะสม)
Andriy M

45

ลองอันนี้

SELECT COUNT(id)
FROM stats
GROUP BY EXTRACT(YEAR_MONTH FROM record_date)

ฟังก์ชันEXTRACT (หน่วยจากวันที่)จะดีกว่าเนื่องจากใช้การจัดกลุ่มน้อยกว่าและฟังก์ชันจะคืนค่าตัวเลข

เงื่อนไขการเปรียบเทียบเมื่อการจัดกลุ่มจะเร็วกว่าฟังก์ชั่น DATE_FORMAT (ซึ่งคืนค่าสตริง) ลองใช้ฟังก์ชัน | ฟิลด์ที่ส่งคืนค่าที่ไม่ใช่สตริงสำหรับเงื่อนไขการเปรียบเทียบ SQL (WHERE, HAVING, ORDER BY, GROUP BY)


43

ฉันลองใช้คำสั่ง 'ที่' ข้างต้นฉันคิดว่าถูกต้องเพราะไม่มีใครแก้ไขได้ แต่ฉันผิด หลังจากการค้นหาบางครั้งฉันพบว่านี่เป็นสูตรที่เหมาะสมสำหรับคำสั่ง WHERE เพื่อให้รหัสเป็นดังนี้:

SELECT COUNT(id)  
FROM stats  
WHERE YEAR(record_date) = 2009  
GROUP BY MONTH(record_date)

30

หากการค้นหาของคุณมากกว่าหลายปีและคุณยังต้องการจัดกลุ่มรายเดือนฉันแนะนำ:

รุ่นที่ 1:

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY DATE_FORMAT(record_date, '%Y%m')

รุ่น # 2 (มีประสิทธิภาพมากขึ้น) :

SELECT SQL_NO_CACHE YEAR(record_date), MONTH(record_date), COUNT(*)
FROM stats
GROUP BY YEAR(record_date)*100 + MONTH(record_date)

ฉันเปรียบเทียบรุ่นเหล่านี้บนโต๊ะขนาดใหญ่ที่มี 1,357,918 แถว () และรุ่นที่ 2 ดูเหมือนจะมีผลลัพธ์ที่ดีกว่า

version1 (ค่าเฉลี่ย 10 การดำเนินการ) : 1.404 วินาที
version2 (ค่าเฉลี่ย 10 การดำเนินการ) : 0.780 วินาที

( SQL_NO_CACHEเพิ่มรหัสเพื่อป้องกัน MySQL ไม่ให้ CACHING กับคิวรี)


1
พิจารณารวมถึงข้อเสนอแนะของ @ fu-chi ในการทดสอบของคุณซึ่งอาจพิสูจน์ได้ว่ามีประสิทธิภาพยิ่งขึ้น นอกจากนี้คุณทดสอบGROUP BY YEAR(record_date)*100 + MONTH(record_date)แล้ว แต่ทำไมไม่ทดสอบGROUP BY YEAR(record_date), MONTH(record_date)ด้วยล่ะ
Andriy M

2
หากคุณใช้ COUNT (1) ปลูกฝัง COUNT (*) มันจะเร็วขึ้นและข้อมูลผลลัพธ์จะเหมือนกัน
Pa0l0

2
นั่นคือสิ่งที่*100ในรุ่น # 2? ขอบคุณล่วงหน้า.
Avión

1
*100ถึงYEAR(record_date)*100 + MONTH(record_date) == DATE_FORMAT(record_date, '%Y%m')
Phu Duy

17

หากคุณต้องการจัดกลุ่มตามวันที่ใน MySQL ให้ใช้รหัสด้านล่าง:

 SELECT COUNT(id)
 FROM stats
 GROUP BY DAYOFMONTH(record_date)

หวังว่านี้ช่วยประหยัดเวลาสำหรับคนที่กำลังจะไปหากระทู้นี้


6
เป็นสิ่งสำคัญที่จะต้องทราบว่าคุณจำเป็นต้องจัดกลุ่มตามMONTH(record_date)บัญชีเป็นเวลาหลายเดือนด้วย
เว็บเน็ต

14

หากคุณต้องการกรองระเบียนสำหรับปีเฉพาะ (เช่น 2000) ให้ปรับWHEREข้อเช่นนี้:

SELECT MONTH(date_column), COUNT(*)
FROM date_table
WHERE date_column >= '2000-01-01' AND date_column < '2001-01-01'
GROUP BY MONTH(date_column)
-- average 0.016 sec.

แทน:

WHERE YEAR(date_column) = 2000
-- average 0.132 sec.

ผลลัพธ์ถูกสร้างขึ้นจากตารางที่มีแถว 300k และดัชนีในคอลัมน์วันที่

สำหรับGROUP BYข้อฉันทดสอบสามตัวแปรกับตารางที่กล่าวถึงข้างต้น นี่คือผลลัพธ์:

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY YEAR(date_column), MONTH(date_column)
-- codelogic
-- average 0.250 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY DATE_FORMAT(date_column, '%Y%m')
-- Andriy M
-- average 0.468 sec.

SELECT YEAR(date_column), MONTH(date_column), COUNT(*)
FROM date_table
GROUP BY EXTRACT(YEAR_MONTH FROM date_column)
-- fu-chi
-- average 0.203 sec.

สุดท้ายคือผู้ชนะ


10

โซลูชันที่สมบูรณ์และเรียบง่ายพร้อมประสิทธิภาพที่ใกล้เคียงกัน แต่สั้นลงและมีความยืดหยุ่นมากขึ้นในปัจจุบัน:

SELECT COUNT(*) FROM stats
-- GROUP BY YEAR(record_date), MONTH(record_date), DAYOFMONTH(record_date)
GROUP BY DATE_FORMAT(record_date, '%Y-%m-%d')

7

หากคุณต้องการรับสถิติรายเดือนที่มีจำนวนแถวต่อเดือนของแต่ละปีเรียงลำดับตามเดือนล่าสุดให้ลองทำดังนี้:

SELECT count(id),
      YEAR(record_date),
      MONTH(record_date) 
FROM `table` 
GROUP BY YEAR(record_date),
        MONTH(record_date) 
ORDER BY YEAR(record_date) DESC,
        MONTH(record_date) DESC

7

คุณสามารถทำได้เพียงฟังก์ชั่นMysql DATE_FORMAT ()ใน GROUP BY คุณอาจต้องการเพิ่มคอลัมน์พิเศษเพื่อเพิ่มความชัดเจนในบางกรณีเช่นที่ระเบียนมีระยะเวลาหลายปีจากนั้นเดือนเดียวกันเกิดขึ้นในหลายปีที่ผ่านมามีตัวเลือกมากมายที่คุณสามารถกำหนดเองได้ โปรดอ่านก่อนที่จะเริ่มต้นนี้ หวังว่ามันจะมีประโยชน์มากสำหรับคุณ นี่คือแบบสอบถามตัวอย่างสำหรับความเข้าใจของคุณ

SELECT
    COUNT(id),
    DATE_FORMAT(record_date, '%Y-%m-%d') AS DAY,
    DATE_FORMAT(record_date, '%Y-%m') AS MONTH,
    DATE_FORMAT(record_date, '%Y') AS YEAR

FROM
    stats
WHERE
    YEAR = 2009
GROUP BY
    DATE_FORMAT(record_date, '%Y-%m-%d ');

4

แบบสอบถามต่อไปนี้ทำงานให้ฉันใน Oracle Database 12c Release 12.1.0.1.0

SELECT COUNT(*)
FROM stats
GROUP BY 
extract(MONTH FROM TIMESTAMP),
extract(MONTH FROM TIMESTAMP),
extract(YEAR  FROM TIMESTAMP);

2

ฉันชอบที่จะปรับการเลือกกลุ่มหนึ่งปีให้เหมาะสม:

SELECT COUNT(*)
  FROM stats
 WHERE record_date >= :year 
   AND record_date <  :year + INTERVAL 1 YEAR;

วิธีนี้คุณสามารถผูกปีในครั้งเดียวเช่น'2009'ด้วยพารามิเตอร์ที่มีชื่อและไม่จำเป็นต้องกังวลเกี่ยวกับการเพิ่ม'-01-01'หรือส่งผ่าน'2010'แยกต่างหาก

นอกจากนี้ตามที่สันนิษฐานว่าเราเป็นเพียงการนับแถวและidไม่เคยมีNULLฉันชอบที่จะCOUNT(*)COUNT(id)


0

.... group by to_char(date, 'YYYY') -> 1989

.... group by to_char(date,'MM') -> 05

.... group by to_char(date,'DD') ---> 23

.... group by to_char(date,'MON') ---> MAY

.... group by to_char(date,'YY') ---> 89


นี่จะช้ามาก
earl3s
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.