d3w*_*abe 6 aggregate-functions google-bigquery
我有一个“供应商”表,看起来像这样......
**company itemKey itemPriceA itemPriceB**
companyA, 203913, 20, 10
companyA, 203914, 20, 20
companyA, 203915, 25, 5
companyA, 203916, 10, 10
Run Code Online (Sandbox Code Playgroud)
每个公司可能有数百万行,我想查询它以返回每个公司的 itemPriceA 和 itemPriceB 之间的代表性增量。我不在乎我带回哪个增量,只要它不是零/空(如第2行或第4行),所以我使用像这样的ANY_VALUE...
SELECT company
, ANY_VALUE(CASE WHEN (itemPriceA-itemPriceB)=0 THEN null ELSE (itemPriceA-itemPriceB) END)
FROM vendors
GROUP BY 1
Run Code Online (Sandbox Code Playgroud)
它似乎有效,但我注意到谷歌文档中有两句话似乎矛盾......
"当组中所有行的表达式为 NULL 时,返回 NULL。ANY_VALUE 的行为就像指定了 RESPECT NULLS;将考虑并选择表达式为 NULL 的行。 "
如果 ANY_VALUE 返回 null“当组中所有行的表达式为 NULL 时”,它不应该为 companyA 返回 null,正确的(因为 4 行中只有 2 行为 null)?但第二句话听起来确实会包含空行。
Ps,您可能想知道为什么我不简单地添加一个 WHERE 子句“WHERE itemPriceA-itemPriceB>0”,但如果一家公司只有匹配的价格,我仍然希望该公司在我的结果中返回。
恐怕所接受的答案必须提供与文档相矛盾的更有力的证据。
@Raul Saucedo 建议以下 BigQuery 文档引用 WHERE 子句:
考虑并选择表达式为 NULL 的行
不是这种情况。ANY_VALUE 文档中的任何地方都没有提到 WHERE 子句。(页面上没有任何地方上没有任何地方。尝试一下ctrl+f。)正如我将解释的那样,文档很清楚。
@d3wannabe 对此的疑问是正确的:
它似乎有效,但我注意到谷歌文档中有两句话似乎矛盾......
“当组中所有行的表达式为 NULL 时,返回 NULL。ANY_VALUE 的行为就像指定了 RESPECT NULLS;表达式为 NULL 的行将被考虑并可能被选择。”
但这些文档并不矛盾。2句话并存。
我们可以使用ARRAY_AGG将一组值转换为列表。该聚合函数可以选择 INGORE NULLS。然后,我们在忽略空值后从列表中选择 1 项。
如果我们有一个包含 2 列的表:id和mixed_data,其中mixed_data一些行包含空值:
SELECT
id,
ARRAY_AGG( -- turn the mixed_data values into a list
mixed_data -- we'll create an array of values from our mixed_data column
IGNORE NULLS -- there we go!
LIMIT 1 -- only fill the array with 1 thing
)[SAFE_OFFSET(0)] -- grab the first item in the array
AS any_mixed_data_without_nulls
FROM your_table
GROUP BY id
Run Code Online (Sandbox Code Playgroud)
在这里查看类似的答案:
有证据表明文档可能与函数的实际行为不一致。查看Samuel 的最新回答来探索他的方法论。
但是,我们无法知道文档是否不正确且 ANY_VALUE 的行为符合预期,或者 ANY_VALUE 是否存在错误且文档表达了预期的行为。我们不知道 Google 在解决此问题时是否会更正文档或功能。
因此,我将继续使用 ARRAY_AGG 创建一个忽略空值的安全 ANY_VALUE,直到我们看到 Google 的修复。
请在 Google 的问题跟踪器中对该问题进行投票,以解决此问题。
小智 3
这是关于 \xe2\x80\x9cany_value 如何与 null 值\xe2\x80\x9d 一起使用的说明。
\n对于any_value,如果存在不同于null 的值,则始终返回第一个值。
\nSELECT ANY_VALUE(fruit) as any_value\nFROM UNNEST([null, "banana",null,null]) as fruit;\nRun Code Online (Sandbox Code Playgroud)\n如果所有行都有 null 值,则返回 null。指的是这句话
\n\n\n\xe2\x80\x9c当组中所有行的表达式为 NULL 时返回 NULL\xe2\x80\x9d
\n
SELECT ANY_VALUE(fruit) as any_value\nFROM UNNEST([null, null, null]) as fruit\n \nRun Code Online (Sandbox Code Playgroud)\n如果一个值为 null 并且您在 where 子句中指定,则返回 null。参考了这些句子
\n\n\n\xe2\x80\x9cANY_VALUE 的行为就像指定了 RESPECT NULLS 一样;考虑并选择表达式为 NULL 的行。\xe2\x80\x9d
\n
SELECT ANY_VALUE(fruit) as any_value\nFROM UNNEST(["apple", "banana", null]) as fruit\nwhere fruit is null\nRun Code Online (Sandbox Code Playgroud)\n始终取决于您使用的过滤器以及any_value 内的字段。
\n你可以看到这个例子,返回两行不为0的行。
\nSELECT ANY_VALUE(e).company, (itemPriceA-itemPriceB) as value\nFROM `vendor` e\nwhere (itemPriceA-itemPriceB)!=0\ngroup by e.company\nRun Code Online (Sandbox Code Playgroud)\n