我有两张桌子,如下所示:
爱德, | 出价 | 日期1 | 日期2 |
---|---|---|---|
1 | B1 | 2021 年 1 月 1 日 | 2021 年 12 月 31 日 |
1 | B1 | 2022 年 1 月 1 日 | 2022 年 12 月 31 日 |
1 | B1 | 2023 年 1 月 1 日 | 2030 年 12 月 31 日 |
2 | B2 | 2021 年 1 月 1 日 | 2030 年 12 月 31 日 |
3 | B3 | 2024 年 1 月 1 日 | 2030 年 12 月 31 日 |
出价 | B值 |
---|---|
B1 | B1 |
B2 | B2 |
B3 | B3 |
我根据 BId 列连接这两个表 A 和 B。查询中有一个日期类型的输入,我们想要根据该参数过滤表 A 中的数据,并需要以下数据的输出。
传递给查询的输入 (input_date):2022 年 1 月 1 日
爱德 | 出价 | 日期1 | 日期2 |
---|---|---|---|
1 | B1 | 2022 年 1 月 1 日 | 2022年12月31日(有多个记录,但应该只出现一次) |
2 | B2 | 2021 年 1 月 1 日 | 2030 年 12 月 31 日 |
3 | B3 | 2024 年 1 月 1 日 | 2030 年 12 月 31 日(这将在未来开始,但它应该会输出) |
我当前正在使用以下查询,但它会提取重复的记录。
select AId, BId, Date1, Date2
from A,B
where A.BId = B.BId
and input_date >= A.Date2; -- We cant add check of Date1 as we want the record with AId '3' from table A.
但这会从 A 中提取 id 为“1”的记录的所有行。正如前面提到的,我们只想要 1 行。
我能想到的一个选择是添加不同或分组依据,但想检查是否有更好的替代方案来实现此要求。我认为随着行数的增加,DISTINCT 或 GROUP BY 会对性能产生影响。
这个问题可以用更好的方式处理吗?
PS:这些只是示例表,实际数据量较大时,表会更大。
问题不清楚,因为 2022 年的输入日期不大于 2030 年的 Date2 值,尽管代码说它应该大于。它也无法告诉我们使用哪种数据库,因为不同类型的数据库之间的日期函数是不同的。
这是假设 SQL Server 的日期函数编写的。如果您使用不同的数据库,日期函数将会不同,您应该告诉我们您有什么。
它使用
row_number()
窗口函数对行进行排名,然后仅筛选每组中排名靠前的行。这允许您仍然包含可能与主要条件不匹配的行(基于“开始未来但仍应出现在输出中”注释),但编号方式使得这些行始终让位于符合条件的分区。因为问题不清楚,所以所写的排名几乎肯定是错误,但它应该为您指出一个可行的解决方案。
with numbered as (
select A.AId, b.BId, Date1, Date2
, row_number() over (partition by A.AId, B.BId
-- prefer dates that meet the criteria
order by case when @input_date >= A.Date2 THEN 0 ELSE 1 END,
-- and then find the value nearest the requested date
abs(datediff(day, @input_date, A.Date2)) ) rn
from A
inner join B ON A.BId = B.BId
)
select AID, BId, Date1, Date2
from numbered
where rn = 1