Oracle - заполнить пустые значения в столбце значениями из другого столбца. - PullRequest
0 голосов
/ 13 января 2020

Я использую Oracle 11.1.1.9.0, и моя цель - заполнить пустые значения первыми значениями NOT NULL в столбце «Сырье» для каждого продукта, т. Е. A, B и C в столбце Product. Пример таблицы и предполагаемый результат показаны в конце этого запроса.

Ни один из кодов, указанных ниже, не работает:

КОД 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)) более (PARTITION BY% 2) 'AS varchar2 (20), Сырье, продукт))

Примечание: функция IFNULL работает в окружающей среде. Он был протестирован с помощью IFNULL («Сырье», «1»), и в столбце «Сырье» все нулевые значения стали равными 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.

Ссылка ниже "Oracle кодовая среда "показывает кодовую среду и примеры функции Oracle Logical SQL. Oracle код среды

Oracle Логическое SQL Руководство: https://docs.oracle.com/middleware/11119/biee/BIEUG/appsql.htm#CHDDCFJI

Ответы [ 4 ]

1 голос
/ 13 января 2020

Для вашего набора данных вы можете просто сделать окно 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))
0 голосов
/ 13 января 2020

В то время как вы говорите, что ищете какое-то «первое» значение, ваши примерные данные показывают, что вы просто хотите, чтобы все одинаковые продукты имели одинаковый материал:

update mytable m1 set material = 
(
  select min(material)
  from mytable m2
  where m2.product = m1.product
);

Если вы просто хотите выбрать это данные. Затем вы можете использовать это:

select product, min(material) over (partition by product)
from mytable;

Согласно документации (https://docs.oracle.com/cd/E28280_01/bi.1111/e10540/sqlref.htm#BIEMG678) кажется, что OBIEE использует специальный синтаксис для оконных функций analyti c (e.g. MIN() OVER()):

select
  product,
  evaluate('min(%1) over (partition by %2)', material, product)
from mytable;

Вы должны включить это, указав EVALUATE_SUPPORT_LEVEL соответственно.

(Надеюсь, я понял это правильно. В противном случае прочитайте документы по этому вопросу и попробуйте что-нибудь подобное для себя. )

0 голосов
/ 13 января 2020

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       | <em>null</em>         | Apple               
A       | <em>null</em>         | Apple               
A       | <em>null</em>         | Apple               
A       | Apple        | Apple               
B       | <em>null</em>         | Orange              
B       | <em>null</em>         | Orange              
B       | <em>null</em>         | Orange              
B       | <em>null</em>         | Orange              
B       | Orange       | Orange              
C       | <em>null</em>         | Banana              
C       | <em>null</em>         | Banana              
C       | <em>null</em>         | Banana              
C       | <em>null</em>         | Banana              
C       | <em>null</em>         | Banana              
C       | Banana       | Banana              

дБ <> скрипка здесь

0 голосов
/ 13 января 2020

Вы можете попробовать выполнить запрос ниже. Мы используем First value analyti c, функция nullif, COALESCE, et c работает на уровне строки, а не на уровне столбца.

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;
...