我目前正在try 将Left joinwindow函数(例如partition by class_id order by date_to desc)结合起来,以解决SQL中的以下问题.这是一个相当困难的问题,因为有一堆棘手的约束在起作用,对我来说,我似乎需要有一种方法来处理partitioned个子表中的哪些行(在应用windows函数之后).

Problem.给定具有两个公共字段class_idprop_id的两个表A和B,我们的目标是对于given个参数yearmonth(例如,2022-05),查询将包括来自表A的列class_id中的all个值,当基于表B的date_todate_from列的值满足某些条件时,改变同一表中的相应值prop_id.条件是:如果表B中的相同值prop_id在给定参数yearmonth之间具有date_fromdate_to,则我们针对该特定class_id将表A中的prop_id设置为Null.请注意,表B中的特定class_id可能具有multiple prop_id,,因此我们需要确定包含给定参数yearmonth的准确的date_fromdate_to对.

样本输入

Table A  
         class_id   prop_id   
         12         aa_13         
         13         ab_21
         22         ac_11
         53         bb_32
         48         ac_57

Table B
         class_id   prop_id  date_from     date_to 
         12         aa_13    2022-02-15    2022-12-10
         12         aa_31    2021-09-30    2022-02-12  
         13         ac_12    2021-05-18    2022-02-05
         22         ac_11    2022-05-12    2022-08-25     
         22         ac_12    2022-01-05    2022-04-23
         22         ac_13    2021-08-18    2021-11-16
         53         bb_32    2022-02-06    2022-03-19
         53         bb_31    2021-05-08    2022-02-05
         48         ac_57    2022-02-03    2022-05-07

现在,如果给定year = 2022month = 5,则预期输出为

Table A  
         class_id   prop_id (modified properly)   
         12         aa_13         
         13         NULL -- 2022-05 > date_to = 2022-02-05
         22         NULL -- 2022-05 could be between 2022-04-23 and 2022-05-11, which is outside the range between 2022-05-12 and 2022-08-25 => NULL is chosen here
         53         NULL -- Same reasoning as for class_id = 22
         48         NULL - 2022-05 could be beyond 2022-05-07 => set it to NULL.

Question.如何编写查询以实现上述预期输出?

推荐答案

您没有为DB引擎提供标记,所以首先是Postgres,然后是Snowflake,根据您的 comments .

Postgres:

create table "public"."a" (
  class_id int4, 
  prop_id text
);

create table "public"."b" (
  class_id int, 
  prop_id varchar,
  date_from date,
  date_to date
);

insert into public.a(class_id,prop_id) values
(12,'aa_13'),
(13,'ac_21'),
(22,'ac_11'),
(53,'bb_32'),
(48,'ac_57');

insert into b values
(12,'aa_13','2022-02-15','2022-12-10'),
(12,'aa_31','2021-09-30','2022-02-12'),
(13,'ac_12','2021-05-18','2022-02-05'),
(22,'ac_11','2022-05-12','2022-08-25'),
(22,'ac_12','2022-01-05','2022-04-23'),
(22,'ac_13','2021-08-18','2021-11-16'),
(53,'bb_32','2022-02-06','2022-03-19'),
(53,'bb_31','2021-05-08','2022-02-05'),
(48,'ac_57','2022-02-03','2022-05-07');

select
  a.class_id, 
  a.prop_id,
  case 
      when b.date_from <= make_date(2022,5,1) and b.date_to >= make_date(2022,5,1) + '1 month - 1 day'::interval
      then a.prop_id 
      else null 
  end modified_prop_id
from a left join b on a.prop_id = b.prop_id;
class_id | prop_id | modified_prop_id
-------: | :------ | :---------------
      12 | aa_13   | aa_13           
      22 | ac_11   | null            
      13 | ac_21   | null            
      48 | ac_57   | null            
      53 | bb_32   | null            

db<>fiddle 100

Snowflake:

create or replace table a (
    class_id number(38,0),
    prop_id varchar(100)
);

create or replace table b (
    class_id number(38,0),
    prop_id varchar(100),
    date_from date,
    date_to date
);

insert into public.a(class_id,prop_id) values
(12,'aa_13'),
(13,'ac_21'),
(22,'ac_11'),
(53,'bb_32'),
(48,'ac_57');

insert into b values
(12,'aa_13','2022-02-15','2022-12-10'),
(12,'aa_31','2021-09-30','2022-02-12'),
(13,'ac_12','2021-05-18','2022-02-05'),
(22,'ac_11','2022-05-12','2022-08-25'),
(22,'ac_12','2022-01-05','2022-04-23'),
(22,'ac_13','2021-08-18','2021-11-16'),
(53,'bb_32','2022-02-06','2022-03-19'),
(53,'bb_31','2021-05-08','2022-02-05'),
(48,'ac_57','2022-02-03','2022-05-07');
      
select
    a.class_id, 
    a.prop_id,
    case 
        when b.date_from <= date_from_parts(2022,5,1) and b.date_to >= last_day(date_from_parts(2022,5,1))
        then a.prop_id 
        else null 
    end modified_prop_id
from a left join b on a.prop_id = b.prop_id;

Sql相关问答推荐

当编号和版本的唯一状态更改时报告

如何通过比较不同表中相同ID S的值来筛选ID为S的列表?

用于动态查询情况的存储过程常识模式

Select 起始参数和截止参数之间的间隔,包括与期间重叠的参数

PostgreSQL中的合并命令是原子的,还是需要一些类似于SQL Server版本的内容?

对任何(数组)使用LIKE?

我怎样才能得到列值对应的最大值在另一个?

返回找到的最小和最大row_number()spark SQL

如何将我的联接数据放入每个用户每月多行的列中?

Postgres SQL查询从字符串中获取邮箱地址

如何将insert语句重复n次使一个值递增?

在 postgres 中插入或更新 jsonb 数组的对象

SQL Server中使用min()和max()从选定的特定值id表中删除不必要的时间

如何从postgresql中的项目映射(关联数组)设置值?

如何从一张表中获取值在至少三行相同的记录

IN子句使用的表值用户定义函数参数

for each 客户查找每个类别的最新评分

在 SQL 中使用循环遍历按时间顺序排列的数据

在 BigQuery 数据集中查找表大小和占总数据集大小的百分比

根据开始/结束标记将 GROUP_ID 分配给行