如何在Firebird中修改SQL,添加两个日期,每个日期都来自其他表?

时间:2019-06-03 10:52:38

标签: sql firebird firebird2.5

我不得不问有关在Firebird中添加日期的问题。在这种情况下,我不知道如何获得正确的结果:工人x有两份雇用合同,第一份是在1988-09-15至2000-03-16期间,第二份是在2000-03-16至2005-02- 28,但是这个日期之一是来自另一个表的第二个日期。

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

我想要得到的结果是这样的16年5个月零3天,因为第一个结果是11年6个月零天,第二个结果是4年11个月2天。谁能告诉我如何在Firebird中执行此操作?我有这样的sql,但我不知道如何修改此查询以获得所需的结果。 我的问题是如何更改此sql以得到将两个datediff函数date形式互相添加两个表的结果。此SQL查询给我一个datediff的结果,因为我在一个名称为TABLE1的表上运行它。但是我有第二张表,名字是TABLE2,还有第二张datediff。因此,我有一个问题,要从这两个表连接这两个resull并显示结果,这是这两个datediff的加法结果。每个其他表中都有一条带有这两个记录的插入。

INSERT INTO TABLE1 (ID, ID_CONTACT, DATE_FROM, DATE_TO) 
   VALUES ('1', '52', '1988-09-15', '2000-03-16'); 

INSERT INTO TABLE2 (ID, ID_CONTACT, DATE_FROM, DATE_TO) 
   VALUES ('1', '52', '2000-03-16', '2005-02-28');

现在我只能从第1列中的一个表中获得结果,该表的名称为Y(年)11,第2列的名称为M(月)6,列D(天)2。

请帮助解决此问题。

1 个答案:

答案 0 :(得分:2)

这是表的基本创建。 以它为例,您可以进行进一步的工作,或对所完成任务的进一步说明。

以它为起点。

  1. AFAIR Firebird 在几天内返回类似(DATE-DATE)的算术运算,与 PostgreSQL 相同,但是您必须检查它。例如, MySQL 似乎以不同的单位来计算日期。 SQL Fiddle 不支持 Firebird

  2. 您只是无法正确地将天数转换为年/月/日,因为存在不同的年份(365或366天)和不同的月份(从28到31天),所以这取决于您在这里确定您将考虑“一年左右”还是“一个月左右”的数学内容。例如,您可以将数学包装到某些存储过程中,以便通过LEFT JOIN在不同的查询中重用它。

  3. 此查询使用JOIN,因此假定 table1 table2 中都存在每个人和联系人对的数据记录然后每个表中只有一行。如果您的人联系人对在某张表中缺少一行或有多对,则可能需要相应地修改查询。

  4. 特别是,您可能想要创建一个辅助表,一个持久表或一​​个GLOBAL TEMPORARY TABLE,该表将同时存储 table1 table2 中的记录em>,仅出于总结目的。它可能会解决在一个表中但在另一个表中没有行的问题。可能会或可能不会解决在同一联系人的同一表中有多行的问题。

还有一个问题,即主题启动器无法回答,因此仍未解决:

  

但是,您的数据中存在一个问题:日期'2000-03-16'立即属于两个合同,这似乎是自相矛盾的。那么您要数多少天?

在此之下,它被计算两次,除非该段是半开放式的,并且DATE_TO实际上应该表示DATE_AFTER


SQL Fiddle

PostgreSQL 9.6模式设置

create table TABLE1 
(ID integer, ID_CONTACT integer, DATE_FROM date , DATE_TO date);

create table TABLE2 
(ID integer, ID_CONTACT integer, DATE_FROM date , DATE_TO date);

INSERT INTO TABLE1 (ID, ID_CONTACT, DATE_FROM, DATE_TO) 
   VALUES ('1', '52', '1988-09-15', '2000-03-16'); 

INSERT INTO TABLE2 (ID, ID_CONTACT, DATE_FROM, DATE_TO) 
   VALUES ('1', '52', '2000-03-16', '2005-02-28');

查询1

select id, id_contact, date_to - date_from as D1 from table1 
   union all
select id, id_contact, date_to - date_from as D2 from table2   

Results

| id | id_contact |   d1 |
|----|------------|------|
|  1 |         52 | 4200 |
|  1 |         52 | 1810 |

查询2

with D1 as (
  select id, id_contact, date_to - date_from as D1 from table1 ),
     D2 as (
  select id, id_contact, date_to - date_from as D2 from table2 )  
Select d1.id, d2.id_contact, d1.d1 + d2.d2  
  From D1, D2 
  Where D1.id = D2.id
    and D1.id_contact = D2.id_contact

Results

| id | id_contact | ?column? |
|----|------------|----------|
|  1 |         52 |     6010 |

SQL Fiddle

PostgreSQL 9.6模式设置

create table TABLE1 
(ID integer, ID_CONTACT integer, DATE_FROM date , DATE_TO date);

create table TABLE2 
(ID integer, ID_CONTACT integer, DATE_FROM date , DATE_TO date);

create table TABLE3 
(ID integer, ID_CONTACT integer, DATE_FROM date , DATE_TO date);

INSERT INTO TABLE1 (ID, ID_CONTACT, DATE_FROM, DATE_TO) 
   VALUES ('1', '52', '1988-09-15', '2000-03-16'); 

INSERT INTO TABLE2 (ID, ID_CONTACT, DATE_FROM, DATE_TO) 
   VALUES ('1', '52', '2000-03-16', '2005-02-28');

INSERT INTO TABLE3 SELECT * FROM TABLE1;   

INSERT INTO TABLE3 SELECT * FROM TABLE2;

查询1

Select id, id_contact, SUM( DATE_TO - DATE_FROM ) 
From TABLE3
Group By 1, 2  

Results

| id | id_contact |  sum |
|----|------------|------|
|  1 |         52 | 6010 |