Как я могу изменить свой sql в Firebird, добавив две даты, где каждая дата из другой таблицы? - PullRequest
1 голос
/ 03 июня 2019

Мне нужно задать вопрос о дате добавления в Firebird. Я не знаю, как получить правильный результат в этом случае: работник х имеет два трудовых договора, первый в период с 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 месяцев и 1 день, а второй результат - 4 года, 11 месяцев и 2 дня. , Может кто-нибудь сказать мне, как это сделать в Firebird? У меня есть sql, как это, но я не знаю, как я могу изменить этот запрос, чтобы получить желаемый результат. Моя проблема заключается в том, как изменить этот sql, чтобы получить результат добавления двух функций даты датированной формы две таблицы друг друга. Этот SQL-запрос дает мне результат одного datediff, потому что я запускаю его на одной таблице, имя которой, например, TABLE1. Но у меня есть вторая таблица, которая называется TABLE2, и есть вторая дата. Поэтому у меня есть проблема с соединением этих двух результатов из этих двух таблиц и показом результата, который является результатом сложения этих двух датированных значений. Существует вставка с этими двумя записями из других таблиц.

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 Ответ

2 голосов
/ 03 июня 2019

Вот базовое воссоздание вашего стола.Используйте его в качестве примера для своей дальнейшей работы или для дальнейшего объяснения того, что задача, которую вы выполнили.

Возьмите ее в качестве отправной точки.

  1. AFAIR Firebird возвращает арифметические операции, такие как (DATE - DATE) в днях, такие же, как PostgreSQL , но вы должны проверить это. MySQL например, кажется, считает дату в разных единицах. SQL Fiddle не поддерживает Firebird .

  2. Вы просто не можете правильно преобразовать количество дней в годы / месяцы / дни, потому что есть разныегоды (365 или 366 дней) и разные месяцы (от 28 до 31 дня), так что вам решать, что вы будете считать «более или менее в год» и «более или менее в месяц» здесь и делать математику,Вы можете заключить математику в какую-нибудь хранимую процедуру, например, , чтобы повторно использовать ее в различных запросах LEFT JOIN.

  3. Этот запрос использует JOIN, поэтому он предполагаетчто записи данных для каждой пары человек-контакт присутствуют как в таблица1 , так и таблица2 , а затем только в одной строке в каждой таблице.Если у вас есть пары человек-контакт, у которых нет строки в какой-либо таблице или их несколько - возможно, вы захотите соответствующим образом изменить запрос.

  4. В частности, вы можете создать помощникатаблица, постоянная или GLOBAL TEMPORARY TABLE, которая будет накапливать записи как из table1 , так и table2 , просто для их суммирования.Это может решить проблему наличия строк в одной из таблиц, но не в другой.Это может или не может решить проблему наличия нескольких строк в одной таблице для одного и того же контакта.

Также был вопрос, что автор темы не отвечает, поэтому он остается нерешенным:

В ваших данных есть одна проблема: дата 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   

Результаты :

| 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

Результаты :

| 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  

Результаты :

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