Oracle - 用另一列的值填充一列中的空值
Oracle - Fill null values in a column with values from another column
我正在使用 Oracle 11.1.1.9.0,我的目标是用 "Raw Materials" 列中每个产品的第一个 NOT NULL 值填充空值,即产品列中的 A、B 和 C。示例 table 和预期结果在此请求的末尾进行了说明。
None 以下代码集有效:
代码 1:
IFNULL(Raw Materials,
First_value(Raw Materials) OVER (PARTITION BY Product))
代码 2:
IFNULL(Raw Materials,
First_value(Raw Materials) OVER (PARTITION BY Product
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW))
代码 3:
COALESCE(lag(Raw Materials ignore null) OVER (partition by Product),
Raw Materials)
代码 4:
IFNULL(原材料,评估('LAG(%1, 1) OVER (PARTITION BY %2)' AS varchar2(20),原材料,产品))
注意:IFNULL 函数在环境中确实有效。它使用 IFNULL(Raw Materials, '1') 进行了测试,导致 Raw Materials 列中的所有空值都变为 1。
谢谢。
+---------+----------+ +---------+----------+
| product | material | | product | material |
+---------+----------+ +---------+----------+
| A | | | A | Apple |
| A | | | A | Apple |
| A | | | A | Apple |
| A | | | A | Apple |
| A | Apple | | A | Apple |
| B | | | B | Orange |
| B | | | B | Orange |
| B | | => | B | Orange |
| B | | | B | Orange |
| B | Orange | | B | Orange |
| C | | | C | Banana |
| C | | | C | Banana |
| C | | | C | Banana |
| C | | | C | Banana |
| C | Banana | | C | Banana |
+---------+----------+ +---------+----------+
Left is the example table data. Right is the intended result.
下面link"Oracle code environment"显示了Oracle逻辑SQL函数的代码环境和示例。
Oracle code environment
Oracle 逻辑 SQL 手册:https://docs.oracle.com/middleware/11119/biee/BIEUG/appsql.htm#CHDDCFJI
对于您的数据集,您可以简单地执行 window MAX()
或 MIN()
:
NVL(Raw_Materials, MAX(Raw_Materials) OVER(PARTITION BY Product))
如果 你有一列可以用来对行进行排序(我假设是 id
),你可以使用 LAG()
和 IGNORE NULLS
子句:
NVL(Raw_Materials, LAG(Raw_Materials IGNORE NULLS) OVER(PARTITION BY Product ORDER BY id))
您可以尝试以下查询,我们正在使用第一个值分析函数 nullif、COALESCE 等在行级别而不是列级别上工作。
with temp as (select 'A' product,NULL raw_material from dual union all
select 'A',NULL from dual union all
select 'A',NULL from dual union all
select 'A',NULL from dual union all
select 'A','APPLE' from dual union all
select 'B',NULL from dual union all
select 'B',NULL from dual union all
select 'B',NULL from dual union all
select 'B',NULL from dual union all
select 'B','ORANGE' from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C','Banana' from dual)
select a.*,FIRST_VALUE(raw_material IGNORE NULLS)
OVER (partition by product ORDER BY product) first_product from temp a;
Oracle 没有 IFNULL
函数。如果您在前两个代码片段中的任何一个中将 IFNULL
换成 COALESCE
,您的代码就会起作用:
SELECT t.*,
COALESCE(
raw_material,
FIRST_VALUE(raw_material)
IGNORE NULLS
OVER ( PARTITION BY product )
) AS updated_raw_material
FROM test_data t;
输出:
PRODUCT | RAW_MATERIAL | UPDATED_RAW_MATERIAL
:------ | :----------- | :-------------------
A | null | Apple
A | null | Apple
A | null | Apple
A | Apple | Apple
B | null | Orange
B | null | Orange
B | null | Orange
B | null | Orange
B | Orange | Orange
C | null | Banana
C | null | Banana
C | null | Banana
C | null | Banana
C | null | Banana
C | Banana | Banana
db<>fiddle here
虽然您说您正在寻找一些 "first" 值,但您的示例数据表明您只希望所有相同的产品具有相同的 material:
update mytable m1 set material =
(
select min(material)
from mytable m2
where m2.product = m1.product
);
如果你只想select这个数据。然后你可以使用这个:
select product, min(material) over (partition by product)
from mytable;
根据文档 (https://docs.oracle.com/cd/E28280_01/bi.1111/e10540/sqlref.htm#BIEMG678),OBIEE 似乎对解析 window 函数使用了一种特殊语法 (e.g. MIN() OVER()
):
select
product,
evaluate('min(%1) over (partition by %2)', material, product)
from mytable;
您必须通过相应地查看 EVALUATE_SUPPORT_LEVEL
来启用它。
(我希望我做对了。否则请阅读相关文档并自行尝试一些相关内容。)
我正在使用 Oracle 11.1.1.9.0,我的目标是用 "Raw Materials" 列中每个产品的第一个 NOT NULL 值填充空值,即产品列中的 A、B 和 C。示例 table 和预期结果在此请求的末尾进行了说明。
None 以下代码集有效:
代码 1:
IFNULL(Raw Materials,
First_value(Raw Materials) OVER (PARTITION BY Product))
代码 2:
IFNULL(Raw Materials,
First_value(Raw Materials) OVER (PARTITION BY Product
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW))
代码 3:
COALESCE(lag(Raw Materials ignore null) OVER (partition by Product),
Raw Materials)
代码 4:
IFNULL(原材料,评估('LAG(%1, 1) OVER (PARTITION BY %2)' AS varchar2(20),原材料,产品))
注意:IFNULL 函数在环境中确实有效。它使用 IFNULL(Raw Materials, '1') 进行了测试,导致 Raw Materials 列中的所有空值都变为 1。
谢谢。
+---------+----------+ +---------+----------+ | product | material | | product | material | +---------+----------+ +---------+----------+ | A | | | A | Apple | | A | | | A | Apple | | A | | | A | Apple | | A | | | A | Apple | | A | Apple | | A | Apple | | B | | | B | Orange | | B | | | B | Orange | | B | | => | B | Orange | | B | | | B | Orange | | B | Orange | | B | Orange | | C | | | C | Banana | | C | | | C | Banana | | C | | | C | Banana | | C | | | C | Banana | | C | Banana | | C | Banana | +---------+----------+ +---------+----------+ Left is the example table data. Right is the intended result.
下面link"Oracle code environment"显示了Oracle逻辑SQL函数的代码环境和示例。 Oracle code environment
Oracle 逻辑 SQL 手册:https://docs.oracle.com/middleware/11119/biee/BIEUG/appsql.htm#CHDDCFJI
对于您的数据集,您可以简单地执行 window MAX()
或 MIN()
:
NVL(Raw_Materials, MAX(Raw_Materials) OVER(PARTITION BY Product))
如果 你有一列可以用来对行进行排序(我假设是 id
),你可以使用 LAG()
和 IGNORE NULLS
子句:
NVL(Raw_Materials, LAG(Raw_Materials IGNORE NULLS) OVER(PARTITION BY Product ORDER BY id))
您可以尝试以下查询,我们正在使用第一个值分析函数 nullif、COALESCE 等在行级别而不是列级别上工作。
with temp as (select 'A' product,NULL raw_material from dual union all
select 'A',NULL from dual union all
select 'A',NULL from dual union all
select 'A',NULL from dual union all
select 'A','APPLE' from dual union all
select 'B',NULL from dual union all
select 'B',NULL from dual union all
select 'B',NULL from dual union all
select 'B',NULL from dual union all
select 'B','ORANGE' from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C',NULL from dual union all
select 'C','Banana' from dual)
select a.*,FIRST_VALUE(raw_material IGNORE NULLS)
OVER (partition by product ORDER BY product) first_product from temp a;
Oracle 没有 IFNULL
函数。如果您在前两个代码片段中的任何一个中将 IFNULL
换成 COALESCE
,您的代码就会起作用:
SELECT t.*,
COALESCE(
raw_material,
FIRST_VALUE(raw_material)
IGNORE NULLS
OVER ( PARTITION BY product )
) AS updated_raw_material
FROM test_data t;
输出:
PRODUCT | RAW_MATERIAL | UPDATED_RAW_MATERIAL :------ | :----------- | :------------------- A | null | Apple A | null | Apple A | null | Apple A | Apple | Apple B | null | Orange B | null | Orange B | null | Orange B | null | Orange B | Orange | Orange C | null | Banana C | null | Banana C | null | Banana C | null | Banana C | null | Banana C | Banana | Banana
db<>fiddle here
虽然您说您正在寻找一些 "first" 值,但您的示例数据表明您只希望所有相同的产品具有相同的 material:
update mytable m1 set material =
(
select min(material)
from mytable m2
where m2.product = m1.product
);
如果你只想select这个数据。然后你可以使用这个:
select product, min(material) over (partition by product)
from mytable;
根据文档 (https://docs.oracle.com/cd/E28280_01/bi.1111/e10540/sqlref.htm#BIEMG678),OBIEE 似乎对解析 window 函数使用了一种特殊语法 (e.g. MIN() OVER()
):
select
product,
evaluate('min(%1) over (partition by %2)', material, product)
from mytable;
您必须通过相应地查看 EVALUATE_SUPPORT_LEVEL
来启用它。
(我希望我做对了。否则请阅读相关文档并自行尝试一些相关内容。)