Tôi đang tìm cách tính số tháng giữa 2 trường thời gian ngày tháng.
Có cách nào tốt hơn là lấy dấu thời gian unix và số chia cho 2 592 000 (giây) và làm tròn trong MySQL không?
Tôi đang tìm cách tính số tháng giữa 2 trường thời gian ngày tháng.
Có cách nào tốt hơn là lấy dấu thời gian unix và số chia cho 2 592 000 (giây) và làm tròn trong MySQL không?
Câu trả lời:
Hàm DATEDIFF có thể cung cấp cho bạn số ngày giữa hai ngày. Cái nào chính xác hơn, vì ... làm thế nào để bạn xác định một tháng? (28, 29, 30 hay 31 ngày?)
PERIODDIFF
chỉ cần lấy giá trị YYYYMM, vì vậy trừ khi bạn tự tính số ngày trước khi vượt qua giá trị YYYYMM, thì tất cả những gì bạn đang tính là số tháng, được làm tròn đến tháng gần nhất nếu có ít hơn một số tháng. Hãy xem câu trả lời của Zane bên dưới.
PERIODDIFF
nhận xét? Định kỳ không tính giá trị ngày, vì vậy bạn đang tính số tháng được làm tròn đến tháng gần nhất nếu có ít hơn một số tháng
Tôi ngạc nhiên là điều này vẫn chưa được đề cập:
Hãy xem hàm TIMESTAMPDIFF () trong MySQL.
Những gì điều này cho phép bạn làm là chuyển hai TIMESTAMP
hoặc DATETIME
giá trị (hoặc thậm chí DATE
khi MySQL sẽ tự động chuyển đổi) cũng như đơn vị thời gian bạn muốn dựa trên sự khác biệt của mình.
Bạn có thể chỉ định MONTH
làm đơn vị trong tham số đầu tiên:
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
Về cơ bản, nó lấy số tháng trôi qua kể từ ngày đầu tiên trong danh sách tham số. Giải pháp này tự động bù cho lượng ngày khác nhau trong mỗi tháng (28,30,31) cũng như tính đến các năm nhuận - bạn không phải lo lắng về bất kỳ điều gì trong số đó.
Sẽ phức tạp hơn một chút nếu bạn muốn giới thiệu độ chính xác thập phân theo số tháng đã trôi qua, nhưng đây là cách bạn có thể làm điều đó:
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
)
Các tham số ngày của bạn ở đâu startdate
và ở đâu enddate
, cho dù đó là từ hai cột ngày trong bảng hay dưới dạng tham số đầu vào từ tập lệnh:
Ví dụ:
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
bình luận về câu trả lời được lựa chọn rất bỏ lỡ hàng đầu
PERIOD_DIFF tính toán các tháng giữa hai ngày.
Ví dụ: để tính toán sự khác biệt giữa now () và một cột thời gian trong your_table:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
Tôi cũng sử dụng PERIODDIFF . Để lấy năm và tháng trong ngày, tôi sử dụng hàm EXTRACT :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
DATE_FORMAT
theo phương pháp đó , cảm ơn! +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
không tính giá trị ngày, vì vậy bạn đang tính số tháng được làm tròn đến tháng gần nhất nếu có ít hơn một số tháng. Bạn nên chỉnh sửa câu trả lời của mình để làm rõ điều này.
Như nhiều câu trả lời ở đây cho thấy, câu trả lời 'đúng' phụ thuộc vào chính xác những gì bạn cần. Trong trường hợp của tôi, tôi cần làm tròn đến số nguyên gần nhất .
Hãy xem xét những ví dụ sau: Ngày 1 tháng 1 -> ngày 31 tháng 1: Đó là 0 tháng và dài gần 1 tháng. 1 tháng 1 -> 1 tháng 2? Đó là 1 tháng, và đúng 1 tháng.
Để nhận số tháng toàn bộ (đầy đủ) , hãy sử dụng:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
Để có được khoảng thời gian làm tròn theo tháng, bạn có thể sử dụng:
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
Điều này chính xác đến +/- 5 ngày và trong phạm vi hơn 1000 năm. Câu trả lời của Zane rõ ràng là chính xác hơn, nhưng nó quá dài so với ý thích của tôi.
Từ hướng dẫn sử dụng MySQL:
PERIOD_DIFF (P1, P2)
Trả về số tháng giữa các khoảng thời gian P1 và P2. P1 và P2 phải ở định dạng YYMM hoặc YYYYMM. Lưu ý rằng các đối số dấu chấm P1 và P2 không phải là giá trị ngày tháng.
mysql> CHỌN PERIOD_DIFF (200802,200703); -> 11
Vì vậy, có thể làm một cái gì đó như sau:
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;
Trong đó d1 và d2 là biểu thức ngày tháng.
Tôi phải sử dụng câu lệnh if () để đảm bảo rằng các tháng là một số có hai chữ số như 02 thay vì 2.
Tôi thích cách này hơn, vì ngay từ cái nhìn đầu tiên, evryone sẽ hiểu rõ ràng:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
Có cách nào tốt hơn? Đúng. Không sử dụng MySQL Timestamps. Ngoài thực tế là chúng chiếm 36 Byte, chúng không thuận tiện chút nào để làm việc. Tôi khuyên bạn nên sử dụng Ngày và Giây Julian từ nửa đêm cho tất cả các giá trị ngày / giờ. Chúng có thể được kết hợp để tạo thành UnixDateTime. Nếu dữ liệu này được lưu trữ trong DWORD (Số nguyên 4 Byte chưa được đánh dấu) thì các ngày trong khoảng thời gian lên đến 2106 có thể được lưu trữ dưới dạng giây kể từ epoc, 01/01/1970 DWORD max val = 4,294,967,295 - DWORD có thể chứa 136 năm Giây
Julian Dates rất tốt để làm việc khi thực hiện các phép tính ngày Các giá trị UNIXDateTime rất tốt để làm việc khi thực hiện các phép tính Ngày / Giờ Cả hai đều không tốt để xem xét, vì vậy tôi sử dụng Dấu thời gian khi tôi cần một cột mà tôi sẽ không tính toán nhiều với, nhưng tôi muốn có một chỉ dẫn trong nháy mắt.
Chuyển đổi sang Julian và ngược lại có thể được thực hiện rất nhanh chóng bằng một ngôn ngữ tốt. Sử dụng con trỏ, tôi có khoảng 900 Clks (Tất nhiên, đây cũng là một chuyển đổi từ STRING thành INTEGER)
Khi bạn tham gia vào các ứng dụng nghiêm túc sử dụng thông tin Ngày / Giờ, chẳng hạn như thị trường tài chính, ngày tháng Julian là thực tế.
Truy vấn sẽ như sau:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Cung cấp một số tháng theo lịch kể từ khi dấu dữ liệu được tạo trên hồ sơ khách hàng, cho phép MySQL thực hiện lựa chọn tháng trong nội bộ.
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
Thực thi mã này và nó sẽ tạo ra một hàm dateeifference sẽ cung cấp cho bạn sự khác biệt về định dạng ngày 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;
Điều này phụ thuộc vào cách bạn muốn xác định # tháng. Trả lời câu hỏi này: 'Sự khác biệt trong các tháng: 15 tháng 2 năm 2008 - 12 tháng 3 năm 2009'. Nó được xác định bằng số ngày rõ ràng phụ thuộc vào năm nhuận - tháng đó là tháng nào, hoặc cùng ngày của tháng trước = 1 tháng.
Một phép tính cho Ngày :
Ngày 15 tháng 2 -> 29 (năm nhuận) = 14 ngày 1 tháng 3 năm 2008 + 365 = ngày 1 tháng 3 năm 2009. Ngày 1 tháng 3 -> 12 tháng 3 = 12 ngày. 14 + 365 + 12 = 391 ngày. Tổng cộng = 391 ngày / (số ngày trung bình trong tháng = 30) = 13.03333
Cách tính tháng :
Ngày 15 tháng 2 năm 2008 - ngày 15 tháng 2 năm 2009 = 12 ngày 15 tháng 2 -> ngày 12 tháng 3 = dưới 1 tháng Tổng cộng = 12 tháng hoặc 13 nếu ngày 15 tháng 3 - ngày 12 tháng 3 được coi là 'tháng trước'
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
Tôi cần sự khác biệt theo tháng với độ chính xác. Mặc dù giải pháp của Zane Bien là đúng hướng, nhưng ví dụ thứ hai và thứ ba của anh ấy cho kết quả không chính xác. Một ngày trong tháng Hai chia cho số ngày trong tháng Hai không bằng một ngày trong tháng Năm chia cho số ngày trong tháng Năm. Vì vậy, ví dụ thứ hai sẽ xuất ra ((31-5 + 1) / 31 + 13/30 =) 1.3043 và ví dụ thứ ba ((29-27 + 1) / 29 + 2/30 + 3 =) 3.1701.
Tôi đã kết thúc với truy vấn sau:
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
Bạn có thể nhận được năm, tháng và ngày theo cách này:
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
Bạn cũng có thể thử điều này:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
HOẶC LÀ
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
Truy vấn này phù hợp với tôi :)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
Chỉ cần mất hai ngày và truy xuất các giá trị giữa chúng.