【问题标题】:Convert This SQL Query to ANSI SQL将此 SQL 查询转换为 ANSI SQL
【发布时间】:2020-01-26 16:58:26
【问题描述】:

我想将此 SQL 查询转换为 ANSI SQL。我无法理解这个查询的逻辑。

我使用雪花数据仓库,但由于加入前的“删除”语句,它不理解此查询,因此我试图将其分解。据我了解,行号列是根据时间戳为我提供从 1 到 N 的顺序并将其放置在 C 中。然后 C 在第一行以外的行(基于 id)上与自身连接并放置在 C1 中。然后从整体数据中删除C1,只留下第一行。

我可能对逻辑的理解有误,但我不习惯在加入之前看到“删除”语句。让我知道我的逻辑是否正确,或者指出我正确的方向。

此查询是从THISstackoverflow 问题复制/粘贴的,该问题与我要解决的确切情况相同,但规模更大。

with C as
(
  select ID,
         row_number() over(order by DT) as rn
  from YourTable
)
delete C1
from C as C1
  inner join C as C2
    on C1.rn = C2.rn-1 and
       C1.ID = C2.ID

我要解决的具体问题是这样的。假设我有这张桌子。我需要按主键组合(primKey 1 和 2)对行进行分区,同时保持时间戳顺序。

ID      primKey1  primKey2  checkVar1   checkVar2   theTimestamp 
100     1         2         302         423         2001-07-13
101     3         6         506         236         2005-10-25
100     1         2         302         423         2002-08-15
101     3         6         506         236         2008-12-05
101     3         6         300         100         2010-06-10
100     1         2         407         309         2005-09-05
100     1         2         302         423         2012-05-09
100     1         2         302         423         2003-07-24

一旦对行进行分区并且时间戳在每个分区中排序,我需要删除重复的 checkVar 组合(checkVar 1 & 2)行,直到下一次更改。因此给我留下了最早的唯一行。带星号的行是需要删除的行,因为它们是重复的。

ID      primKey1  primKey2  checkVar1   checkVar2   theTimestamp 
100     1         2         302         423         2001-07-13
*100    1         2         302         423         2002-08-15
*100    1         2         302         423         2003-07-24
100     1         2         407         309         2005-09-05
100     1         2         302         423         2012-05-09

101     3         6         506         236         2005-10-25
*101    3         6         506         236         2008-12-05
101     3         6         300         100         2010-06-10

这是最终结果。如您所见,对于 ID=100,即使第 1 条和第 3 条记录相同,但 checkVar 组合在两者之间发生了变化,这很好。我只删除重复项,直到值发生变化。

ID      primKey1  primKey2  checkVar1   checkVar2   theTimestamp 
100     1         2         302         423         2001-07-13
100     1         2         407         309         2005-09-05
100     1         2         302         423         2012-05-09

101     3         6         506         236         2005-10-25
101     3         6         300         100         2010-06-10

【问题讨论】:

  • 请说明您要实现的逻辑。从查询中看不出来。
  • 基于 CTE 的删除是适用于 Sql Server 但不适用于其他 DBMS 的事情之一。但是对于标准 SQL,可能需要一个在表中唯一的额外字段。显然,该 ID 不是该表中的主键,因为它有重复。
  • 嘿戈登和 LukStorms。我编辑了问题以显示我要完成的工作。虽然在我的情况下,没有真正的主键概念,因为我使用的主键不是唯一的。它们主要用于分区目的。虽然,主键和时间戳的组合总是唯一的。
  • 您是要从 CTE 还是从 YourTable 中删除?如果这是一次性的,您可能只想使用 CTAS 并创建一个新表。如果这是一个持续的事情,那么您可能想要在基表上创建一个物化视图。

标签: sql snowflake-cloud-data-platform


【解决方案1】:

如果你想为每个id保留最早的行,那么你可以使用:

delete from yourtable yt
    where yt.dt > (select min(yt2.dt)
                   from yourtable yt
                   where yt2.id = yd.id
                  );

如果这是您的意图,您的查询不会这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多