2 tarih ve saat alanı arasındaki ay sayısını hesaplamak istiyorum.
Unix zaman damgasını alıp 2 592 000 (saniye) bölüp MySQL içinde yuvarlamaktan daha iyi bir yol var mı?
2 tarih ve saat alanı arasındaki ay sayısını hesaplamak istiyorum.
Unix zaman damgasını alıp 2 592 000 (saniye) bölüp MySQL içinde yuvarlamaktan daha iyi bir yol var mı?
Yanıtlar:
DATEDIFF işlevi, iki tarih arasındaki gün için size numarasını verebilirim. Hangisi daha doğrudur, çünkü ... bir ayı nasıl tanımlarsınız? (28, 29, 30 veya 31 gün?)
PERIODDIFF
sadece bir YYYYMM değeri alır, bu nedenle YYYYMM değerlerini geçmeden önceki günleri hesaba katmazsanız, hesapladığınız tek şey ay sayısıdır ve tam sayıdan az ay varsa en yakın aya yuvarlanır. Aşağıdaki Zane'nin cevabına bakın.
PERIODDIFF
Yorum için neden bu kadar çok olumlu oy var ? Perioddiff gün değerlerini almaz, bu nedenle tam sayıdan daha az ay varsa en yakın aya yuvarlanan ayların sayısını
Bundan henüz bahsedilmemesine şaşırdım:
MySQL'deki TIMESTAMPDIFF () işlevine bir göz atın .
Bunun yapmanıza izin verdiği şey, iki TIMESTAMP
veya DATETIME
değer (veya DATE
MySQL'in otomatik olarak dönüştüğü gibi) ve farkınızı temel almak istediğiniz zaman birimini aktarmaktır.
MONTH
İlk parametrede birim olarak belirtebilirsiniz :
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
Temel olarak parametre listesindeki ilk tarihten itibaren geçen ay sayısını alır. Bu çözüm, her ayın değişen gün sayısını (28,30,31) otomatik olarak telafi eder ve artık yılları da hesaba katar - bunlardan hiçbiri için endişelenmenize gerek yoktur.
Geçen ay sayısında ondalık kesinlik eklemek istiyorsanız bu biraz daha karmaşıktır, ancak bunu şu şekilde yapabilirsiniz:
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
)
Bir tablodaki iki tarih sütunundan veya bir koddan girdi parametreleri olarak tarih parametreleriniz nerede startdate
ve nerede?enddate
Örnekler:
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
seçilen cevapla ilgili yorum için tüm olumlu oylar çok
PERIOD_DIFF , iki tarih arasındaki ayları hesaplar.
Örneğin, now () ile tablonuzdaki bir zaman sütunu arasındaki farkı hesaplamak için:
select period_diff(date_format(now(), '%Y%m'), date_format(time, '%Y%m')) as months from your_table;
Ayrıca PERIODDIFF kullanıyorum . Tarihin yılını ve ayını almak için EXTRACT işlevini kullanıyorum :
SELECT PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM NOW()), EXTRACT(YEAR_MONTH FROM time)) AS months FROM your_table;
DATE_FORMAT
yöntemi % 50 daha az kullanır , teşekkürler! +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
gün değerlerini almaz, bu nedenle tam sayıdan daha az ay varsa en yakın aya yuvarlanmış ay sayısını hesaplıyorsunuz. Bunu netleştirmek için cevabınızı düzenlemelisiniz.
Buradaki cevapların çoğunun gösterdiği gibi, 'doğru' cevap tam olarak neye ihtiyacınız olduğuna bağlıdır. Benim durumumda, en yakın tam sayıya yuvarlamam gerekiyor .
Şu örnekleri düşünün: 1 Ocak -> 31 Ocak: 0 tam ay ve neredeyse 1 ay sürüyor. 1 Ocak -> 1 Şubat? Tam 1 ay ve tam olarak 1 ay sürüyor.
Tam (tam) ayların sayısını elde etmek için şunu kullanın:
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-01-31'); => 0
SELECT TIMESTAMPDIFF(MONTH, '2018-01-01', '2018-02-01'); => 1
Ay olarak yuvarlatılmış bir süre elde etmek için şunları kullanabilirsiniz:
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
Bu +/- 5 güne kadar ve 1000 yılı aşan aralıklar için doğrudur. Zane'nin cevabı açıkça daha doğru, ama benim beğenime göre fazla ayrıntılı.
MySQL kılavuzundan:
PERIOD_DIFF (P1; P2)
P1 ve P2 dönemleri arasındaki ay sayısını döndürür. P1 ve P2, YYMM veya YYYYMM formatında olmalıdır. P1 ve P2 dönem bağımsız değişkenlerinin tarih değerleri olmadığını unutmayın.
mysql> SEÇİM SÜRESİ_DIFF (200802,200703); -> 11
Bu yüzden şöyle bir şey yapmak mümkün olabilir:
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 ve d2, tarih ifadeleridir.
Ayların 2 yerine 02 gibi iki basamaklı bir sayı olduğundan emin olmak için if () ifadelerini kullanmak zorunda kaldım.
Bu yolu tercih ederim, çünkü herkes ilk bakışta bunu açıkça anlayacaktır:
SELECT
12 * (YEAR(to) - YEAR(from)) + (MONTH(to) - MONTH(from)) AS months
FROM
tab;
Daha iyi bir yol var mı? Evet. MySQL Zaman Damgalarını kullanmayın. 36 Byte'ı işgal etmelerinin yanı sıra, çalışmak için hiç de uygun değiller. Tüm tarih / saat değerleri için gece yarısından itibaren Julian Tarih ve Saniyelerini kullanmanızı tavsiye ederim. Bunlar bir UnixDateTime oluşturmak için birleştirilebilir. Bu bir DWORD'de (işaretsiz 4 Bayt Tamsayı) depolanırsa, epoc, 01/01/1970 DWORD max val = 4,294,967,295'ten bu yana 2106'ya kadar olan tarihler saniyeler olarak saklanabilir - Bir DWORD 136 yıllık Saniyeyi tutabilir
Jülyen Tarihleri, tarih hesaplamaları yaparken çalışmak çok güzel Tarih / Saat hesaplamaları yaparken UNIXDateTime değerleri ile çalışmak iyidir İkisine de bakılması iyi değildir, bu yüzden çok fazla hesaplama yapmayacağım bir sütuna ihtiyacım olduğunda Zaman Damgalarını kullanırım ile, ancak bir bakışta gösterge istiyorum.
Jülyen'e ve geri dönüş, iyi bir dilde çok hızlı bir şekilde yapılabilir. İşaretçileri kullanarak bunu yaklaşık 900 Clks'ye düşürdüm (Bu aynı zamanda STRING'den INTEGER'a bir dönüşüm tabii ki)
Örneğin finans piyasaları gibi Tarih / Saat bilgilerini kullanan ciddi uygulamalara girdiğinizde, Jülyen tarihleri fiilen geçerlidir.
Sorgu şöyle olacaktır:
select period_diff(date_format(now(),"%Y%m"),date_format(created,"%Y%m")) from customers where..
Bir müşteri kaydında oluşturulan tarih damgasından bu yana, MySQL'in dahili olarak ay seçimini yapmasına izin vererek birkaç takvim ayı verir.
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
Bu kodu çalıştırın ve size yyyy-aa-gg tarih biçiminde fark verecek bir işlev tarih farkı yaratacaktır.
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;
Bu, # ayın nasıl tanımlanmasını istediğinize bağlıdır. Şu soruları yanıtlayın: 'Aylarda fark nedir: 15 Şubat 2008 - 12 Mart 2009'. Artık yıllara bağlı olan net kesim sayısı ile mi tanımlanır - hangi ay olduğu veya önceki ayın aynı günü = 1 ay.
Günler için bir hesaplama :
15 Şubat -> 29 (artık yıl) = 14 Mart 1, 2008 + 365 = 1 Mart 2009. 1 Mart -> 12 Mart = 12 gün. 14 + 365 + 12 = 391 gün. Toplam = 391 gün / (aydaki ortalama gün sayısı = 30) = 13.03333
Ayların hesaplanması :
15 Şubat 2008 - 15 Şubat 2009 = 12 Şubat 15 -> 12 Mart = 1 aydan az Toplam = 12 ay veya 15 Şubat - 12 Mart 'geçen ay' olarak kabul edilirse 13
SELECT *
FROM emp_salaryrevise_view
WHERE curr_year Between '2008' AND '2009'
AND MNTH Between '12' AND '1'
Kesinlikle ay farkına ihtiyacım vardı. Zane Bien'in çözümü doğru yönde olsa da, ikinci ve üçüncü örnekleri yanlış sonuçlar veriyor. Şubat ayındaki bir günün, Şubat ayındaki gün sayısına bölünmesi, Mayıs ayındaki bir günün Mayıs ayındaki gün sayısına bölünmesiyle elde edilen değere eşit değildir. Yani ikinci örnek ((31-5 + 1) / 31 + 13/30 =) 1.3043 ve üçüncü örnek ((29-27 + 1) / 29 + 2/30 + 3 =) 3.1701 çıktısı vermelidir.
Şu sorgu ile sonlandırdım:
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
Yılları, ayları ve günleri şu şekilde elde edebilirsiniz:
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
Ayrıca şunu da deneyebilirsiniz:
select MONTH(NOW())-MONTH(table_date) as 'Total Month Difference' from table_name;
VEYA
select MONTH(Newer_date)-MONTH(Older_date) as 'Total Month Difference' from table_Name;
Bu sorgu benim için çalıştı :)
SELECT * FROM tbl_purchase_receipt
WHERE purchase_date BETWEEN '2008-09-09' AND '2009-09-09'
Sadece iki tarih alır ve aralarındaki değerleri alır.