2008-11-14 18 views

Odpowiedz

16

Funkcja DATEDIFF może podać liczbę dni między dwiema datami. Co jest dokładniejsze, od kiedy ... jak definiujesz miesiąc? (28, 29, 30 lub 31 dni?)

+48

[PERIODDIFF] (http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_period-diff) może dokładnie obliczyć liczbę miesięcy. –

+6

"Bardziej dokładne" jest niewiarygodnie subiektywne, jeśli chodzi o daty. Jeśli na przykład jesteś w firmie, która ma cykle miesięczne, które muszą wiedzieć, ile miesięcy znajduje się między dwiema datami, może być ważniejsza niż liczba dni z tego samego powodu, który podano powyżej. Jak długi jest miesiąc? Jeśli potrzebuję liczenia miesięcy, nie mogę po prostu podzielić przez 30. –

+5

To nie jest poprawna odpowiedź; powinieneś oznaczyć odpowiedź [Max's] (http://stackoverflow.com/a/562477/389034) poniżej. –

1

To zależy od tego, jak chcesz zdefiniować # miesięcy. Odpowiedz na te pytania: "Jaka jest różnica w miesiącach: 15 lutego 2008 r. - 12 marca 2009 r.". Czy jest zdefiniowany przez czysty czas # dni, który zależy od lat przestępnych - w którym miesiącu jest, lub tego samego dnia poprzedniego miesiąca = 1 miesiąc.

Obliczenia na Dniach:

15 luty -> 29 (rok przestępny) = 14 01 marca, 2008 + 365 = 01 marca 2009. Mar 1 -> Mar 12 = 12 dni. 14 + 365 + 12 = 391 dni. Razem = 391 dni/(Śr dni w miesiącu = 30) = 13,03333

Obliczenie miesięcy:

15 lut 2008 - 15 lutego 2009 = 12 15 lutego -> mar 12 = mniej niż 1 miesiąc Razem = 12 miesięcy lub 13 czy 15 lutego - 12 marca uważany jest za 'przeszłość miesięcy'

7

z podręcznika MySQL:

PERIOD_DIFF (P1, P2)

Zwraca liczbę miesięcy między okresami P1 i P2. P1 i P2 powinny mieć format YYMM lub RRRRMM. Zauważ, że argumenty okresu P1 i P2 nie są wartościami daty.

mysql> SELECT PERIOD_DIFF (200802,200703); -> 11

Więc może to być możliwe, aby zrobić coś takiego:

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; 

Gdzie D1 i D2 są wyrażenia data.

musiałem użyć jeśli() oświadczenia, aby upewnić się, że było kilka miesięcy dwie cyfry jak 02 zamiast 2.

1
SELECT * 
FROM emp_salaryrevise_view 
WHERE curr_year Between '2008' AND '2009' 
    AND MNTH Between '12' AND '1' 
6

Czy istnieje lepszy sposób? tak. Nie używaj znaczników czasu MySQL. Poza tym, że zajmują 36 Bajtów, nie są w ogóle wygodne do pracy. Polecam używanie dat Juliańskich i sekund od północy dla wszystkich wartości daty/czasu. Można je łączyć, tworząc UnixDateTime.Jeśli jest przechowywany w DWORD (unsigned 4 Byte Integer), to data sięga aż do 2106 może być zapisana jako sekunda od epoc, 01/01/1970 DWORD max val = 4 294 967 295 - DWORD może pomieścić 136 lat Sekund

Daty Julian są bardzo przyjemne w pracy przy obliczaniu daty Wartości UNIXDateTime dobrze sprawdzają się przy dokonywaniu obliczeń Data/Czas Nie warto też patrzeć, więc używam znaczników czasu, kiedy potrzebuję kolumny, którą będę nie licząc się z dużymi kalkulacjami, ale chcę uzyskać natychmiastowe wskazanie.

Nawrócenie na język juliański iz powrotem można wykonać bardzo szybko w dobrym języku. Używając wskaźników mam go do około 900 Clks (jest to również konwersja z STRINGa na INTEGER oczywiście)

Kiedy dostajesz się do poważnych aplikacji, które używają informacji Data/Czas, takich jak na przykład rynki finansowe, daty juliańskie są de facto.

+0

gdzie Czy dostałeś informację o * tym, że zajmują 36 bajtów *? Wymagania dla pamięci podręcznej MySQL dla kolumny TIMESTAMP wynoszą ** 4 bajty **. http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html – poncha

+0

już teraz zacznij planowanie błędu Y2106! ;-) – ErichBSchulz

93

oblicza miesiące między dwiema datami.

Na przykład, do obliczania różnicy między jest() i kolumnę czasową your_table:

select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table; 
+1

Każdy pomysł, co robi, gdy może to być 11 miesięcy i 1 dzień, więc 12 miesięcy, ale jeśli zmienisz na 30 dni miesięcy, to nadal będzie 11? –

+1

11 miesięcy i 1 dzień zwróci 11 miesięcy z powyższym przykładem. PERIOD_DIFF nie ma poczucia 30 względem 31 dni. –

3

zapytaniu są następująco:

select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where.. 

daje szereg miesiące kalendarzowe, ponieważ Stworzono datestamp na rekordzie klienta, pozwalając MySQL na wewnętrzną selekcję miesięcy.

-1

To zapytanie pracował dla mnie :)

