在 redshift 中重复连续运行后,除查询的结果发生变化

Posted

技术标签:

【中文标题】在 redshift 中重复连续运行后,除查询的结果发生变化【英文标题】:results of except query change after repeated consecutive runs in redshift 【发布时间】:2021-05-04 00:19:28 【问题描述】:

我在 aws redshift 中运行下面的 postgresql 查询。每次我运行此查询时,我都会使用 except 运算符在 daily_table.product_repeat_sub_query 端获得不同的记录数的不同结果。在此期间,daily_table.product_repeat_sub_query 表或 daily_table.daily_sku_t 都不会更新。 daily_table.product_repeat_sub_query 表和 product_repeat_sub_query 查询都具有相同的记录数。 daily_table.daily_sku_t 的架构如下,daily_table.product_repeat_sub_query 中的匹配字段具有相同的数据类型。我还包括了下表中的一些示例记录。有没有人知道,当底层表没有改变时,每次运行这个查询时,except 查询的结果会如何不同?

daily_table.daily_sku_t schema:

customer_uuid string
boardname_12 string
producttype string
productsubtype string
storeid int
product_id string
dateclosed date
Size string

查询:

with product_repeat_sub_query as
(
        select
            dateclosed, t.product_id, t.storeid, t.producttype, t.productsubtype, t.size, t.boardname_12,
            case
                when ticketid = first_value(ticketid) over (partition by t.product_id, customer_uuid
            ORDER BY
                dateclosed ASC rows between unbounded preceding and unbounded following) then 0
                else gros-s-receipts
            end as product_repeat_gross, datediff(day,
            lag(dateclosed, 1) over (partition by t.boardname_12, customer_uuid, t.product_id
        ORDER BY
            dateclosed ASC ),
            dateclosed) as product_cycle_days
        from
            daily_table.daily_sku_t t )
            
select count(*) from
(
select dateclosed, storeid, boardname_12, producttype, productsubtype, size, product_id, product_cycle_days from daily_table.product_repeat_sub_query
except
select dateclosed, storeid, boardname_12, producttype, productsubtype, size, product_id, product_cycle_days from product_repeat_sub_query
);

-- 36843 -- 36887 -- 36188

数据:

daily_table.product_repeat_sub_query

dateclosed  storeid boardname_12    producttype productsubtype  size    product_id  product_cycle_days
2021-04-23  427     22RED                       DRUMER          1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    2
2021-04-24  427     22RED                       DRUMER          1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    6
2021-04-26  427     22RED                       DRUMER          1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    8
2021-04-26  427     22RED                       DRUMER          1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    3
2021-05-01  427     22RED                       DRUMER          1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    13
2020-06-18  61      FLAV RX         WINGER      BEVERAGE        100MT   0000265d-6b81-4d79-90cf-xxxxxxxxxxxx    5
2020-06-29  

product_repeat_subquery

dateclosed  storeid boardname_12    producttype productsubtype  size    product_id  product_cycle_days
2021-04-23  427     22RED           DRUMER                      1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    2
2021-04-24  427     22RED           DRUMER                      1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    6
2021-04-26  427     22RED           DRUMER                      1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    8
2021-04-26  427     22RED           DRUMER                      1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    3
2021-05-01  427     22RED           DRUMER                      1T  000011aa-4f03-4f0b-a621-xxxxxxxxxxxx    13
2020-06-18  61      FLAV RX         WINGER      BEVERAGE        100MT   0000265d-6b81-4d79-90cf-xxxxxxxxxxxx    5
2020-06-29  

更新:

with product_repeat_sub_query as
    (
            select customer_uuid,
                dateclosed, t.product_id, t.storeid, t.producttype, t.productsubtype, t.size, t.boardname_12,
                case
                    when ticketid = first_value(ticketid) over (partition by t.product_id, customer_uuid
                ORDER BY
                    dateclosed ASC rows between unbounded preceding and unbounded following) then 0
                    else gros-s-receipts
                end as product_repeat_gross, datediff(day,
                lag(dateclosed, 1) over (partition by t.boardname_12, customer_uuid, t.product_id
            ORDER BY
                dateclosed ASC,t.boardname_12, customer_uuid, t.product_id ),
                dateclosed) as product_cycle_days
            from
                daily_table.daily_sku_t t 

where (t.customer_uuid is not null) 
            and (trim(t.customer_uuid) != '')
            and (t.product_id is not null) 
            and (trim(t.product_id) != '')

)
                
    select count(*) from
    (
    select customer_uuid, dateclosed, storeid, boardname_12, producttype, productsubtype, size, product_id, product_cycle_days from daily_table.product_repeat_sub_query
    except
    select customer_uuid, dateclosed, storeid, boardname_12, producttype, productsubtype, size, product_id, product_cycle_days from product_repeat_sub_query
    );

即使在将分区中的所有字段添加到 order by 并过滤 id 字段中的空值或空白之后,我每次仍然得到不同的计数。

【问题讨论】:

【参考方案1】:

您的窗口函数没有完全限定的 order by 子句。您在分区中重复了“日期关闭”值。这意味着 Redshift 可以对滞后函数和一值函数有不同的行顺序。我预计这些“随机”排序差异会导致您的结果发生变化。

【讨论】:

非常感谢您回复我这个提示!您对如何更改查询以使结果保持一致有任何建议吗? 将列添加到您的 order by 子句中,以确保每次都完全相同的排序。如果您没有任何组合可以执行此操作(您有重复的行),那么您可以添加一个标识列,以确保该值不同。问题是如果您的查询对随机排序很敏感,那么它应该测量什么?如果 dateclose 相同,那么 lag() 应该返回哪一行来实现您想要的业务结果?这些问题我无能为力。 我尝试将分区中的所有字段添加到 order by,并过滤掉 id 字段的空值或空白,但每次运行时我仍然得到不同的差异计数。有什么我想念的吗?这就是您通过子句限定 order by 的意思吗?我已经用我的新代码对我的原始帖子添加了更新。感谢您的帮助。 那不行。根据定义,分区 by 中的所有列在分区内都是相同的,因此将它们添加到 order by 不会执行任何操作。试试这个“select , count() from daily_table.daily_sku_t group by dateclose, have count(*) > 1;”。为了使这些窗口函数返回一致的结果,对于如何对分区中的行进行排序,只能有一种选择。现在将列添加到 group by 以获得计数 > 1 的零行。然后您可以将这些添加到窗口函数的 order by 子句中。

以上是关于在 redshift 中重复连续运行后,除查询的结果发生变化的主要内容,如果未能解决你的问题,请参考以下文章

Redshift 终止长时间运行的查询

由于运行查询,Redshift 集群更大

Redshift 查询花费太多时间

洞察 Redshift Spectrum 查询错误

AWS Redshift CTAS 查询在集群查询选项卡中完成,但仍从客户端 sql 工作台/j 运行。该表也未创建

在 Postgres (Redshift) 中使用两个选择列运行 MAX 聚合查询时出现问题