Подсчет суммы Oracle LISTAGG по дате и месту - PullRequest
0 голосов
/ 21 октября 2019

Я использую Oracle 12.1 в Windows. Мне нужна помощь в создании списка, агрегированного по дате (весь день - это условие дня, усечение (дата)) и местоположению, а также подсчет количества типов инвентаря за этот день в результате списка. Я планирую сделать это представление таблицы 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;

Я не смог найти примеры, где я могу получить сумму (num_cars) в пределахthe listagg.
Также (и я не хочу задавать вопрос по этому вопросу), но что произойдет, если совокупность списка превысит 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: недопустимое имя таблицы 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.

1 Ответ

1 голос
/ 21 октября 2019

Сначала вам нужно будет вычислить эту сумму, а затем использовать ее в 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>

Теперь это зависит от того, что именно вы хотите получить в результате (не совсем поняло описание; пример вывода помог бы), но я надеюсь, что вы получитеidea.

По второму вопросу: да, это XMLAGG, который вам придется использовать, если результат превышает ограничение в 4000 символов.


[EDIT]

Ага;кажется, что это 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>
...