我不得不问另一个关于Firebird中datediff的问题。在这种情况下,我不知道如何获得正确的结果: 工人x有两份雇用合同,第一份是在1988-09-15至2000-03-16之间,第二份是在2000-03-16至2005-02-28之间。我要得到的结果是这样的16年5个月3天,因为第一个结果是11年6个月零一天,第二个结果是4年11个月2天。 有谁能告诉我如何在firebird中做到这一点。我最想知道的是,从几个月的总和(17个月)起,我可以做5个月,而其他12个月又增加了一年的价值。现在我有了这样的SQL:
SELECT
a.id_contact,
sum(floor(datediff(day, a.DATE_FROM, a.DATE_TO)/365.25)) as YEAR,
mod(sum(mod(floor(datediff(day, a.DATE_FROM, a.DATE_TO)/30.41),12)),12) as MTH
FROM KP a
group by a.id_contact
然后我有5个月的时间,但我没有12个月的年价值增加值。请帮助我...
答案 0 :(得分:2)
您应该先对天进行求和,然后对结果求和,然后计算Y,M,D
SELECT
KP3.id_contact
, (KP3.D2-KP3.D1) / (12*31) AS Y
, ((KP3.D2-KP3.D1) - ((KP3.D2-KP3.D1) / (12*31)) * 12 * 31) / 31 AS M
, CAST(MOD((KP3.D2-KP3.D1) - (((KP3.D2-KP3.D1) / (12*31)) * 12 * 31), 31) AS INTEGER) AS D
FROM
(SELECT
KP2.id_contact, SUM(KP2.D1) AS D1, SUM(KP2.D2) AS D2
FROM
(
SELECT
KP.id_contact, DATEDIFF(MONTH, KP.DATE_FROM, KP.DATE_TO) / 12 AS Y, CAST(MOD(DATEDIFF(MONTH, KP.DATE_FROM, KP.DATE_TO), 12) AS INTEGER) AS M
, EXTRACT(YEAR FROM KP.DATE_FROM)*12*31+EXTRACT(MONTH FROM KP.DATE_FROM)*31+EXTRACT(DAY FROM KP.DATE_FROM) D1
, EXTRACT(YEAR FROM KP.DATE_TO)*12*31+EXTRACT(MONTH FROM KP.DATE_TO)*31+EXTRACT(DAY FROM KP.DATE_TO) D2
FROM
KP
) AS KP2
GROUP BY KP2.id_contact
) AS KP3
答案 1 :(得分:0)
正确的方法似乎是衡量在两个任务上花费的天数,然后将这些日期相加,然后将其转换为与生俱来的不精确形式的年限,月-日。 有关此内容的更多信息
借用Livius的转换查询,并将系数调整为更实际,将发展为:
https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=2fba0ace6a70ae16a167ec838642dc28
在这里,我们一步一步地前进,从简单的地块发展成为越来越复杂的地块,这最终使我们得到了 16年零5个月零2天:
select rdb$get_context('SYSTEM', 'ENGINE_VERSION') as version from rdb$database;
| VERSION | | :------ | | 3.0.5 |
create table KP ( ID_CONTACT integer not null, DATE_FROM date not null, DATE_TO date not null ) -- https://stackoverflow.com/questions/51551257/how-to-get-correct-year-month-and-day-in-firebird-function-datediff
✓
create index KP_workers on KP(id_contact)
✓
insert into KP values (1, '1988-09-15', '2000-03-16')
1 rows affected
insert into KP values (1, '2000-03-16', '2005-02-28')
1 rows affected
-- the sample data from https://stackoverflow.com/questions/60030543 -- might expose the rounding bug in my original formulae: -- unexpected ROUNDING UP leading to NEGATIVE value for months insert into KP values (2, '2018-02-08', '2019-12-01')
1 rows affected
insert into KP values (2, '2017-02-20', '2018-01-01')
1 rows affected
select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KP a
ID_CONTACT | DATE_FROM | DATE_TO | DAYS_COUNT ---------: | :--------- | :--------- | :--------- 1 | 1988-09-15 | 2000-03-16 | 4200 1 | 2000-03-16 | 2005-02-28 | 1810 2 | 2018-02-08 | 2019-12-01 | 661 2 | 2017-02-20 | 2018-01-01 | 315
-- Original answer by Livius SELECT KP3.id_contact , KP3.D2-KP3.D1 as days_count , (KP3.D2-KP3.D1) / (12*31) AS Y , ((KP3.D2-KP3.D1) - ((KP3.D2-KP3.D1) / (12*31)) * 12 * 31) / 31 AS M , CAST(MOD((KP3.D2-KP3.D1) - (((KP3.D2-KP3.D1) / (12*31)) * 12 * 31), 31) AS INTEGER) AS D FROM (SELECT KP2.id_contact, SUM(KP2.D1) AS D1, SUM(KP2.D2) AS D2 FROM ( SELECT KP.id_contact, DATEDIFF(MONTH, KP.DATE_FROM, KP.DATE_TO) / 12 AS Y, CAST(MOD(DATEDIFF(MONTH, KP.DATE_FROM, KP.DATE_TO), 12) AS INTEGER) AS M , EXTRACT(YEAR FROM KP.DATE_FROM)*12*31+EXTRACT(MONTH FROM KP.DATE_FROM)*31+EXTRACT(DAY FROM KP.DATE_FROM) D1 , EXTRACT(YEAR FROM KP.DATE_TO)*12*31+EXTRACT(MONTH FROM KP.DATE_TO)*31+EXTRACT(DAY FROM KP.DATE_TO) D2 FROM KP ) AS KP2 GROUP BY KP2.id_contact ) AS KP3
ID_CONTACT | DAYS_COUNT | Y | M | D ---------: | :--------- | :- | :- | -: 1 | 6120 | 16 | 5 | 13 2 | 997 | 2 | 8 | 5
select ID_CONTACT, sum(DAYS_COUNT) as DAYS_COUNT from ( select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KP a ) GROUP BY 1
ID_CONTACT | DAYS_COUNT ---------: | :--------- 1 | 6010 2 | 976
-- this step taken from https://dbfiddle.uk/?rdbms=firebird_3.0&fiddle=52c1e130f589ca507c9ff185b5b2346d -- based on original Livius forumla with non-exact integer coefficients -- it seems not be generating negative counts, but still shows very different results SELECT KP_DAYS.id_contact, KP_DAYS.DAYS_COUNT / (12*31) AS Y, ((KP_DAYS.DAYS_COUNT) - ((KP_DAYS.DAYS_COUNT) / (12*31)) * 12 * 31) / 31 AS M, CAST(MOD((KP_DAYS.DAYS_COUNT) - (((KP_DAYS.DAYS_COUNT) / (12*31)) * 12 * 31), 31) AS INTEGER) AS D FROM ( select ID_CONTACT, sum(DAYS_COUNT) as DAYS_COUNT from ( select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KP a ) GROUP BY 1 ) as KP_DAYS
ID_CONTACT | Y | M | D ---------: | :- | :- | -: 1 | 16 | 1 | 27 2 | 2 | 7 | 15
SELECT KP_DAYS.id_contact, KP_DAYS.days_count , FLOOR(KP_DAYS.DAYS_COUNT / 365.25) AS Y , FLOOR( (KP_DAYS.DAYS_COUNT - (FLOOR(KP_DAYS.DAYS_COUNT / 365.25) * 365.25) ) / 30.5) AS M , CAST(MOD((KP_DAYS.DAYS_COUNT) - (((KP_DAYS.DAYS_COUNT) / 365.25) * 365.25), 30.5) AS INTEGER) AS D FROM ( select ID_CONTACT, sum(DAYS_COUNT) as DAYS_COUNT from ( select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KP a ) GROUP BY 1 ) as KP_DAYS
ID_CONTACT | DAYS_COUNT | Y | M | D ---------: | :--------- | :- | :- | -: 1 | 6010 | 16 | 5 | 2 2 | 976 | 2 | 8 | 1
注意,以上在数学上仍然不正确。但是应该给“胆量感”的时间戳。 以Y-M-D形式获取时间跨度的精确和精确的问题尚无定论。
例如,您引用了3天,而此查询给出了2天。我在那里没有看到错误。由于月份和年份彼此不同,因此您无法正确地测量以月为单位的时间间隔。这就像测量城市中的地理距离。
伦敦和巴黎之间有多少纽约?布鲁斯山有多少华沙?您没有任何数学上正确的答案。
因此,您只能使用NON-PRECISE估算值进行回答。适合于街头交流的随取随谈。因此,任何基于DateDiff的查询本质上都会产生“ 2Y 10M给予或花费几天时间”的完美有效答案-在这种情况下“只是给我整体印象”是有效的答案。
以数学准确性的完美主义来实现这种简单感觉是不可能的。例如,假设您获得约6Y的跨度。现在,您应该考虑多少个leap年?在1999年至2004年的“ 6Y”中有两个leap年,而在1998年至2003年的同一“ 6Y”中只有一个was年。哪一个是正确的“ 6Y”度量标准?
然后我们有千年了,其中2000年是leap年,而1900年不是。同样的“滑动窗口”问题使您在时间跨度(如“ 110Y”)中具有不确定的of年数。如果您想了解外行的看法并计算“年月”中的时间跨度,则必须同意,这使事情变得简单,简单且不精确。并且几年不匹配几天或几天是正常的,可以