SELECT * FROM tbl_purchase_receipt 
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09' 

To po prostu wziąć dwie daty i pobiera wartości między nimi.

+0

całkowicie niepoprawna odpowiedź, chce liczbę miesięcy –

7

Wolę w ten sposób, ponieważ evryone go zrozumie wyraźnie na pierwszy rzut oka:

SELECT 
    12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months 
FROM 
    tab; 
2
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 
22

używam również PERIODDIFF. Aby uzyskać roku i miesiąca od daty, używam funkcji EXTRACT:

SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table; 
+2

Niesamowite! Wykorzystuje on o 50% mniej czasu niż metoda "DATE_FORMAT", dzięki! +1 –

+1

Tutaj dla unix timestamp 'WYBIERZ PERIOD_DIFF (EKSTRAKT (YEAR_MONTH FROM TERAZ()), EKSTRAKT (YEAR_MONTH OD FROM_UNIXTIME (czas,"% Y% m% d "))) AS miesięcy od your_table;' – Smolla

+2

To jest niepoprawne, PERIOD_DIFF' nie uwzględnia wartości dni, więc obliczasz liczbę miesięcy zaokrąglonych w górę do najbliższego miesiąca, jeśli jest mniej niż cała liczba miesięcy. Powinieneś edytować swoją odpowiedź, aby to wyjaśnić. – rgvcorley

2

wykonanie tego kodu i będzie utworzyć funkcję datedeifference które dadzą Ci różnicę w formacie daty rrrr-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; 
+1

Czy sądzisz, że mógłbyś trochę wyczyścić i skomentować swój kod, więc jest to trochę bardziej zrozumiałe? Dzięki –

145

miesiąc-różnica między dowolnymi dwoma podanymi datami:

Dziwię ten nie został jeszcze wymienić:

Zapraszamy do obejrzenia funkcji w MySQL TIMESTAMPDIFF().

Co to pozwala zrobić to wprost w dwóch TIMESTAMP lub DATETIME wartości (lub nawet DATE jak MySQL będzie automatycznie przeliczać), jak również jednostka czasu chcesz oprzeć na różnicę.

Można określić MONTH jako jednostki w pierwszym parametrze:

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-04') 
-- Outputs: 0 


SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-06-15') 
-- Outputs: 1 

SELECT TIMESTAMPDIFF(MONTH, '2012-05-05', '2012-12-16') 
-- Outputs: 7 

Zasadniczo dostaje numer miesięcy, które upłynęły od pierwszej daty listy parametrów. To rozwiązanie automatycznie rekompensuje różną liczbę dni w każdym miesiącu (28,30,31), a także biorąc pod uwagę lata przestępne —, nie musisz się martwić o nic z tego.


Miesiąc różnicy z precyzją:

To trochę bardziej skomplikowane, jeśli chcesz wprowadzić dokładność dziesiętną liczby miesięcy upłynął, ale tutaj jest to, jak można to zrobić:

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 
) 

Gdzie startdate i enddate są twoje parametry tej pory, czy to z dwóch dat kolumn w tabeli lub parametrów wejściowych ze skryptu:

Przykłady:

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 
+3

To jest poprawna odpowiedź, wszystkie notatki do wpisu 'PERIODDIFF' na temat wybranej odpowiedzi są bardzo niefortunne – rgvcorley

+3

Dzięki, w moim przypadku potrzebowałem włącznie dat, więc zastępuję wszystkie" enddate "przez" date_add (enddate, interwał 1 dzień) ". Wówczas od 2014-03-01 do 2014-05-31 otrzymasz 3,00 zamiast 2,97 –

+1

Dziękuję bardzo .....special thanx dla "Dokładność miesiąca z dokładnością:". Jesteś gwiazdą mysql – Vidhi

0

można uzyskać lat, miesięcy i dni w ten sposób:

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 
1

Potrzebowałem miesiąc różnicy z precyzją. Chociaż rozwiązanie Zane Bien jest we właściwym kierunku, jego drugi i trzeci przykład dają niedokładne wyniki. Dzień w lutym podzielony przez liczbę dni w lutym nie jest równy jednemu dniu w maju podzielonemu przez liczbę dni w maju. Tak więc drugi przykład powinien wyprowadzić ((31-5 + 1)/31 + 13/30 =) 1,3043 a trzeci przykład ((29-27 + 1)/29 + 2/30 + 3 =) 3,1701.

skończyło się następujące zapytanie:

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 
0

Można również spróbować tego:

select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name; 

LUB

select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name; 
3

Ponieważ wiele odpowiedzi tutaj Pokazują, " odpowiednia odpowiedź zależy od tego, czego dokładnie potrzebujesz. W moim przypadku muszę w rundzie do najbliższej liczby całkowitej.

Weź pod uwagę następujące przykłady: 1 stycznia -> 31 stycznia: 0 miesięcy i prawie 1 miesiąc. 1 stycznia -> 1 lutego? Jest to 1 miesiąc i dokładnie 1 miesiąc.

Aby uzyskać liczbę całych miesięcy, przeznaczenie:

SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0 
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1 

dostać zaokrąglone czas w miesiącach, można użyć:

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 

To jest z dokładnością do +/- 5 dni i dla zakresów powyżej 1000 lat. Odpowiedź Zane'a jest oczywiście bardziej dokładna, ale jest zbyt szczegółowa, jak mi się podoba.