จัดกลุ่มตามเดือนและปีใน MySQL


99

ด้วยตารางที่มีการประทับเวลาในแต่ละแถวคุณจะจัดรูปแบบแบบสอบถามให้พอดีกับรูปแบบวัตถุ json เฉพาะนี้ได้อย่างไร

ฉันพยายามจัดระเบียบวัตถุ json เป็นปี / เดือน

json เพื่อปิดการสืบค้น:

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

นี่คือคำถามที่ฉันมี -

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

ข้อความค้นหาถูกทำลายลงเนื่องจาก (คาดเดาได้) รวมกันเป็นปีที่แตกต่างกัน

คำตอบ:


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

คือสิ่งที่คุณต้องการ


63
+1: อีกทางเลือกหนึ่งโดยใช้DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponies

3
ยิ่งไปกว่านั้นจำเป็นต้องใช้เวลาFROM_UNIXTIMEหากคุณมีการประทับเวลา UNIX ในฐานข้อมูลของคุณDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo

ขอบคุณ @OMGPonies ด้วยไวยากรณ์ของคุณฉันสามารถดำเนินการ GROUP ตามเงื่อนไขได้
Henry

ประสิทธิภาพ ... การทดสอบGROUP BY YEAR(date), MONTH(date) DESC;(~ 450 ms) และGROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 ms) ของฉันบนตาราง InnoDB ที่มีมากกว่า 300,000 รายการแสดงให้เห็นว่าก่อนหน้านี้ (คำตอบที่ทำเครื่องหมายไว้สำหรับคำถามนี้) ใช้เวลาประมาณครึ่งหนึ่งของเวลาหลัง
ow3n

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

ยินดีต้อนรับสู่ StackOverflow! นี่เป็นคำถามเก่าและมีคำตอบแล้ว เรายินดีหากคุณสามารถมีส่วนร่วมในคำถามเร่งด่วนเพิ่มเติมได้เช่นกัน คุณสามารถค้นหาเคล็ดลับในการที่จะให้คำตอบที่ดีที่นี่
Mifeet

ดูความคิดเห็นของฉันในคำตอบด้านบน ... บนตารางขนาดใหญ่วิธีนี้ใช้เวลานานเป็นสองเท่า
ow3n


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

ควรใช้ DESC ทั้ง YEAR และ Month เพื่อให้ได้ลำดับที่ถูกต้อง


7

ฉันรู้ว่านี่เป็นคำถามเก่า แต่สิ่งต่อไปนี้ควรใช้งานได้หากคุณไม่ต้องการชื่อเดือนที่ระดับ DB:

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

ดูเอกสารฟังก์ชัน EXTRACT

คุณอาจจะพบว่าสิ่งนี้ทำงานได้ดีขึ้น .. และหากคุณกำลังสร้างออบเจ็กต์ JSON ในเลเยอร์แอปพลิเคชันคุณสามารถจัดรูปแบบ / สั่งซื้อเมื่อคุณเรียกใช้ผลลัพธ์

หมายเหตุฉันไม่ทราบว่าคุณสามารถเพิ่ม DESC ลงใน GROUP BY clause ใน MySQL ได้บางทีคุณอาจไม่มีคำสั่ง 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
โปรดทราบว่าการส่งออกจากEXTRACT(YEAR_MONTH FROM summaryDateTime)เป็น201901
เอ็ดการ์กาซา

@EdgarOrtega ใช่ แต่นั่นก็เพียงพอแล้วที่จะสร้างวัตถุ JSON ที่ต้องการในคำถามเดิมโดยใช้ตรรกะของแอปพลิเคชัน สมมติว่ารูปแบบของการวนซ้ำบางรูปแบบเหนือผลการสืบค้นกำลังเกิดขึ้นแล้วแนวทางของฉันมีเป้าหมายเพื่อให้ได้ข้อมูลที่ต้องการขั้นต่ำจากฐานข้อมูลอย่างง่ายและรวดเร็วที่สุด
Arth

1
คุณพูดถูกก็น่าจะเพียงพอแล้ว ความคิดเห็นของฉันเป็นเพียงเพื่อระบุว่าผลลัพธ์จากฟังก์ชันนั้นเป็นอย่างไรอาจมีคนไม่ชอบรูปแบบนั้น
Edgar Ortega

@EdgarOrtega ไม่ต้องกังวลขอบคุณผลงานที่คุ้มค่า!
Arth

2

คุณต้องทำอะไรแบบนี้

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

คุณ cal ยังทำเช่นนี้

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

สั่งซื้อตามปีและเดือน สมมติว่าคุณต้องการสั่งซื้อตั้งแต่ปีนี้และเดือนนี้ไปจนถึง 12 เดือน





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

คุณยังคงต้องประมวลผลในสคริปต์ภายนอกเพื่อให้ได้โครงสร้างที่คุณต้องการ

ตัวอย่างเช่นใช้การระเบิดของ PHP เพื่อสร้างอาร์เรย์จากรายการชื่อเดือนจากนั้นใช้ json_encode ()


-2

ใช้

GROUP BY year, month DESC";

แทน

GROUP BY MONTH(t.summaryDateTime) DESC";

แม้ว่าจะดูเหมือนว่า GROUP BY MONTH (t.summaryDateTime) DESC ไม่ได้เรียงลำดับเดือนอย่างถูกต้องด้วยเหตุผลบางประการ ...
Derek Adair
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.