UNNEST 多个值?
UNNEST Multiple Values?
我正在尝试从另一个 table 中制作一个 table。原来的 table 有一行看起来像这样:
------------------------
| col1 | col 2 | col 3 |
------------------------
| item | a,b,c | 1,2,3 |
------------------------
我正在尝试将该行放入 table 中,如下所示:
------------------------
| col1 | col 2 | col 3 |
------------------------
| item | a | 1 |
------------------------
| item | b | 2 |
------------------------
| item | c | 3 |
------------------------
所以基本上我试图同时 UNNEST 两个逗号分隔的行。到目前为止,我想出的最好的办法是分别对每一列进行 UNNEST,然后尝试将两个结果 tables 组合起来(我也在努力解决),但理想情况下我希望将其合二为一步骤.
这是我一次 UNNEST 一行的查询:
SELECT
col1, col2, col3
FROM
tableName,
UNNEST(SPLIT(col2)) AS col2
这是我尝试将 UNNEST 作为子查询执行的尝试,但它给出了大量结果:
SELECT sub.*
FROM (
SELECT
col1, col2, col3 AS col3
FROM
tableName,
UNNEST(SPLIT(col2)) AS col2
WHERE
randomCol = 'something'
) sub,
UNNEST(SPLIT(sub.col3)) AS col3
说原来的 table 有 'a row':你是说一个吗?如果是,这就可以了:
with
num_rows_ as (
select length( regexp_replace((select b from t), '[^,]+')) + 1 value_ from dual),
a_ as (
select a from t),
b_ as (
select regexp_substr( (select b from t), '[^,]', 1, level ) b,rownum rownum_
from dual
connect by level <= (select value_ from num_rows_)),
c_ as (
select regexp_substr( (select c from t), '[^,]', 1, level ) c,rownum rownum_
from dual
connect by level <= (select value_ from num_rows_))
select a_.a,b_.b,c_.c
from a_
full outer join b_ on 1=1
inner join c_ on b_.rownum_ = c_.rownum_;
http://sqlfiddle.com/#!4/f795b9/29
或更短,一步完成:
with a_ as
(select a from t),
b_c_ as (
select regexp_substr( (select b from t), '[^,]', 1, level ) b,regexp_substr( (select c from t), '[^,]', 1, level ) c
from dual
connect by level <= (length( regexp_replace((select b from t), '[^,]+')) + 1)
)
select * from a_ cross join b_c_;
您可以使用 unnest(split(col))
策略,但不要交叉连接两列。您的回答暗示了逗号分隔值的隐含顺序,因此您需要建立一个字段(下面的 RowNumber
)来指示此顺序。
with Expanded2 as (
select
tableName.col1,
col2.col2,
row_number() over (partition by col1 order by 1) RowNumber
from
tableName,
unnest(split(col2)) col2
), Expanded3 as (
select
tableName.col1,
col3.col3,
row_number() over (partition by col1 order by 1) RowNumber
from
tableName,
unnest(split(col3)) col3
)
select
Expanded2.col1,
Expanded2.col2,
Expanded3.col3
from
Expanded2
full outer join Expanded3 on
Expanded2.col1 = Expanded3.col1
and Expanded2.RowNumber = Expanded3.RowNumber
我不确定您的 rdbms 如何处理有效的空 window 分区。以上在 PostgreSQL 中有效。 SQL 服务器需要 order by (select null)
。 Ymmv.
SQL 标准允许将多个值传递给 unnest()
函数。
因此以下内容应该有效(并且在 Postgres 中有效)
select d.col1,
t.*
from data d
cross join unnest(string_to_array(d.col2, ','), string_to_array(d.col3, ',')) as t(col1, col2)
这也能正确处理列表中不同数量的元素。
但是,我不知道您的专有 DBMS 是否支持它。
我正在尝试从另一个 table 中制作一个 table。原来的 table 有一行看起来像这样:
------------------------
| col1 | col 2 | col 3 |
------------------------
| item | a,b,c | 1,2,3 |
------------------------
我正在尝试将该行放入 table 中,如下所示:
------------------------
| col1 | col 2 | col 3 |
------------------------
| item | a | 1 |
------------------------
| item | b | 2 |
------------------------
| item | c | 3 |
------------------------
所以基本上我试图同时 UNNEST 两个逗号分隔的行。到目前为止,我想出的最好的办法是分别对每一列进行 UNNEST,然后尝试将两个结果 tables 组合起来(我也在努力解决),但理想情况下我希望将其合二为一步骤.
这是我一次 UNNEST 一行的查询:
SELECT
col1, col2, col3
FROM
tableName,
UNNEST(SPLIT(col2)) AS col2
这是我尝试将 UNNEST 作为子查询执行的尝试,但它给出了大量结果:
SELECT sub.*
FROM (
SELECT
col1, col2, col3 AS col3
FROM
tableName,
UNNEST(SPLIT(col2)) AS col2
WHERE
randomCol = 'something'
) sub,
UNNEST(SPLIT(sub.col3)) AS col3
说原来的 table 有 'a row':你是说一个吗?如果是,这就可以了:
with
num_rows_ as (
select length( regexp_replace((select b from t), '[^,]+')) + 1 value_ from dual),
a_ as (
select a from t),
b_ as (
select regexp_substr( (select b from t), '[^,]', 1, level ) b,rownum rownum_
from dual
connect by level <= (select value_ from num_rows_)),
c_ as (
select regexp_substr( (select c from t), '[^,]', 1, level ) c,rownum rownum_
from dual
connect by level <= (select value_ from num_rows_))
select a_.a,b_.b,c_.c
from a_
full outer join b_ on 1=1
inner join c_ on b_.rownum_ = c_.rownum_;
http://sqlfiddle.com/#!4/f795b9/29
或更短,一步完成:
with a_ as
(select a from t),
b_c_ as (
select regexp_substr( (select b from t), '[^,]', 1, level ) b,regexp_substr( (select c from t), '[^,]', 1, level ) c
from dual
connect by level <= (length( regexp_replace((select b from t), '[^,]+')) + 1)
)
select * from a_ cross join b_c_;
您可以使用 unnest(split(col))
策略,但不要交叉连接两列。您的回答暗示了逗号分隔值的隐含顺序,因此您需要建立一个字段(下面的 RowNumber
)来指示此顺序。
with Expanded2 as (
select
tableName.col1,
col2.col2,
row_number() over (partition by col1 order by 1) RowNumber
from
tableName,
unnest(split(col2)) col2
), Expanded3 as (
select
tableName.col1,
col3.col3,
row_number() over (partition by col1 order by 1) RowNumber
from
tableName,
unnest(split(col3)) col3
)
select
Expanded2.col1,
Expanded2.col2,
Expanded3.col3
from
Expanded2
full outer join Expanded3 on
Expanded2.col1 = Expanded3.col1
and Expanded2.RowNumber = Expanded3.RowNumber
我不确定您的 rdbms 如何处理有效的空 window 分区。以上在 PostgreSQL 中有效。 SQL 服务器需要 order by (select null)
。 Ymmv.
SQL 标准允许将多个值传递给 unnest()
函数。
因此以下内容应该有效(并且在 Postgres 中有效)
select d.col1,
t.*
from data d
cross join unnest(string_to_array(d.col2, ','), string_to_array(d.col3, ',')) as t(col1, col2)
这也能正确处理列表中不同数量的元素。
但是,我不知道您的专有 DBMS 是否支持它。