如何在不更改表架构的情况下将查询结果存储在当前表上?
Posted
技术标签:
【中文标题】如何在不更改表架构的情况下将查询结果存储在当前表上?【英文标题】:How to store the result of query on the current table without changing the table schema? 【发布时间】:2016-05-01 11:08:43 【问题描述】:我有一个结构
id: "123",
scans:[
"scanid":"123",
"status":"sleep"
]
,
id: "123",
scans:[
"scanid":"123",
"status":"sleep"
]
查询删除重复:
SELECT *
FROM (
SELECT
*,
ROW_NUMBER()
OVER (PARTITION BY id)
row_number,
FROM table1
)
WHERE row_number = 1
我将目标表指定为 table1。
这里我将扫描作为重复记录,scanid 作为字符串,status 作为字符串。但是当我进行一些查询(我正在查询以删除重复项)并覆盖现有表时,表架构会发生变化。它变成scans_scanid(string)
和scans_status(string)
。扫描记录架构现在已更改。请建议我哪里出错了?
【问题讨论】:
提供您遇到问题的查询示例 Mikhail..我已经修改了这个问题。请检查。 【参考方案1】:1) 如果您在 Web UI 上运行查询,结果自动为flattened,这就是您看到架构发生变化的原因。
您需要运行查询并写信给destination table,您也可以在网络用户界面上执行此操作。
2) 如果您没有在 Web UI 上运行查询,但仍然看到架构已更改,则应进行显式选择,以便为您保留架构,例如:
select 'foo' as scans.scanid
这会为您创建一个类似输出的记录,但它不会是重复记录,请进一步阅读。
3) 对于某些用例,您可能需要使用NEST(expr)
function
将当前聚合范围内的所有值聚合成一个重复的 场地。例如,查询“SELECT x, NEST(y) FROM ... GROUP BY x” 为每个不同的 x 值返回一个输出记录,并包含一个 查询输入中与 x 配对的所有 y 值的重复字段。这 NEST 函数需要一个 GROUP BY 子句。
BigQuery 会自动展平查询结果,因此如果您使用 NEST ***查询的函数,结果不会包含重复 字段。使用产生的子选择时使用 NEST 函数 供同一查询立即使用的中间结果。
【讨论】:
Pentium10.. 我用的是case1),甚至将目标表指定为table1。这也会导致架构发生变化。 确保不要把桌子弄平。 是的,我选择了写入首选项作为覆盖表,并且在结果架构中我取消了展平结果..但架构仍然是展平的。现在,如果我尝试使用以前的模式插入更多行,则会引发错误。 我要感谢 google-bigquery 团队及时回复我的所有问题,让我意识到使用任何方法的积极和消极方面。【参考方案2】:众所周知,NEST() 与 UnFlatten Results Output 不兼容,主要用于子查询中的中间结果。
尝试以下解决方法
请注意,我将 INTEGER 用于 id 和 scanid。如果它们应该是 STRING,您需要
一种。更改输出架构部分
以及
湾。删除 t = scanid:parseInt(x[0]), status:x[1]
中 parseInt() 函数的使用
SELECT id, scans.scanid, scans.status
FROM JS(
( // input table
SELECT id, NEST(CONCAT(STRING(scanid), ',', STRING(status))) AS scans
FROM (
SELECT id, scans.scanid, scans.status
FROM (
SELECT id, scans.scanid, scans.status,
ROW_NUMBER() OVER (PARTITION BY id) AS dup
FROM table1
) WHERE dup = 1
) GROUP BY id
),
id, scans, // input columns
"['name': 'id', 'type': 'INTEGER', // output schema
'name': 'scans', 'type': 'RECORD',
'mode': 'REPEATED',
'fields': [
'name': 'scanid', 'type': 'INTEGER',
'name': 'status', 'type': 'STRING'
]
]",
"function(row, emit) // function
var c = [];
for (var i = 0; i < row.scans.length; i++)
x = row.scans[i].toString().split(',');
t = scanid:parseInt(x[0]), status:x[1]
c.push(t);
;
emit(id: row.id, scans: c);
"
)
这里我使用BigQuery User-Defined Functions。它们非常强大,但仍有一些 Limits 和 Limitations 需要注意。也请记住 - 他们是相当有资格获得昂贵的候选人High-Compute queries
复杂的查询会消耗非常大的计算资源 相对于处理的字节数。通常,此类查询 包含大量的 JOIN 或 CROSS JOIN 子句或复杂的 用户自定义函数。
【讨论】:
以上是关于如何在不更改表架构的情况下将查询结果存储在当前表上?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不创建架构的情况下将 CSV 文件加载到 BigQuery
如何在不等待结果的情况下将 SQL 查询发送到 PHP 中的数据库