【问题标题】:Snowflake: Unsupported subquery for DISTINCT - Column order matters?雪花:不支持 DISTINCT 的子查询 - 列顺序很重要?
【发布时间】:2020-10-28 17:50:10
【问题描述】:

我有两个相关的表(没有列出不必要的列):

LOCATION

VENUE_ID - NUMBER(38,0)

VISIT

ID - NUMBER(38,0)
VENUE_ID - NUMBER(38,0)
DEVICE_ID - VARCHAR(16777216)

这些表是相关的,因此访问与通过VENUE_ID 的位置相关联。

我正在尝试按位置获取唯一设备 ID 的计数,因此我编写了以下查询:

SELECT "d"."VENUE_ID"
    , (
      SELECT COUNT(*)
      FROM (
          SELECT DISTINCT "f0"."DEVICE_ID"
          FROM "MAIN"."VISIT" AS "f0"
          WHERE "d"."VENUE_ID" = "f0"."VENUE_ID"
      ) AS "t")
FROM "MAIN"."LOCATION" AS "d"

不幸的是,这个查询导致了神秘错误SQL compilation error: Unsupported subquery type cannot be evaluated

通过一些实验,我发现我可以让查询返回而不会出错,但前提是我在 SELECT 中的现有子查询之前添加了一个额外的(无用的)子查询:

SELECT "d"."VENUE_ID"

    -- New Useless Subquery
    , (
      SELECT COUNT(*)
      FROM "MAIN"."VISIT" AS "f"
      WHERE "d"."VENUE_ID" = "f"."VENUE_ID")
    --

    , (
      SELECT COUNT(*)
      FROM (
          SELECT DISTINCT "f0"."DEVICE_ID"
          FROM "MAIN"."VISIT" AS "f0"
          WHERE "d"."VENUE_ID" = "f0"."VENUE_ID"
      ) AS "t")
FROM "MAIN"."LOCATION" AS "d"

如果我将新的子查询移动到 select after 不同的子查询中的任何位置,则会返回错误。我已经查看了the documentation on subqueries in Snowflake,要么我不明白这如何适用于我的查询,要么我面临着无证行为。有人知道这里发生了什么吗?

【问题讨论】:

  • 你可以通过使用 LEFT JOIN SELECT "d"."VENUE_ID", COUNT(DISTINCT "f0"."DEVICE_ID") FROM "MAIN"."LOCATION" AS "d" LEFT JOIN "MAIN"."VISIT" AS "f0" ON "d"."VENUE_ID" = "f0"."VENUE_ID" GROUP BY "d"."VENUE_ID" 来避免相关的子队列,虽然很有趣
  • 它类似于scenario I've encountered。重写查询很容易(我想大多数答案都会集中在这个上面)。我也很好奇优化器允许一个查询并禁止另一个查询的确切规则是什么。
  • 这是我面临的问题的一个很好的解决方案,但就像我在 OP 中所说的那样,我已经有办法检索我需要的数据。我正在寻找关于正在发生的事情的解释,而不是针对我的特定要求的解决方案。这是我发现的 Snowflake 中的错误吗?

标签: snowflake-cloud-data-platform


【解决方案1】:

我认为你让这变得比需要的更复杂。以下应该是您所需要的:

SELECT l.venue_id
  , count(distinct v.device_id)
FROM location l
LEFT JOIN visit v
 on l.venue_id = v.venue_id
GROUP BY l.venue_id

【讨论】:

  • 如果需求是最初表达的(而不是对真实需求的简化),那么你甚至不需要位置表;您可以仅使用访问表在上述查询中运行 SELECT
  • 您需要位置表来查找访问次数为 0 的场景,它们不会出现在访问计数中。
  • 我同意 - 如果这是要求的一部分,它可能是。我不清楚它是否来自语句“我正在尝试按位置获取唯一设备 ID 的计数”
【解决方案2】:

答案有点神秘,但发生的事情是这样的:

您要求 ONE 值,并且您需要保证您的子查询仅返回 ONE 值。一个明确的条款不能保证这一点。在某些数据库中,只要数据返回一行就可以工作,但是当您得到两行时,数据库就会抛出错误。

Snowflake 对其子查询分析非常严格。所以你需要使用一个保证总是返回一个值的子查询,例如 select sum(..), select count(..)

【讨论】:

  • 查询中的 DISTINCT 类包含在 COUNT(*) 中。此外,即使存在 DISTINCT,问题中的第一个查询也可以完美运行。
  • 你是对的。我坚持我已经弄清楚了,在大多数情况下似乎都是这样,但你是对的,我仍然没有正确的答案来理解为什么不支持某些子查询
  • @GravlLift 我目前的研究(这只是基于我的测试)是雪花与使用称为子查询去相关的查询重写方法的查询计划器一起使用。对于这种查询重写,有一些不支持的子查询。例如:我有这个查询UPDATE db1.tmetrics AS m SET m.OAGroup = (SELECT DISTINCT l.OAGroup FROM db1.group_mapping l WHERE l.agroup = m.agroup) WHERE OAGroup IS NULL AND AGroup IS NOT NULL,它报告了一个无效的子查询,因为存在一个 NULL 敏感的相关性。添加像 l.assignmentgroup 这样的子句不是 null 解决了它
猜你喜欢
  • 2023-02-24
  • 1970-01-01
  • 2023-02-09
  • 1970-01-01
  • 1970-01-01
  • 2020-02-02
  • 1970-01-01
  • 1970-01-01
  • 2015-06-02
相关资源
最近更新 更多