基于匹配值的雪花SQL计数和从另一个表求和

Posted

技术标签:

【中文标题】基于匹配值的雪花SQL计数和从另一个表求和【英文标题】:Snowflake SQL Counting and Summing from Another Table based on Matching Value 【发布时间】:2019-10-23 04:33:36 【问题描述】:

我正在尝试在雪花中执行 SQL 查询,以根据第一个表中的值计算不同表中的值。例如,我在 table1 和 table2 中找到一个匹配的值,并从表 2 中计算匹配它的行。

当我尝试执行此操作时,查询会运行,但结果数据的计数不正确。它看起来好像在做某种奇怪的突破/累积计数。 我已经尝试阅读示例并在谷歌上搜索这样的示例,但有趣的是在非雪花 SQL 中,我看到的示例不需要按我尝试选择的计数“分组”。

在雪花中它会给我一个错误,除非我将 (select count() 来自... 但是这样做似乎会返回一个过度计数/对值求和的结果,当我删除它时 (select count()... 行和分组依据,它会正确执行其他所有操作,所以我我猜那里有什么特别不对劲的地方。

select 
    "naming_db"."public"."username".name as "Name",
    "naming_db"."public"."addresses".address as "Address",
    count(*) as "Shoe Count",
    (select count(*) from "data_db"."records"."orderID" where 
    "data_db"."records"."orderID".ID = "data_db"."records"."userinfo".ID) as "Orders",
    sum("data_db"."records"."userinfo".revenue) as "Spend"
from "data_db"."records"."userinfo"
    join "naming_db"."public"."username" on "naming_db"."public"."username".name = "data_db"."records"."userinfo".nameid
    join "naming_db"."public"."addresses" on "naming_db"."public"."addresses".address = "data_db"."records"."userinfo".addressid
    full join "data_db"."records"."orderID" on "data_db"."records"."userinfo".ID = "data_db"."records"."orderID".ID
group by 1,2,4

我认为 (select count(*) from... 行是问题所在,但我似乎无法弄清楚如何以一种可以使查询运行并返回我想要的结果的方式编写它。

刚刚编辑了查询以使其更有意义。试图混淆那里的一些信息,但我意识到这太令人困惑了抱歉!

这是我想要的结果。当我删除“订单”行时,我得到了这个 - 即 (select count(*) from...

Correct but missing Orders

以下是我在“订单”行中添加时得到的结果: Incorrect summing and breaks out more rows

【问题讨论】:

选择不同的计数(*),这可能会对您有所帮助。 您应该谈谈表 1-3 包含的内容以及它们之间的关系。需要该信息来确保您获得正确的解决方案。 在两个不同的列上两次加入table1 是高度可疑的。样本数据和期望的结果真的很有帮助。 很抱歉。当我试图混淆某些信息时,我意识到这比我想要的更令人困惑,但我已经对其进行了修改以更好地显示。让我知道现在是否有意义!我还添加了结果示例。 您的描述现在更好了,但仍然缺乏细节。具体来说,userinfo 不清楚:它是否包含每个用户的一条记录,还是一个订单表?如果是订单表,那么 orderID 可能是订单详细信息吗?表的唯一键是什么? 【参考方案1】:

重新排列查询后,看起来您有:

    userinfoUser 表,每个用户包含一行,并且每个用户也有一个累积的收入金额 orderIDOrder 表,其中包含每个客户每个产品的数量 usernameaddresses 仅用于显示用户联系信息(不重要)。

仍然很难理解你的聚合应该显示什么,所以我试图猜测:

    鞋数在您修改后的查询中显示为蓝色。它计算每个用户的累积行数,即现在的订单行数。鞋子数据曾经在查询中,但您已将其删除,因此 Shoe Count 现在没有意义了。 订单数很可能是每个用户的订单总数,以及该用户订单表中的行数。但是 鞋码 没有区别,这让我想知道为什么。 支出是每位用户的收入。

FULL JOIN 的使用令人困惑。它表示某些订单是针对非注册用户的 - 在userinfo 表中不存在。这对我来说没有意义。您的示例表明所有订单都来自userinfo 中的用户,因此不需要FULL JOIN。 为什么需要它?

解决方案应该非常简单。如果我不理解您的要求,请告诉我:

SELECT
  ANY_VALUE(n.name) AS "Name",
  ANY_VALUE(a.address) AS "Address",
  COUNT(*) AS "Shoe Count", 
  COUNT(o.ID) AS "Orders",
  ANY_VALUE(u.revenue) AS "Spend"
FROM "data_db"."records"."userinfo" u
INNER JOIN "naming_db"."public"."username" n ON n.name = u.nameid
INNER JOIN "naming_db"."public"."addresses" a ON a.address = u.addressid
INNER JOIN "data_db"."records"."orderID" o ON o.ID = u.ID
GROUP BY u.ID

【讨论】:

很抱歉给您带来了困惑!我已经更新了查询以更清楚。我想根据从另一个表中找到的匹配 ID 计算所有 orderID。我希望我的措辞正确哈哈。我附上了结果的示例截图以及我希望实现的目标。感谢您的帮助! 您仍然没有尽可能具体,可能是因为您想隐藏真实案例的细节。你说“另一张桌子”,但不是哪个。从您的最新示例中,我们可以假设您的意思是 userinfo 表。我怀疑您的问题的至少一部分来自想要显示不同的聚合,其中一些数字已被表连接重复,导致不正确的高数字。但是,如果基表中只有一个数字,则可以使用 ANY_VALUE() 来解决此问题。【参考方案2】:

您的子选择是雪有限支持的相关子查询。因此,如果您转向一个计算所有 ID 的 CTE,那么您应该得到您所要求的。

WITH order_counts AS (
    SELECT ID, count(*) as count data_db.records.orderID group by 1
)
select 
    un.name as Name,
    a.address as Address,
    count(*) as Shoe Count,
    oc.count as Orders,
    sum(ui.revenue) as Spend
from data_db.records.userinfo as ui
join naming_db.public.username as un
    on un.name = ui.nameid
join naming_db.public.addresses as a
    on a.address = ui.addressid
left join order_counts as oc
    on ui.ID = oc.ID
group by 1,2,4

我还插入了一些别名,以便 SQL 更具可读性。

【讨论】:

这让我成功了 99%!我意识到应该使用另一个 ID,那是最后一块,哈哈。非常感谢您的帮助!【参考方案3】:

您可以在column 鞋子上使用sum() 而不是subquery

select 
    "table1".name as "Name",
    "table1".address as "Address",
    count(*) as "Counts",
    sum(case when coalesce("table3".shoeID, 0) != 0 then 1 else 0 end) as "Shoes",
    sum("table2".shoecount) as "Number of Shoes"
from "table2"
join "table1" on "table1".name = "table2".name
join "table1" on "table1".Address = "table2".Address
full join "table3" on "table3".shoeID = "table2".shoeID
group by 1,2,4

【讨论】:

我试过这个,但我不太确定 coalesce 是如何工作的。它抛出了一个错误,因为 shoeID 不是一个数值——它是字母数字,所以我猜它与之后的逻辑有关?但我也认为它不会根据在另一张表中找到的 ID 计算鞋子的数量。感谢您的帮助!

以上是关于基于匹配值的雪花SQL计数和从另一个表求和的主要内容,如果未能解决你的问题,请参考以下文章

从另一个表中删除 ID 不匹配的 sql 行

SQL 计数匹配

如果存在匹配值,则从另一个表中检索数据 - 否则基于第一个连接条件返回

用于生成基于新列的匹配字段值的 SQL 逻辑

如何从另一个表中获取每个值的计数?

如何从另一个 SQL 表中获取两个不同列的匹配数据:Inner Join 和/或 Union?