ฉันต้องการคำนวณจำนวนเดือนระหว่างช่องวันที่ 2 ช่อง
มีวิธีที่ดีกว่าการใช้การประทับเวลาแบบยูนิกซ์และการหารด้วย 2602,000 (วินาที) และการปัดเศษใน MySQL หรือไม่?
ฉันต้องการคำนวณจำนวนเดือนระหว่างช่องวันที่ 2 ช่อง
มีวิธีที่ดีกว่าการใช้การประทับเวลาแบบยูนิกซ์และการหารด้วย 2602,000 (วินาที) และการปัดเศษใน MySQL หรือไม่?
คำตอบ:
DATEDIFFฟังก์ชั่นสามารถให้จำนวนวันระหว่างวันที่สองวัน ข้อใดถูกต้องกว่าเนื่องจาก ... คุณกำหนดเดือนได้อย่างไร? (28, 29, 30 หรือ 31 วัน?)
PERIODDIFF
เพียงแค่ใช้ค่า YYYYMM ดังนั้นหากคุณไม่คิดจำนวนวันด้วยตัวเองก่อนที่คุณจะส่งค่า YYYYMM สิ่งที่คุณกำลังคำนวณคือจำนวนเดือนปัดเศษเป็นเดือนที่ใกล้ที่สุดหากมีจำนวนเดือนน้อยกว่าจำนวนเต็ม ดูคำตอบของ Zane ด้านล่าง
PERIODDIFF
ความคิดเห็นจำนวนมาก Perioddiff ไม่ใช้ค่าวันดังนั้นคุณกำลังคำนวณจำนวนเดือนที่ปัดเศษขึ้นเป็นเดือนที่ใกล้ที่สุดหากมีจำนวนเดือนน้อยกว่าทั้งหมด
ฉันแปลกใจที่ยังไม่ได้พูดถึง:
ดูที่ฟังก์ชันTIMESTAMPDIFF ()ใน MySQL
สิ่งที่ช่วยให้คุณทำได้คือส่งผ่านสองค่าTIMESTAMP
หรือDATETIME
(หรือแม้กระทั่งDATE
เมื่อ MySQL จะแปลงอัตโนมัติ) รวมถึงหน่วยเวลาที่คุณต้องการอิงตามความแตกต่างของคุณ
คุณสามารถระบุMONTH
เป็นหน่วยในพารามิเตอร์แรก:
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-04')
-- Outputs: 0
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-05')
-- Outputs: 1
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-15')
-- Outputs: 1
SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-12-16')
-- Outputs: 7
โดยทั่วไปจะได้รับจำนวนเดือนที่ผ่านไปนับจากวันแรกในรายการพารามิเตอร์ โซลูชันนี้จะชดเชยจำนวนวันที่แตกต่างกันโดยอัตโนมัติในแต่ละเดือน (28,30,31) รวมทั้งคำนึงถึงปีอธิกสุรทินคุณไม่ต้องกังวลเกี่ยวกับสิ่งนั้น
จะซับซ้อนกว่าเล็กน้อยหากคุณต้องการเพิ่มความแม่นยำของทศนิยมในจำนวนเดือนที่ผ่านไป แต่คุณสามารถทำได้ดังนี้
SELECT
TIMESTAMPDIFF(MONTH, startdate, enddate) +
DATEDIFF(
enddate,
startdate + INTERVAL
TIMESTAMPDIFF(MONTH, startdate, enddate)
MONTH
) /
DATEDIFF(
startdate + INTERVAL
TIMESTAMPDIFF(MONTH, startdate, enddate) + 1
MONTH,
startdate + INTERVAL
TIMESTAMPDIFF(MONTH, startdate, enddate)
MONTH
)
พารามิเตอร์วันที่ของคุณอยู่ที่ไหนstartdate
และอยู่ที่ไหนenddate
ไม่ว่าจะมาจากคอลัมน์วันที่สองคอลัมน์ในตารางหรือเป็นพารามิเตอร์อินพุตจากสคริปต์:
ตัวอย่าง:
With startdate = '2012-05-05' AND enddate = '2012-05-27':
-- Outputs: 0.7097
With startdate = '2012-05-05' AND enddate = '2012-06-13':
-- Outputs: 1.2667
With startdate = '2012-02-27' AND enddate = '2012-06-02':
-- Outputs: 3.1935
PERIODDIFF
PERIOD_DIFFคำนวณเดือนระหว่างวันที่สองวัน
ตัวอย่างเช่นในการคำนวณความแตกต่างระหว่าง now () และคอลัมน์เวลาใน your_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
ฉันใช้PERIODDIFFด้วย ในการรับปีและเดือนของวันที่ฉันใช้ฟังก์ชัน EXTRACT :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
DATE_FORMAT
ขอบคุณ! +1
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(time, "%Y%m%d"))) AS months FROM your_table;
PERIOD_DIFF
ไม่ใช้ค่าวันดังนั้นคุณกำลังคำนวณจำนวนเดือนที่ปัดเศษเป็นเดือนที่ใกล้ที่สุดหากมีจำนวนเดือนน้อยกว่าจำนวนเต็ม คุณควรแก้ไขคำตอบของคุณเพื่อให้ชัดเจน
จากคำตอบหลาย ๆ คำตอบคำตอบที่ 'ถูกต้อง' ขึ้นอยู่กับสิ่งที่คุณต้องการ ในกรณีของฉันฉันต้องปัดเศษเป็นจำนวนเต็มที่ใกล้เคียงที่สุด
ลองพิจารณาตัวอย่างเหล่านี้ 1 มกราคม -> 31 มกราคม: เป็น 0 ทั้งเดือนและยาวเกือบ 1 เดือน 1 มกราคม -> 1 กุมภาพันธ์? เป็นเวลา 1 เดือนเต็มและยาว 1 เดือน
ในการรับจำนวนเดือนทั้งหมด (สมบูรณ์)ให้ใช้:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
หากต้องการรับระยะเวลาที่ปัดเศษเป็นเดือนคุณสามารถใช้:
SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1
SELECT ROUND(TIMESTAMPDIFF(DAY, '2018-01-01', '2018-01-31')*12/365.24); => 1
ค่านี้มีความแม่นยำถึง +/- 5 วันและสำหรับช่วงมากกว่า 1,000 ปี คำตอบของ Zane นั้นแม่นยำกว่าอย่างเห็นได้ชัด แต่มันเกินไปสำหรับความชอบของฉัน
จากคู่มือ MySQL:
PERIOD_DIFF (P1, P2)
ส่งคืนจำนวนเดือนระหว่างช่วงเวลา P1 และ P2 P1 และ P2 ควรอยู่ในรูปแบบ YYMM หรือ YYYYMM สังเกตว่าอาร์กิวเมนต์ช่วงเวลา P1 และ P2 ไม่ใช่ค่าวันที่
mysql> เลือก PERIOD_DIFF (200802,200703); -> 11
ดังนั้นอาจเป็นไปได้ที่จะทำสิ่งนี้:
Select period_diff(concat(year(d1),if(month(d1)<10,'0',''),month(d1)), concat(year(d2),if(month(d2)<10,'0',''),month(d2))) as months from your_table;
โดยที่ d1 และ d2 เป็นนิพจน์วันที่
ฉันต้องใช้คำสั่ง if () เพื่อให้แน่ใจว่าเดือนนั้นเป็นตัวเลขสองหลักเช่น 02 แทนที่จะเป็น 2
ฉันชอบวิธีนี้เพราะ evryone จะเข้าใจอย่างชัดเจนในแวบแรก:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
มีวิธีที่ดีกว่า? ใช่. อย่าใช้ MySQL Timestamps นอกเหนือจากข้อเท็จจริงที่ว่าพวกเขาใช้ 36 ไบต์แล้วยังไม่สะดวกในการทำงานด้วย ฉันขอแนะนำให้ใช้ Julian Date and Seconds ตั้งแต่เที่ยงคืนสำหรับค่าวันที่ / เวลาทั้งหมด สิ่งเหล่านี้สามารถรวมกันเพื่อสร้าง UnixDateTime หากสิ่งนี้ถูกเก็บไว้ใน DWORD (จำนวนเต็ม 4 ไบต์ที่ไม่ได้ลงนาม) จะสามารถจัดเก็บวันที่ได้ถึง 2106 เป็นวินาทีนับตั้งแต่ epoc 01/01/1970 DWORD max val = 4,294,967,295 - DWORD สามารถถือได้ 136 ปีวินาที
Julian Dates ทำได้ดีมากเมื่อทำการคำนวณวันที่ค่า UNIXDateTime นั้นใช้ได้ดีเมื่อทำการคำนวณวันที่ / เวลาดูไม่ดีดังนั้นฉันจึงใช้การประทับเวลาเมื่อฉันต้องการคอลัมน์ที่ฉันจะไม่ทำการคำนวณมากนัก ด้วย แต่ฉันต้องการการบ่งชี้โดยย่อ
การแปลงเป็นจูเลียนและย้อนกลับสามารถทำได้อย่างรวดเร็วในภาษาที่ดี การใช้พอยน์เตอร์ฉันลดลงเหลือประมาณ 900 Clks (นี่เป็นการแปลงจาก STRING เป็น INTEGER แน่นอน)
เมื่อคุณเข้าสู่แอปพลิเคชันที่จริงจังที่ใช้ข้อมูลวันที่ / เวลาเช่นตลาดการเงินวันที่ของ Julian เป็นจริง
แบบสอบถามจะเป็นดังนี้:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
ให้จำนวนเดือนตามปฏิทินนับตั้งแต่การสร้างข้อมูลล่าสุดในบันทึกของลูกค้าโดยให้ MySQL ทำการเลือกเดือนเป็นการภายใน
DROP FUNCTION IF EXISTS `calcula_edad` $$
CREATE DEFINER=`root`@`localhost` FUNCTION `calcula_edad`(pFecha1 date, pFecha2 date, pTipo char(1)) RETURNS int(11)
Begin
Declare vMeses int;
Declare vEdad int;
Set vMeses = period_diff( date_format( pFecha1, '%Y%m' ), date_format( pFecha2, '%Y%m' ) ) ;
/* Si el dia de la fecha1 es menor al dia de fecha2, restar 1 mes */
if day(pFecha1) < day(pFecha2) then
Set vMeses = VMeses - 1;
end if;
if pTipo='A' then
Set vEdad = vMeses div 12 ;
else
Set vEdad = vMeses ;
end if ;
Return vEdad;
End
select calcula_edad(curdate(),born_date,'M') -- for number of months between 2 dates
เรียกใช้โค้ดนี้และจะสร้างฟังก์ชันลงวันที่ความแตกต่างซึ่งจะให้ความแตกต่างในรูปแบบวันที่ yyyy-mm-dd
DELIMITER $$
CREATE FUNCTION datedifference(date1 DATE, date2 DATE) RETURNS DATE
NO SQL
BEGIN
DECLARE dif DATE;
IF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < 0 THEN
SET dif=DATE_FORMAT(
CONCAT(
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 ,
'-',
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 ,
'-',
DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(DATE_SUB(date1, INTERVAL 1 MONTH)), '-', DAY(date2))))),
'%Y-%m-%d');
ELSEIF DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2)))) < DAY(LAST_DAY(DATE_SUB(date1, INTERVAL 1 MONTH))) THEN
SET dif=DATE_FORMAT(
CONCAT(
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 ,
'-',
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 ,
'-',
DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
'%Y-%m-%d');
ELSE
SET dif=DATE_FORMAT(
CONCAT(
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))DIV 12 ,
'-',
PERIOD_DIFF(date_format(date1, '%y%m'),date_format(date2, '%y%m'))% 12 ,
'-',
DATEDIFF(date1, DATE(CONCAT(YEAR(date1),'-', MONTH(date1), '-', DAY(date2))))),
'%Y-%m-%d');
END IF;
RETURN dif;
END $$
DELIMITER;
ขึ้นอยู่กับว่าคุณต้องการกำหนด # เดือนอย่างไร ตอบคำถามนี้: 'เดือนที่แตกต่างกันคืออะไร: 15 ก.พ. 2551-12 มี.ค. 2552' กำหนดโดยการตัด # ของวันที่ชัดเจนซึ่งขึ้นอยู่กับปีอธิกสุรทิน - เดือนอะไรหรือวันเดียวกันของเดือนก่อนหน้า = 1 เดือน
การคำนวณวัน :
15 ก.พ. -> 29 (ปีอธิกสุรทิน) = 14 1 มี.ค. 2551 + 365 = 1 มี.ค. 2552 1 มี.ค. -> 12 มี.ค. = 12 วัน 14 + 365 + 12 = 391 วัน. รวม = 391 วัน / (วันเฉลี่ยในเดือน = 30) = 13.03333
การคำนวณเดือน :
15 ก.พ. 2551 - 15 ก.พ. 2552 = 12 ก.พ. 58 -> 12 มี.ค. = น้อยกว่า 1 เดือนรวม = 12 เดือนหรือ 13 ก.พ. 15 - 12 มี.ค. ถือเป็น "เดือนที่ผ่านมา"
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
ฉันต้องการความแตกต่างของเดือนด้วยความแม่นยำ แม้ว่าวิธีการแก้ปัญหาของ Zane Bien จะเป็นไปในทิศทางที่ถูกต้อง แต่ตัวอย่างที่สองและสามของเขาให้ผลลัพธ์ที่ไม่ถูกต้อง วันในเดือนกุมภาพันธ์หารด้วยจำนวนวันในเดือนกุมภาพันธ์ไม่เท่ากับวันในเดือนพฤษภาคมหารด้วยจำนวนวันในเดือนพฤษภาคม ดังนั้นตัวอย่างที่สองควรแสดงผล ((31-5 + 1) / 31 + 13/30 =) 1.3043 และตัวอย่างที่สาม ((29-27 + 1) / 29 + 2/30 + 3 =) 3.1701
ฉันลงเอยด้วยคำถามต่อไปนี้:
SELECT
'2012-02-27' AS startdate,
'2012-06-02' AS enddate,
TIMESTAMPDIFF(DAY, (SELECT startdate), (SELECT enddate)) AS days,
IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), 0, (TIMESTAMPDIFF(DAY, (SELECT startdate), LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY)) / DAY(LAST_DAY((SELECT startdate)))) AS period1,
TIMESTAMPDIFF(MONTH, LAST_DAY((SELECT startdate)) + INTERVAL 1 DAY, LAST_DAY((SELECT enddate))) AS period2,
IF(MONTH((SELECT startdate)) = MONTH((SELECT enddate)), (SELECT days), DAY((SELECT enddate))) / DAY(LAST_DAY((SELECT enddate))) AS period3,
(SELECT period1) + (SELECT period2) + (SELECT period3) AS months
คุณสามารถรับปีเดือนและวันด้วยวิธีนี้:
SELECT
username
,date_of_birth
,DATE_FORMAT(CURDATE(), '%Y') - DATE_FORMAT(date_of_birth, '%Y') - (DATE_FORMAT(CURDATE(), '00-%m-%d') < DATE_FORMAT(date_of_birth, '00-%m-%d')) AS years
,PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(date_of_birth, '%Y%m') ) AS months
,DATEDIFF(CURDATE(),date_of_birth) AS days
FROM users
คุณยังสามารถลองสิ่งนี้:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
หรือ
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
คำตอบง่ายๆให้วันที่เริ่มต้นเป็น ins_frm และวันที่สิ้นสุดเป็น ins_to
SELECT convert(TIMESTAMPDIFF(year, ins_frm, ins_to),UNSIGNED) as yrs,
mod(TIMESTAMPDIFF(MONTH, ins_frm, ins_to),12) mnths
FROM table_name
สนุก :)))
ลองทำตามนี้
SELECT YEAR(end_date)*12 + MONTH(end_date) - (YEAR(start_date)*12 + MONTH(start_date))
แบบสอบถามนี้ใช้ได้ผลสำหรับฉัน :)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
ใช้เวลาเพียงสองวันและดึงค่าระหว่างพวกเขา