Запрос Postgresql, который подсчитывает промежуточные итоги на основе анализа разделенного списка

PostgreSQL 14

Предполагая, что этот образец данных...

Элемент Кол-во Фрукты:Апельсин 1 Фрукты:Апельсин 2 Фрукты:Апельсин 3 Фрукты:Яблоко 4 Фрукты:Яблоко 5 Минерал:Нефрит 1 Минерал:Нефрит 2 Минерал: Тальк: Сырой 3 Минерал: Тальк: Сырой 4 Минерал: Тальк: Обработанный 5 Минерал: Тальк: Обработанный 6

... как лучше всего получить что-то вроде ROLLUP, рекурсивного запроса или UNION для подсчета промежуточных итогов для каждого уровня значения элемента, разбиваясь на двоеточия? Количество уровней (разделителей-двоеточий) для каждого элемента является переменным, но при необходимости я могу определить максимальное значение.

Желаемый результат (я знаю, что ROLLUP поместит больше нулей в разных местах, и это нормально):

Элемент Кол-во Фрукты:Апельсин 6 Фрукты:Яблоко 9 Фрукты 15 Минерал:Нефрит 3 Минерал: Тальк: Сырой 7 Минерал: Тальк: Обработанный 11 Минерал: Тальк 18 Минерал 21 НУЛЕВОЙ 36

sql предназначен не для этого.

Jens 15.08.2024 20:38

@Jens: Достаточно справедливо, и я могу сделать это в принимающем коде, но встроенные функции приближают меня настолько, что, похоже, стоит спросить. Я не уверен, почему вопрос, выполнимо ли это, приводит к тому, что меня минусуют...

EMF 15.08.2024 21:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я использовал рекурсивную стратегию, которая работает в этом случае, потому что я решил сгенерировать parent items, удалив последний сегмент.

Результат: рабочий пример

Вот код для создания вашей таблицы

CREATE TABLE items (
    item TEXT,
    qty INT
);

вставить в таблицу

INSERT INTO items (item, qty) VALUES
('Fruit:Orange', 1),
('Fruit:Orange', 2),
('Fruit:Orange', 3),
('Fruit:Apple', 4),
('Fruit:Apple', 5),
('Mineral:Jade', 1),
('Mineral:Jade', 2),
('Mineral:Talc:Raw', 3),
('Mineral:Talc:Raw', 4),
('Mineral:Talc:Processed', 5),
('Mineral:Talc:Processed', 6);

Рекурсивная стратегия

WITH RECURSIVE item_hierarchy AS (
    SELECT 
        item,
        qty,
        item AS level_item,
        CASE 
            WHEN POSITION(':' IN item) > 0 THEN 
              ARRAY_TO_STRING(TRIM_ARRAY(STRING_TO_ARRAY(item, ':'), 1), ':')
            ELSE NULL 
        END AS parent_item
    FROM items
    
    UNION ALL
  
    SELECT
        ih.item,
        ih.qty,
        ih.parent_item AS level_item,
        CASE 
            WHEN POSITION(':' IN ih.parent_item) > 0 THEN 
              ARRAY_TO_STRING(TRIM_ARRAY(STRING_TO_ARRAY(parent_item, ':'), 1), ':')
            ELSE NULL 
        END AS parent_item
    FROM item_hierarchy ih
    WHERE ih.parent_item IS NOT NULL
)

SELECT 
    COALESCE(level_item, 'NULL') AS item,
    SUM(qty) AS qty
FROM item_hierarchy
GROUP BY level_item
ORDER BY 
    LENGTH(COALESCE(level_item, '')) ASC, 
    level_item;

@ValNik вот что я вижу.... ims.png

Я не вижу строки ('Mineral:Talc', 18)

ValNik 15.08.2024 21:18

Согласен с @ValNik, что здесь отсутствует подуровень, но я понимаю, к чему вы клоните с помощью этого подхода.

EMF 15.08.2024 21:34

@DerekRoberts: Похоже, вы слишком агрессивно относитесь к анализу родительского элемента и всегда захватываете первый элемент. Я смотрю, смогу ли я это отрегулировать.

EMF 15.08.2024 21:46

@EMF хаха! разве мне не нравится слово «агрессивный» в этом контексте. родитель был единственной идеей, которую я мог использовать. Я думаю, ты справишься, я в тебя верю!

Derek Roberts 15.08.2024 21:50

Думаю, я понял. Замените LEFT(item, POSITION(':' IN item) - 1) на ARRAY_TO_STRING(TRIM_ARRAY(STRING_TO_ARRAY(item, ':'), 1), ':'). То же самое со вторым экземпляром, использующим ih.parent_item. Это не дает мне общей суммы, но для UNION это тривиально.

EMF 15.08.2024 22:12

@DerekRoberts: Если вы обновите свой ответ, я приму его. Вы помогли мне на 99% пути!

EMF 15.08.2024 22:18

@EMF потрясающе звучит, 99% — A++. Я знал, что ты сможешь. сделал бы это сейчас СДЕЛАНО!

Derek Roberts 15.08.2024 22:20

Если попробовать новую версию примера запроса - произойдет сбой при неполной рекурсии? (dbfiddle.uk/p-P_F_ge)

ValNik 16.08.2024 00:02

@ValNik, правда, я только что запустил код, и кажется, все в порядке... общая сумма не такая, как упоминается в EMF, но она работает ИЛИ вы исчерпали свою машину на dbfiddle за день?

Derek Roberts 16.08.2024 00:10

Пожалуйста, посмотрите простой пример (dbfiddle.uk/K6Mgwlu_ ). Я ограничу глубину рекурсии. И еще пример ( dbfiddle.uk/RTCUj3yK).

ValNik 16.08.2024 00:19

@ValNik EMF предложила использовать ARRAY_TO_STRING, что ей помогло, вы хотите сказать, что это не работает? Я запустил вот этот код(dbfiddle.uk/p-P_F_ge) и он работает, что же делать?

Derek Roberts 16.08.2024 00:51

ARRAY_TO_STRING — хорошая функция. Я о You should use parent_item in recursive part of item_hierarchy: ARRAY_TO_STRING(TRIM_ARRAY(STRING_TO_ARRAY(parent_item, ':'), 1), ':')

ValNik 16.08.2024 00:53

@ValNik, ок, сейчас поменяю, дайте мне знать, если все в порядке

Derek Roberts 16.08.2024 00:55

Кстати, мои правки работают на меня и дают именно то, что я просил. Я попытался опубликовать весь отредактированный фрагмент, но в нем слишком много символов.

EMF 16.08.2024 01:42

Но да, похоже, что второй экземпляр в ответе ссылается на item вместо ih.parent_item.

EMF 16.08.2024 01:51

Другие вопросы по теме