重新生成sql查询以从两个表求和日期
我需要一个解决方案扩展,我收到的,它是在链接可见。我无法连接两个表中的数据。我有两个表KP和KPS中的日期数据。我知道我必须从SQL查询中的第二个表中添加数据,在那个地方是KP2的定义,但我不知道如何做到这一点。我应该使用join吗 我有一个SQL查询:重新生成sql查询以从两个表求和日期,sql,firebird,Sql,Firebird,我需要一个解决方案扩展,我收到的,它是在链接可见。我无法连接两个表中的数据。我有两个表KP和KPS中的日期数据。我知道我必须从SQL查询中的第二个表中添加数据,在那个地方是KP2的定义,但我不知道如何做到这一点。我应该使用join吗 我有一个SQL查询: SELECT KP3.id_contact, (KP3.D2-KP3.D1) / (12*31) AS Y, ((KP3.D2-KP3.D1) - ((KP3.D2-KP3.D1) / (12*31)) * 12 * 3
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
我在示例中展示了这一点。表KP中有如下数据
ID DATE_FROM DATE_TO
------------------------------
1 2018-02-08 2019-12-01
在表KPS中,我有如下数据:
ID DATE_FROM DATE_TO
------------------------------
1 2017-02-20 2018-01-01
2Y 8M 7D
查询结果应如下所示:
ID DATE_FROM DATE_TO
------------------------------
1 2017-02-20 2018-01-01
2Y 8M 7D
请帮我做这个。可能是这样的:
DROP TABLE IF EXISTS #TestTableA, #TestTableB
CREATE TABLE #TestTableA (DFA DATE, DTA DATE)
CREATE TABLE #TestTableB (DFB DATE, DTB DATE)
INSERT INTO #TestTableA
SELECT '2018-02-08','2019-12-01'
INSERT INTO #TestTableB
SELECT '2017-02-20','2018-01-01'
SELECT CAST(SUM(DaysQTY) / 365 AS VARCHAR(4)) + 'Y ' +
CAST((SUM(DaysQTY) % 365) / 30 AS VARCHAR(2)) + 'M ' +
CAST((SUM(DaysQTY) % 365) % 30 AS VARCHAR(2)) + 'D' AS Result
FROM ( SELECT DATEDIFF(DAY,DFA,DTA) AS DaysQTY
FROM #TestTableA
UNION ALL
SELECT DATEDIFF(DAY,DFB,DTB) AS DaysQTY
FROM #TestTableB
) t
试着猜你的意思 也许您的意思是在所有源表之间选择最早的最小日期,然后选择最晚的日期并计算其间的天数 或者,您可能想计算所有源表中每个作业的天数,以及nsum中每个工人的天数 不知道,这两种解决方案都是从简单的模块进一步构建而成,并进一步扩展到最终结果。它还使用您链接的问题中的数据进行自我检查 以下是您可以调整的脚本,看看它是如何运行的: 结果可能是2年9个月2天,也可能是2年8个月1天,这取决于您对加入源表的含义的猜测 Cherry选择您需要的子查询并剔除不需要的子查询
您需要以何种方式连接表KP和KPS中的数据?这里的逻辑是什么?为什么这种组合会导致2Y 8M 7D?这在Firebird中完全不行。如果存在该下拉表并选择“2017-02-20”,“2018-01-01”就是非标准SQL。还有,到底为什么要使用select中的insert而不是标准的insert来插入tx、y、z值xxx、yyy、zzz,我想知道…@Arioch'The:更糟糕的是:+不用于连接SQL中的字符串-其运算符是| | | a| u horse_,带有_no_名称,我甚至没有查看运算符,或者可能我也会注意到C样式的%表示余数:-D
-- https://stackoverflow.com/questions/60030543/rebuild-sql-query-to-sum-date-from-two-tables
create table KPS1 (
ID integer not null,
DATE_FROM date not null,
DATE_TO date not null
)
✓
create table KPS2 (
ID integer not null,
DATE_FROM date not null,
DATE_TO date not null
)
✓
create index KPS1_workers on KPS1(id)
✓
create index KPS2_workers on KPS2(id)
✓
insert into KPS1 values (1, '2018-02-08', '2019-12-01')
1 rows affected
insert into KPS2 values (1, '2017-02-20', '2018-01-01')
1 rows affected
-- this data sample taked from
-- https://stackoverflow.com/questions/51551257/how-to-get-correct-year-month-and-day-in-firebird-function-datediff
insert into KPS1 values (2, '1988-09-15', '2000-03-16')
1 rows affected
insert into KPS1 values (2, '2000-03-16', '2005-02-28')
1 rows affected
select * from KPS1 union all select * from KPS2
ID | DATE_FROM | DATE_TO
-: | :--------- | :---------
1 | 2018-02-08 | 2019-12-01
2 | 1988-09-15 | 2000-03-16
2 | 2000-03-16 | 2005-02-28
1 | 2017-02-20 | 2018-01-01
-- sadly, the topic starter did not say what he wants to do with his many sources of data
-- so multiple interpretations are possible!
-- here we are counting days from the first date to the last date, one row per worker
-- finding the minimum and maximum dates from ALL the sources
-- (multitude of rows in multitude of tables)
-- very simple to write and read, it however would be bad on long tables
-- because ID indexes hidden by UNION and not available for further, outer queries
-- FULL-SCAN in natural order and post-merge external sorting would occur
Select ID as id_contact, Min(DATE_FROM) as DATE_FROM, Max(DATE_TO) as DATE_TO
From (select * from KPS1 union all select * from KPS2)
Group by ID
ID_CONTACT | DATE_FROM | DATE_TO
---------: | :--------- | :---------
1 | 2017-02-20 | 2019-12-01
2 | 1988-09-15 | 2005-02-28
-- finding the minimum and maximum dates from ALL the sources
-- this one is harder to write and read
-- but should be better for execution: it allows use of indexes by ID be propagated
-- This optimized query works fine with the data presented by topic starter
-- where each source tables has exactly one row for one and the same worker.
-- It will not work so fine when some workers are missed from some tables.
-- Fixing it will make the query even more complex to write and read
Select KPS1.ID as id_contact,
IIF(KPS1.DATE_FROM < KPS2.DATE_FROM, KPS1.DATE_FROM, KPS2.DATE_FROM) as DATE_FROM,
IIF(KPS2.DATE_TO < KPS2.DATE_TO, KPS2.DATE_TO, KPS1.DATE_TO) as DATE_TO
From KPS1, KPS2
Where KPS1.ID = KPS2.ID
ID_CONTACT | DATE_FROM | DATE_TO
---------: | :--------- | :---------
1 | 2017-02-20 | 2019-12-01
Select ID_CONTACT, DateDiff(day, DATE_FROM, DATE_TO) as DAYS_COUNT From
(
Select ID as id_contact, Min(DATE_FROM) as DATE_FROM, Max(DATE_TO) as DATE_TO
From (select * from KPS1 union all select * from KPS2)
Group by ID
)
ID_CONTACT | DAYS_COUNT
---------: | :---------
1 | 1014
2 | 6010
-- alternatively, here counting days per-job, many rows may happen for the same worker
select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KPS1 a
union all
select b.*, datediff(day, b.DATE_FROM, b.DATE_TO) as DAYS_COUNT from KPS2 b
ID | DATE_FROM | DATE_TO | DAYS_COUNT
-: | :--------- | :--------- | :---------
1 | 2018-02-08 | 2019-12-01 | 661
2 | 1988-09-15 | 2000-03-16 | 4200
2 | 2000-03-16 | 2005-02-28 | 1810
1 | 2017-02-20 | 2018-01-01 | 315
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KPS1 a
)
GROUP BY ID_CONTACT
union all
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select b.*, datediff(day, b.DATE_FROM, b.DATE_TO) as DAYS_COUNT from KPS2 b
)
GROUP BY ID_CONTACT
ID_CONTACT | DAYS_COUNT
---------: | :---------
1 | 661
2 | 6010
1 | 315
WITH PER_SOURCE_SUMMER AS
(
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KPS1 a
)
GROUP BY ID_CONTACT
union all
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select b.*, datediff(day, b.DATE_FROM, b.DATE_TO) as DAYS_COUNT from KPS2 b
)
GROUP BY ID_CONTACT
)
SELECT ID_CONTACT, SUM(Days_Count) as DAYS_COUNT
FROM PER_SOURCE_SUMMER
GROUP BY 1
ID_CONTACT | DAYS_COUNT
---------: | :---------
1 | 976
2 | 6010
-- Now, having TWO interpretations of the task and TWO implementations of days counter
-- we finally can come up with conversion from precise but hard to feel DAYS
-- to imprecise but easy to digest Y-M-D
WITH SOURCE_MIN_MAX AS
(
Select ID_CONTACT, DateDiff(day, DATE_FROM, DATE_TO) as DAYS_COUNT From
(
Select ID as id_contact, Min(DATE_FROM) as DATE_FROM, Max(DATE_TO) as DATE_TO
From (select * from KPS1 union all select * from KPS2)
Group by ID
)
),
PER_SOURCE_SUMMER AS
(
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KPS1 a
)
GROUP BY ID_CONTACT
union all
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select b.*, datediff(day, b.DATE_FROM, b.DATE_TO) as DAYS_COUNT from KPS2 b
)
GROUP BY ID_CONTACT
),
SOURCE_PER_JOB AS
(
SELECT ID_CONTACT, SUM(Days_Count) as DAYS_COUNT
FROM PER_SOURCE_SUMMER
GROUP BY 1
),
KP_DAYS AS
(
SELECT 1 as METHOD, A.* FROM SOURCE_MIN_MAX A
union all
SELECT 2 as METHOD, B.* FROM SOURCE_PER_JOB B
)
SELECT * from KP_DAYS
METHOD | ID_CONTACT | DAYS_COUNT
-----: | ---------: | :---------
1 | 1 | 1014
1 | 2 | 6010
2 | 1 | 976
2 | 2 | 6010
WITH SOURCE_MIN_MAX AS
(
Select ID_CONTACT, DateDiff(day, DATE_FROM, DATE_TO) as DAYS_COUNT From
(
Select ID as id_contact, Min(DATE_FROM) as DATE_FROM, Max(DATE_TO) as DATE_TO
From (select * from KPS1 union all select * from KPS2)
Group by ID
)
),
PER_SOURCE_SUMMER AS
(
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select a.*, datediff(day, a.DATE_FROM, a.DATE_TO) as DAYS_COUNT from KPS1 a
)
GROUP BY ID_CONTACT
union all
SELECT ID as ID_CONTACT, SUM(Days_Count) as DAYS_COUNT FROM
(
select b.*, datediff(day, b.DATE_FROM, b.DATE_TO) as DAYS_COUNT from KPS2 b
)
GROUP BY ID_CONTACT
),
SOURCE_PER_JOB AS
(
SELECT ID_CONTACT, SUM(Days_Count) as DAYS_COUNT
FROM PER_SOURCE_SUMMER
GROUP BY 1
),
KP_DAYS AS
(
SELECT 1 as METHOD, A.* FROM SOURCE_MIN_MAX A
union all
SELECT 2 as METHOD, B.* FROM SOURCE_PER_JOB B
)
SELECT
KP_DAYS.method, 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 KP_DAYS
METHOD | ID_CONTACT | DAYS_COUNT | Y | M | D
-----: | ---------: | :--------- | :- | :- | -:
1 | 1 | 1014 | 2 | 9 | 2
1 | 2 | 6010 | 16 | 5 | 2
2 | 1 | 976 | 2 | 8 | 1
2 | 2 | 6010 | 16 | 5 | 2