【问题标题】:Oracle LISTAGG sum count by date and locationOracle LISTAGG 总和按日期和位置计数
【发布时间】:2019-10-21 18:31:48
【问题描述】:

我在 Windows 上运行 Oracle 12.1。 我需要帮助按日期(整天是日期条件,trunc(date))和位置创建列表聚合,并在列表结果中计算当天的库存类型数量。我计划将此作为 car_equipment 表的视图以显示列表聚合。
在显示最大(日期)的库存列表之前,我做了一个简单的视图。

CREATE OR REPLACE FORCE NONEDITIONABLE VIEW "DB1"."CAR_INVENTORY_VW" ("MAX_INVENTORY_DATE","LOCATION", "INVENTORY_LIST") AS 
 SELECT 
  inventory_date max_inventory_date,
  location,
  LISTAGG(num_cars || ' ' || equipment_type, ', ') 
    WITHIN GROUP (ORDER BY equipment_type) inventory_list
      FROM (
        SELECT c.*, RANK() OVER(PARTITION BY location ORDER BY inventory_date DESC) rn
            FROM car_equipment c
           ) x 
           WHERE rn = 1
            GROUP BY inventory_date, location;

但现在我想显示一个位置的所有日期,并按每个位置的日期收集库存类型的计数总和。 下面是创建表和行的代码: 首先创建表并插入数据条件示例的行。

CREATE TABLE "CAR_EQUIPMENT" 
   ("NUM_CARS" NUMBER(10,0), 
"EQUIPMENT_TYPE" VARCHAR2(100 BYTE), 
"LOCATION" VARCHAR2(500 BYTE), 
"INVENTORY_DATE" DATE) 
SEGMENT CREATION IMMEDIATE 
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 
NOCOMPRESS LOGGING
   STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
   PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
   BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
   TABLESPACE "USERS" ;

INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('8', 'Rovers', 'coventry', TO_DATE('2019-09-07 09:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('1', 'Rovers', 'coventry', TO_DATE('2019-09-07 18:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('9', 'Jaguars', 'coventry', TO_DATE('2019-09-07 06:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('7', 'Rovers', 'leamington', TO_DATE('2019-08-30 00:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('10','Trans Am', 'leamington', TO_DATE('2019-08-30 09:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('2','Trans Am', 'leamington', TO_DATE('2019-08-30 18:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('8', 'Rovers', 'coventry', TO_DATE('2019-09-06 18:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO "CAR_EQUIPMENT" (NUM_CARS, EQUIPMENT_TYPE, LOCATION, INVENTORY_DATE) VALUES ('4', 'Rovers', 'leamington', TO_DATE('2019-09-06 09:00:00', 'YYYY-MM-DD HH24:MI:SS'));

commit;

我找不到可以在 listagg 中获得 sum(num_cars) 的示例。
另外,(我不想在这里提出后续问题),但是如果列表聚合超过 4000 字节会发生什么。我读到可以使用 xmlagg,但是如果结果超过 4000 字节,那么显示列表的最佳方式是什么。你以前遇到过这个问题吗,你是如何解决这个问题的。再次感谢您的任何建议。 最诚挚的问候,吉莉

我试过了:

create or replace view TEST_LAGG(
  WITH
  TEMP AS (SELECT LOCATION,
                  trunc(INVENTORY_DATE) inventory_date,
                  EQUIPMENT_TYPE,
                  sum(NUM_CARS) sum_num_cars
           from CAR_EQUIPMENT
           group by LOCATION,
                    trunc(INVENTORY_DATE),
                    EQUIPMENT_TYPE
         )
   select LOCATION,
          INVENTORY_DATE,
          listagg(sum_num_cars ||' '|| EQUIPMENT_TYPE, ', ') within group (order by inventory_date) lagg
   from TEMP
   group by LOCATION,
        inventory_date);

但是我得到 ORA-00903: invalid table name 00903. 00000 - “无效的表名”

再次感谢Littlefoot,我试过了:

create or replace view TEST_LAGG
 AS WITH
  TEMP (SELECT LOCATION,
                  trunc(INVENTORY_DATE) inventory_date,
                  EQUIPMENT_TYPE,
                  sum(NUM_CARS) sum_num_cars
           from CAR_EQUIPMENT
           group by LOCATION,
                   trunc(INVENTORY_DATE),
                    EQUIPMENT_TYPE
         )
    select LOCATION,
      INVENTORY_DATE,
      listagg(sum_num_cars ||' '|| EQUIPMENT_TYPE, ', ') within group   (order by inventory_date) lagg
 from TEMP
 group by LOCATION,
        inventory_date;

但我得到错误:ORA-00903:无效的表名 00903. 00000 - “无效的表名” *原因:
*行动: 行错误:135 列:3 -- TEMP 表参考行。

【问题讨论】:

  • 不错的细节。您能否也显示预期的输出?
  • 日期位置 CAR_LIST 2019-09-07 Coventry 9 Rovers | 9 美洲虎
  • 列标题为 DATE LOCATION CAR_LIST

标签: oracle date sum listagg


【解决方案1】:

您首先必须计算该总和,然后在 listagg 中使用它。像这样的:

SQL>     with
  2        temp as (select location, inventory_date, equipment_type, sum(num_cars) sum_num_cars
  3                 from car_equipment
  4                 group by location, inventory_date, equipment_type
  5                )
  6      select location,
  7             inventory_date,
  8             listagg(sum_num_cars ||' '|| equipment_type, ', ') within group (order by inventory_date) lagg
  9      from temp
 10      group by location,
 11               inventory_date;

LOCATION        INVENTORY_DATE      LAGG
--------------- ------------------- ------------------------------
coventry        2019-09-06 18:00:00 8 Rovers
coventry        2019-09-07 06:00:00 9 Jaguars
coventry        2019-09-07 09:00:00 8 Rovers
coventry        2019-09-07 18:00:00 1 Rovers
leamington      2019-08-30 00:00:00 7 Rovers
leamington      2019-08-30 09:00:00 10 Trans Am
leamington      2019-08-30 18:00:00 2 Trans Am
leamington      2019-09-06 09:00:00 4 Rovers

8 rows selected.

SQL>

现在,这取决于您究竟想要得到什么结果(不太理解描述;示例输出会有所帮助),但我希望您能明白。

关于您的第二个问题:是的,如果结果超过 4000 个字符的限制,您必须使用 XMLAGG。


[编辑]

啊哈;看来你需要的是TRUNC(inventory_date)。它将从日期列中删除时间部分。

SQL> with
  2    temp as (select location,
  3                    trunc(inventory_date) inventory_date,
  4                    equipment_type,
  5                    sum(num_cars) sum_num_cars
  6             from car_equipment
  7             group by location,
  8                      trunc(inventory_date),
  9                      equipment_type
 10            )
 11  select location,
 12         inventory_date,
 13         listagg(sum_num_cars ||' '|| equipment_type, ', ') within group (order by inventory_date) lagg
 14  from temp
 15  group by location,
 16           inventory_date;

LOCATION        INVENTORY_DATE      LAGG
--------------- ------------------- ------------------------------
coventry        2019-09-06 00:00:00 8 Rovers
coventry        2019-09-07 00:00:00 9 Jaguars, 9 Rovers
leamington      2019-08-30 00:00:00 12 Trans Am, 7 Rovers
leamington      2019-09-06 00:00:00 4 Rovers

SQL>

[编辑:创建视图]

SQL> create or replace view TEST_LAGG as
  2    WITH
  3    TEMP AS (SELECT LOCATION,
  4                    trunc(INVENTORY_DATE) inventory_date,
  5                    EQUIPMENT_TYPE,
  6                    sum(NUM_CARS) sum_num_cars
  7             from CAR_EQUIPMENT
  8             group by LOCATION,
  9                      trunc(INVENTORY_DATE),
 10                      EQUIPMENT_TYPE
 11           )
 12     select LOCATION,
 13            INVENTORY_DATE,
 14            listagg(sum_num_cars ||' '|| EQUIPMENT_TYPE, ', ') within group (order by inventory_date) lagg
 15     from TEMP
 16     group by LOCATION,
 17          inventory_date;

View created.

SQL> select * from test_lagg;

LOCATION        INVENTORY_DATE      LAGG
--------------- ------------------- ------------------------------
coventry        2019-09-06 00:00:00 8 Rovers
coventry        2019-09-07 00:00:00 9 Jaguars, 9 Rovers
leamington      2019-08-30 00:00:00 12 Trans Am, 7 Rovers
leamington      2019-09-06 00:00:00 4 Rovers

SQL>

【讨论】:

  • 不客气。什么是“标准配置”? XMLAGG 在 SQL 中工作,如果这是问题的话(即你不需要 PL/SQL)。
  • 12.1 之前的 XML 支持可以选择不安装。从 12.1 开始,XML 支持将始终可用 - 如果这就是您的意思...
  • 如果我理解正确,trunc(inventory_date) 可能会有所帮助,因为它会从日期列中删除时间部分。我编辑了我的信息;请看一下。
  • 我没有(显然......)。我注意到您在命名表和列时使用了双引号 - 不要在 Oracle 中这样做。键入您想要的任何类型的字母(大写、小写、混合大小写),Oracle 将在其内部表中将它们默认为大写,您可以随意引用它们。但是,如果您使用双引号和小写/混合大小写,则必须始终使用双引号。你试过的时候是这样吗?
  • 字母大小写可以(因为您在双引号中使用了大写字母)。问题是:去掉括号,添加AS关键字,即create or replace view test_lagg as with temp ...
猜你喜欢
  • 2021-11-18
  • 2021-10-05
  • 2023-03-11
  • 1970-01-01
  • 2023-03-27
  • 2020-12-31
  • 1970-01-01
  • 2016-12-09
  • 2022-12-19
相关资源
最近更新 更多