oracle - 合并多个列值

oracle - merge multiple column values

我有以下数据集:

DAILY_DATA:

DEPT CLASS DATE BOOK_ID TRANSFER_RETAIL TRANSFER_COST
100 1 10-APR 100 23.4 54
100 1 10-APR 200 0 92

我想合并 TRANSFER_RETAIL 和 TRANSFER_COST 的值 并将其添加到 BOOK_ID = 100

所在的行

因此该行将显示:

DEPT CLASS DATE BOOK_ID TRANSFER_RETAIL TRANSFER_COST
100 1 10-APR 100 23.4 146
100 1 10-APR 200 0 92

我该怎么做?

与其将它们合并到一个已经存在的列中,不如添加一个新的虚拟列 比如

ALTER TABLE daily_data
ADD (
      transfer_total AS ( transfer_retail+transfer_cost )
    );

它不会在数据段内占用任何额外的 space,只是用于始终根据这两列显示所需的计算值。顺便说一句,您当前列的值 transfer_cost 将保留为原始值,并且 table 的规范化规则将受到保护。

我建议创建一个VIEW比修改原始数据更好。这避免了更新查询 运行 两次等所有风险,并且原始数据始终可用。

CREATE TABLE DAILY_DATA(DEPT INT,CLASS int, "DATE" DATE,BOOK_ID INT, TRANSFER_RETAIL DECIMAL(5,2),TRANSFER_COST DECIMAL(5,2));
INSERT INTO DAILY_DATA 
SELECT 100, 1,to_date('2022-04-10','yyyy-mm-dd'),100,23.4,54 FROM dual UNION ALL
SELECT 100, 1,to_date('2022-04-10','yyyy-mm-dd'), 200, 0, 92 FROM dual
CREATE VIEW TOTALLED AS
SELECT
  DEPT,
  CLASS,
  "DATE",
  BOOK_ID,
    CASE WHEN BOOK_ID = 100 THEN SUM(TRANSFER_RETAIL) OVER(partition BY "DATE")
      ELSE TRANSFER_RETAIL end TRANSFER_RETAIL,
    CASE WHEN BOOK_ID = 100 THEN SUM(TRANSFER_COST) OVER(partition BY "DATE") 
      ELSE TRANSFER_COST end TRANSFER_COST
from DAILY_DATA;
SELECT * FROM TOTALLED;
DEPT | CLASS | DATE      | BOOK_ID | TRANSFER_RETAIL | TRANSFER_COST
---: | ----: | :-------- | ------: | --------------: | ------------:
 100 |     1 | 10-APR-22 |     200 |               0 |            92
 100 |     1 | 10-APR-22 |     100 |            23.4 |           146

db<>fiddle here

您可以使用 MERGE 语句来合并行:

MERGE INTO daily_data dst
USING (
  SELECT dept,
         class,
         "DATE",
         SUM(transfer_retail) AS transfer_retail,
         SUM(transfer_cost) AS transfer_cost
  FROM   daily_data
  WHERE  book_id = 200
  -- AND dept = 100
  -- AND class = 1
  -- AND "DATE" = DATE '2022-04-10'
  GROUP BY dept, class, "DATE"
) src
ON (    dst.book_id = 100
    AND dst.dept    = src.dept
    AND dst.class   = src.class
    AND dst."DATE"  = src."DATE")
WHEN MATCHED THEN
  UPDATE
  SET transfer_retail = dst.transfer_retail + src.transfer_retail,
      transfer_cost   = dst.transfer_cost + src.transfer_cost;

其中,对于示例数据:

CREATE TABLE DAILY_DATA (DEPT, CLASS, "DATE", BOOK_ID, TRANSFER_RETAIL, TRANSFER_COST) AS
SELECT 100, 1, DATE '2022-04-10', 100, 23.4, 54 FROM DUAL UNION ALL
SELECT 100, 1, DATE '2022-04-10', 200, 0,    92 FROM DUAL;

然后在 MERGE 之后,table 将包含:

DEPT CLASS DATE BOOK_ID TRANSFER_RETAIL TRANSFER_COST
100 1 10-APR-22 100 23.4 146
100 1 10-APR-22 200 0 92

db<>fiddle here