我有(我认为是)一个相当复杂的查询。该查询获取我想要的记录,然后获取第一个响应中引用的所有数据。如果我的条件子查询是字符串,则有效,但如果它是一个字段(具有完全相同的值),则无效。
// Query with string as conditional in lowest sub-query (4th line from the bottom)
SELECT
e1.entity as entity
,ARRAY_CAT(
ARRAY_COMPACT(
ARRAY_CONSTRUCT(
any_value(e2.entity),
any_value(u1.user)
)
)
,ARRAY_AGG(e3.entity)
) as includes
FROM ENTITIES e1
LEFT JOIN ENTITIES e2 ON e1.entity:owner:workspace = e2.entity:id
LEFT JOIN USERS u1 ON e1.entity:owner:user = u1.user:id
LEFT JOIN ENTITIES e3 ON e3.entity:id IN (
SELECT ee2.value FROM
table(FLATTEN( input=>
SELECT SPLIT(LISTAGG( CASE WHEN IS_ARRAY(ee1.value:id) THEN ARRAY_TO_STRING(ee1.value:id, ',') ELSE ee1.value:id END, ','), ',')
FROM table(FLATTEN( input => ( SELECT e4.entity:relationships:entities FROM ENTITIES e4 WHERE e4.entity:id = 'bd265f29-ca32-449a-b765-bb488e4d6b3c' ) )) ee1
)) ee2
)
GROUP BY e1.entity
以上内容产生:
“实体”列: https://jsonblob.com/6d98b587-8989-11e9-b738-a9487a0dac0b
“包含”列: https://jsonblob.com/068a8672-8988-11e9-b738-77f0e471310b
但是,如果将uuid字符串(bd265f29-ca32-449a-b765-bb488e4d6b3c
)更改为e1.entity:id
(如下),则会收到错误SQL compilation error: Unsupported subquery type cannot be evaluated
。
SELECT
e1.entity as entity
,ARRAY_CAT(
ARRAY_COMPACT(
ARRAY_CONSTRUCT(
any_value(e2.entity),
any_value(u1.user)
)
)
,ARRAY_AGG(e3.entity)
) as includes
FROM ENTITIES e1
LEFT JOIN ENTITIES e2 ON e1.entity:owner:workspace = e2.entity:id
LEFT JOIN USERS u1 ON e1.entity:owner:user = u1.user:id
LEFT JOIN ENTITIES e3 ON e3.entity:id IN (
SELECT ee2.value FROM
table(FLATTEN( input=>
SELECT SPLIT(LISTAGG( CASE WHEN IS_ARRAY(ee1.value:id) THEN ARRAY_TO_STRING(ee1.value:id, ',') ELSE ee1.value:id END, ','), ',')
FROM table(FLATTEN( input => ( SELECT e4.entity:relationships:entities FROM ENTITIES e4 WHERE e4.entity:id = e1.entity:id ) )) ee1
)) ee2
)
GROUP BY e1.entity
我不知道为什么交换机会导致错误。为什么我的子查询只能使用字符串,而不能使用字段引用?
答案 0 :(得分:1)
因此,使用几个 CTE 来提供数据,何时可以完成大部分相关子查询的提升。我将两种形式的事物数组都放在实体中,并在您的 FLATTEN 用法中表示了具有多个 id 的单个实体:
WITH users AS (
SELECT parse_json('{"id":1}') as user
), entities AS (
SELECT parse_json(column1) as entity
FROM VALUES
('{"id":10, "relationships":{"entities":[{"id":11},{"id":12}]}, "owner":{"user":1,"workspace":10}}'),
('{"id":11, "relationships":{"entities":[{"id":11}]}}'),
('{"id":12, "relationships":{"entities":[{"id":[10,11]}]}}')
), ent1 AS (
SELECT e4.entity:id as ent_id
,ee1.index
,SPLIT(LISTAGG( IFF( IS_ARRAY(ee1.value:id), ARRAY_TO_STRING(ee1.value:id, ','), ee1.value:id), ','), ',') as vals
FROM ENTITIES AS e4,
TABLE(FLATTEN( input => e4.entity:relationships:entities )) ee1
GROUP BY 1,2
), ent_rels AS (
SELECT ent_id, ee2.value::number as rel_id
FROM ent1 ee1,
TABLE(FLATTEN( input => ee1.vals)) ee2
)
SELECT
e1.entity:id as entity
,e2.entity:id as e2_entity
,u1.user:id as u1_user
,e3.entity:id as e3_entity
FROM ENTITIES e1
LEFT JOIN ENTITIES e2 ON e1.entity:owner:workspace = e2.entity:id
LEFT JOIN USERS u1 ON e1.entity:owner:user = u1.user:id
LEFT JOIN ent_rels er ON er.ent_id = e1.entity:id
LEFT JOIN ENTITIES e3 ON e3.entity:id = er.rel_id
ORDER BY e1.entity:id;
所以此 SQL 不是您拥有的选择结果,但确实显示了按预期加入的内容。
ENTITY E2_ENTITY U1_USER E3_ENTITY
10 10 1 11
10 10 1 12
11 null null 11
12 null null 10
12 null null 11
所以这个最终选择是你原来的方式
SELECT
e1.entity as entity
,ARRAY_CAT(
ARRAY_COMPACT(
ARRAY_CONSTRUCT(
any_value(e2.entity),
any_value(u1.user)
)
)
,ARRAY_AGG(e3.entity)
) as includes
FROM ENTITIES e1
LEFT JOIN ENTITIES e2 ON e1.entity:owner:workspace = e2.entity:id
LEFT JOIN USERS u1 ON e1.entity:owner:user = u1.user:id
LEFT JOIN ent_rels er ON er.ent_id = e1.entity:id
LEFT JOIN ENTITIES e3 ON e3.entity:id = er.rel_id
GROUP BY e1.entity
ORDER BY e1.entity:id;
另外,考虑到您正在撤消两层嵌套以获得匹配的 ID,您可以避免使用 LISTAGG 和 SPLITS 并通过以下方式将它们分解:
), ent1 AS (
SELECT e4.entity:id as ent_id
,ee1.value:id as vals
FROM ENTITIES AS e4,
TABLE(FLATTEN( input => e4.entity:relationships:entities )) ee1
), ent_rels AS (
SELECT ent_id
,coalesce(ee2.value,ee1.vals) as rel_id
FROM ent1 ee1,
TABLE(FLATTEN( input => ee1.vals, outer => true)) ee2
)
如果这是您的偏好,可以合并/嵌套:
, ent_rels AS (
SELECT ent_id
,coalesce(ee3.value,ee2.vals) as rel_id
FROM (
SELECT e1.entity:id as ent_id
,ee1.value:id as vals
FROM ENTITIES AS e1,
TABLE(FLATTEN( input => e1.entity:relationships:entities )) ee1
) ee2,
TABLE(FLATTEN( input => ee2.vals, outer => true)) ee3
)
答案 1 :(得分:0)
子查询上的雪花documentation包括以下限制:
仅当可以静态确定相关标量子查询返回一行时(例如,如果SELECT列表包含不带GROUP BY的聚合函数),当前才支持相关标量子查询。
所以您可以尝试:
<ion-content class="background">
<img src="../assets/imgs/bas1.png"/>
<ion-card>
<ion-card-header>
SIGNUP
</ion-card-header>
<ion-card-content>
<ion-list no-line>
<form [formGroup]="myForm" novalidate >
<ion-item>
<ion-input input type="text" placeholder="Name" formControlName="name"></ion-input>
</ion-item>
<ion-item no-lines *ngIf="( myForm.get('name').hasError('minlength') || myForm.get('name').hasError('required') ) && myForm.get('name').touched">
<div class="error" *ngIf="myForm.get('name').hasError('required') && myForm.get('name').touched">
Name is required
</div>
<div class="error" *ngIf="myForm.get('name').hasError('minlength') && myForm.get('name').touched">
Maximum of 6 characters
</div>
</ion-item>
<ion-item>
<ion-input input type="text" placeholder="Username" formControlName="username"></ion-input>
</ion-item>
<ion-item no-lines *ngIf="( myForm.get('username').hasError('minlength') || myForm.get('username').hasError('required') ) && myForm.get('username').touched">
<div class="error" *ngIf="myForm.get('username').hasError('required') && myForm.get('username').touched">
username is required
</div>
<div class="error" *ngIf="myForm.get('username').hasError('minlength') && myForm.get('username').touched">
Minimum of 6 characters
</div>
</ion-item>
<ion-item>
<ion-input type="email" placeholder="E-mail" formControlName="email"></ion-input>
</ion-item>
<ion-item no-lines *ngIf="( myForm.get('email').hasError('email') || myForm.get('email').hasError('required') ) && myForm.get('email').touched">
<div class="error" *ngIf="myForm.get('email').hasError('required') && myForm.get('username').touched">
email is required
</div>
<div class="error" *ngIf="myForm.get('email').hasError('email') && myForm.get('email').touched">
Enter valid email
</div>
</ion-item>
<ion-item>
<ion-input type="password" placeholder="Password" formControlName="password"></ion-input>
</ion-item>
<ion-item no-lines *ngIf="( myForm.get('password').hasError('required') ) && myForm.get('password').touched">
<div class="error" *ngIf="myForm.get('password').hasError('required') && myForm.get('password').touched">
password is required
</div>
</ion-item>
<ion-item>
<ion-input type="password" placeholder="confirmPassword" formControlName="confirmpassword"></ion-input>
</ion-item>
<ion-item no-lines *ngIf="( myForm.get('confirmpassword').hasError('required') ) && myForm.get('confirmpassword').touched">
<div class="error" *ngIf="myForm.get('confirmpassword').hasError('required') && myForm.get('confirmpassword').touched">
password should match
</div>
</ion-item>
</form>
<button ion-button block class="google" (click)="onSubmit(myForm)">SIGN-UP</button>
</ion-list>
</ion-card-content>
</ion-card>
</ion-content>
<style type="text/css">
.error
{
color:red;
}
</style>
答案 2 :(得分:0)
您是否尝试过像这样投射它?
e1.entity:id::string
答案 3 :(得分:0)
Snowflake文档中提到:
目前在FLATTEN内部具有相关性的子查询 不支持。
您不能简单地使用e1.entity:relationships:entities代替子查询吗?