두 날짜 시간 필드 사이의 개월 수를 계산하려고합니다.
유닉스 타임 스탬프를 얻고 2 592 000 (초)로 나누고 MySQL을 반올림하는 것보다 더 좋은 방법이 있습니까?
답변:
DATEDIFF의 함수는 두 날짜 사이에 당신의 일 수를 제공 할 수 있습니다. 어느 쪽이 더 정확합니까? 왜냐하면 ... 한 달을 어떻게 정의합니까? (28 일, 29 일, 30 일 또는 31 일?)
PERIODDIFF
단순히 YYYYMM 값을 취하므로 YYYYMM 값을 전달하기 전에 직접 날짜를 고려하지 않는 한 계산하는 모든 것은 월 수이며, 전체 월 수가 적은 경우 가장 가까운 월로 반올림됩니다. 아래 Zane의 답변을 참조하십시오.
PERIODDIFF
댓글에 대한 찬성표가 많은 이유는 무엇 입니까? Perioddiff는 일 값을 사용하지 않으므로 전체 개월 수보다 적은 경우 가장 가까운 달로 반올림 한 개월 수를 계산합니다
나는 이것이 아직 언급되지 않은 것에 놀랐다.
MySQL 의 TIMESTAMPDIFF () 함수를 살펴보십시오 .
이것이 당신이 할 수있는 것은 차이를 기반으로 할 시간 단위뿐만 아니라 두 개의 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 월 1 일-> 1 월 31 일 : 전체 0 개월, 거의 1 개월 길이입니다. 1 월 1 일-> 2 월 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 일까지 정확하며 1000 년 이상의 범위에 대해 정확합니다. Zane의 대답은 분명히 더 정확하지만 내 취향에 비해 너무 장황합니다.
MySQL 매뉴얼에서 :
PERIOD_DIFF (P1, P2)
기간 P1과 P2 사이의 개월 수를 반환합니다. P1 및 P2는 YYMM 또는 YYYYMM 형식이어야합니다. 기간 인수 P1 및 P2는 날짜 값이 아닙니다.
mysql> SELECT 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는 날짜 표현식입니다.
월이 2가 아닌 02와 같은 두 자리 숫자인지 확인하기 위해 if () 문을 사용해야했습니다.
evryone이 언뜻보기에 명확하게 이해할 것이기 때문에 저는이 방법을 선호합니다.
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
더 좋은 방법이 있습니까? 예. MySQL 타임 스탬프를 사용하지 마십시오. 36 바이트를 차지한다는 사실을 제외하고는 작업하기에 전혀 편리하지 않습니다. 모든 날짜 / 시간 값에 대해 자정부터 Julian Date 및 Seconds를 사용하는 것이 좋습니다. 이들을 결합하여 UnixDateTime을 형성 할 수 있습니다. 이것이 DWORD (부호없는 4 바이트 정수)에 저장되면 epoc, 01/01/1970 DWORD max val = 4,294,967,295-DWORD는 136 년의 초를 저장할 수 있습니다.
Julian Dates는 날짜 계산을 할 때 사용하기에 매우 좋습니다. UNIXDateTime 값은 날짜 / 시간 계산을 할 때 사용하기에 좋습니다. 둘 다보기에는 좋지 않으므로 많은 계산을 수행하지 않을 열이 필요할 때 Timestamps를 사용합니다. 하지만 한눈에 표시하고 싶습니다.
줄리안으로 변환했다가 되 돌리는 것은 좋은 언어로 매우 빠르게 수행 할 수 있습니다. 포인터를 사용하면 약 900 Clks까지 내려갑니다 (물론 STRING에서 INTEGER 로의 변환이기도합니다).
예를 들어 금융 시장과 같은 날짜 / 시간 정보를 사용하는 심각한 애플리케이션에 들어가면 율리우스 력 날짜는 사실상 사실입니다.
쿼리는 다음과 같습니다.
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의 차이를 제공하는 datedeifference 함수가 생성됩니다.
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;
이것은 정의 할 개월 수에 따라 다릅니다. '달의 차이는 무엇입니까 : 2008 년 2 월 15 일-2009 년 3 월 12 일'질문에 답하십시오. 윤년에 따라 달라지는 명확한 일 수로 정의됩니까-월이 무엇입니까, 아니면 전월의 같은 날 = 1 개월입니까?
일에 대한 계산 :
2 월 15 일-> 29 일 (윤년) = 2008 년 3 월 1 일 + 365 = 2009 년 3 월 1 일. 3 월 1 일-> 3 월 12 일 = 12 일. 14 + 365 + 12 = 391 일. 합계 = 391 일 / (월 평균 일수 = 30) = 13.03333
월 계산 :
2008 년 2 월 15 일-2009 년 2 월 15 일 = 2 월 15 일-> 3 월 12 일 = 1 개월 미만 합계 = 12 개월 또는 2 월 15 일-3 월 12 일이 '지난 달'로 간주되는 경우 13
나는 정확한 월 차이가 필요했습니다. Zane Bien의 솔루션은 올바른 방향이지만 그의 두 번째 및 세 번째 예는 부정확 한 결과를 제공합니다. 2 월의 하루를 2 월의 일 수로 나눈 값은 5 월의 하루를 5 월의 일 수로 나눈 값과 같지 않습니다. 따라서 두 번째 예는 ((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;
이 시도
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'
두 개의 날짜를 취하고 그 사이의 값을 검색합니다.