聚合列文本,其中 table a 中的日期介于 table b 中的日期之间
Aggregate column text where dates in table a are between dates in table b
示例数据
CREATE TEMP TABLE a AS
SELECT id, adate::date, name
FROM ( VALUES
(1,'1/1/1900','test'),
(1,'3/1/1900','testing'),
(1,'4/1/1900','testinganother'),
(1,'6/1/1900','superbtest'),
(2,'1/1/1900','thebesttest'),
(2,'3/1/1900','suchtest'),
(2,'4/1/1900','test2'),
(2,'6/1/1900','test3'),
(2,'7/1/1900','test4')
) AS t(id,adate,name);
CREATE TEMP TABLE b AS
SELECT id, bdate::date, score
FROM ( VALUES
(1,'12/31/1899', 7 ),
(1,'4/1/1900' , 45),
(2,'12/31/1899', 19),
(2,'5/1/1900' , 29),
(2,'8/1/1900' , 14)
) AS t(id,bdate,score);
我想要的
我需要做的是聚合来自 table a 的列文本,其中 id 匹配 table b 并且 table a 的日期介于 [=] 的两个最接近的日期之间25=] b。期望的输出:
id date score textagg
1 12/31/1899 7 test, testing
1 4/1/1900 45 testinganother, superbtest
2 12/31/1899 19 thebesttest, suchtest, test2
2 5/1/1900 29 test3, test4
2 8/1/1900 14
我的想法是做这样的事情:
create table date_join
select a.id, string_agg(a.text, ','), b.*
from tablea a
left join tableb b
on a.id = b.id
*having a.date between b.date and b.date*;
但我真的在为最后一行而苦苦挣扎,弄清楚如何仅在 table b 中的日期位于 table b 中最近的两个日期之间的位置进行聚合。非常感谢任何指导。
我不能保证这是最好的方法,但这是一种的方法。
with b_values as (
select
id, date as from_date, score,
lead (date, 1, '3000-01-01')
over (partition by id order by date) - 1 as thru_date
from b
)
select
bv.id, bv.from_date, bv.score,
string_agg (a.text, ',')
from
b_values as bv
left join a on
a.id = bv.id and
a.date between bv.from_date and bv.thru_date
group by
bv.id, bv.from_date, bv.score
order by
bv.id, bv.from_date
我假设您 table 中的日期永远不会大于 12/31/2999,所以如果您在该日期之后仍然 运行 此查询,请接受我的抱歉。
这是我在 运行 时得到的输出:
id from_date score string_agg
1 0 7 test,testing
1 92 45 testinganother,superbtest
2 0 19 thebesttest,suchtest,test2
2 122 29 test3,test4
2 214 14
我可能还会注意到联接中的 between
是性能杀手。如果您的数据量很大,可能会有更好的想法来解决这个问题,但这在很大程度上取决于您的实际数据。
示例数据
CREATE TEMP TABLE a AS
SELECT id, adate::date, name
FROM ( VALUES
(1,'1/1/1900','test'),
(1,'3/1/1900','testing'),
(1,'4/1/1900','testinganother'),
(1,'6/1/1900','superbtest'),
(2,'1/1/1900','thebesttest'),
(2,'3/1/1900','suchtest'),
(2,'4/1/1900','test2'),
(2,'6/1/1900','test3'),
(2,'7/1/1900','test4')
) AS t(id,adate,name);
CREATE TEMP TABLE b AS
SELECT id, bdate::date, score
FROM ( VALUES
(1,'12/31/1899', 7 ),
(1,'4/1/1900' , 45),
(2,'12/31/1899', 19),
(2,'5/1/1900' , 29),
(2,'8/1/1900' , 14)
) AS t(id,bdate,score);
我想要的
我需要做的是聚合来自 table a 的列文本,其中 id 匹配 table b 并且 table a 的日期介于 [=] 的两个最接近的日期之间25=] b。期望的输出:
id date score textagg
1 12/31/1899 7 test, testing
1 4/1/1900 45 testinganother, superbtest
2 12/31/1899 19 thebesttest, suchtest, test2
2 5/1/1900 29 test3, test4
2 8/1/1900 14
我的想法是做这样的事情:
create table date_join
select a.id, string_agg(a.text, ','), b.*
from tablea a
left join tableb b
on a.id = b.id
*having a.date between b.date and b.date*;
但我真的在为最后一行而苦苦挣扎,弄清楚如何仅在 table b 中的日期位于 table b 中最近的两个日期之间的位置进行聚合。非常感谢任何指导。
我不能保证这是最好的方法,但这是一种的方法。
with b_values as (
select
id, date as from_date, score,
lead (date, 1, '3000-01-01')
over (partition by id order by date) - 1 as thru_date
from b
)
select
bv.id, bv.from_date, bv.score,
string_agg (a.text, ',')
from
b_values as bv
left join a on
a.id = bv.id and
a.date between bv.from_date and bv.thru_date
group by
bv.id, bv.from_date, bv.score
order by
bv.id, bv.from_date
我假设您 table 中的日期永远不会大于 12/31/2999,所以如果您在该日期之后仍然 运行 此查询,请接受我的抱歉。
这是我在 运行 时得到的输出:
id from_date score string_agg
1 0 7 test,testing
1 92 45 testinganother,superbtest
2 0 19 thebesttest,suchtest,test2
2 122 29 test3,test4
2 214 14
我可能还会注意到联接中的 between
是性能杀手。如果您的数据量很大,可能会有更好的想法来解决这个问题,但这在很大程度上取决于您的实际数据。