Myślę, że możesz zastąpić większość swojego kodu następującym zapytaniem. Może być konieczne dostosowanie klauzuli IN, co jest uciążliwe, jeśli często zmieniasz listę klientów. Ale to powiela Twoje wyniki:
SELECT *
FROM (SELECT DECODE(ppc.customer_class_code, 'E', c.description, ppc.customer_class_code) AS IDENTIFIER, tpp.item_code, tpp.price AS ITEM_PRICE, ppc.price
FROM table_price_list tpl
INNER JOIN table_price_product tpp ON tpp.list_header_id = tpl.list_header_id AND tpp.request_id = tpl.request_id
INNER JOIN prices_per_client ppc ON tpp.item_code = ppc.item_code
LEFT JOIN clients c ON ppc.customer_number = c.account_number
WHERE SYSDATE BETWEEN NVL(tpp.start_date_active, SYSDATE) AND NVL(tpp.end_date_active, SYSDATE+1))
PIVOT (AVG(PRICE) FOR IDENTIFIER IN ('A' AS CLASS_A , 'B' AS CLASS_B, 'SUPERMARKET' AS SUPERMARKET, 'WALMART' AS WALMART));
Oto aktualizacja skrzypce .
Jeśli chodzi o wyjście JSON, byłoby znacznie łatwiej, gdybyś był w nowszej wersji, ponieważ jest teraz częścią podstawowej funkcjonalności.
EDYCJA:Dodawanie funkcji XML na komentarze
Możesz sprawdzić to zapytanie:
SELECT XMLSERIALIZE(CONTENT
XMLELEMENT("Item",
XMLATTRIBUTES(sub.item_code AS "SKU", sub.item_price AS "Price"),
XMLELEMENT("PRICES_FOR_CLIENTS",
XMLAGG(XMLELEMENT("CLIENT_PRICE",
XMLFOREST(sub.identifier AS "Client", sub.price AS "Price"))))) AS CLOB INDENT)
FROM (SELECT DECODE(ppc.customer_class_code, 'E', c.description, ppc.customer_class_code) AS IDENTIFIER, tpp.item_code, tpp.price AS ITEM_PRICE, avg(ppc.price) AS PRICE
FROM table_price_list tpl
INNER JOIN table_price_product tpp ON tpp.list_header_id = tpl.list_header_id AND tpp.request_id = tpl.request_id
INNER JOIN prices_per_client ppc ON tpp.item_code = ppc.item_code
LEFT JOIN clients c ON ppc.customer_number = c.account_number
WHERE SYSDATE BETWEEN NVL(tpp.start_date_active, SYSDATE) AND NVL(tpp.end_date_active, SYSDATE+1)
GROUP BY DECODE(ppc.customer_class_code, 'E', c.description, ppc.customer_class_code), tpp.item_code, tpp.price) sub
WHERE sub.identifier IS NOT NULL
GROUP BY sub.item_code, sub.item_price;
Oto zaktualizowane skrzypce z tym zapytaniem (Link ).
Co daje następujący wynik:
<Item SKU="99342435" Price="9999">
<PRICES_FOR_CLIENTS>
<CLIENT_PRICE>
<Client>WALMART</Client>
<Price>40340</Price>
</CLIENT_PRICE>
<CLIENT_PRICE>
<Client>SUPERMARKET</Client>
<Price>48343</Price>
</CLIENT_PRICE>
<CLIENT_PRICE>
<Client>B</Client>
<Price>33223</Price>
</CLIENT_PRICE>
<CLIENT_PRICE>
<Client>A</Client>
<Price>29223</Price>
</CLIENT_PRICE>
</PRICES_FOR_CLIENTS>
</Item>
Edycja 2:dodawanie JSON przez łączenie ciągów
Następujące dane wyprowadzą JSON przez bezpośrednie łączenie ciągów:
SELECT '{"sku":"'||sub.item_code||'","PRICE":"'||sub.item_price||'",PRICES_FOR_CLIENTS:['||listagg('{"group":"'||sub.identifier||'","PRICE":"'||sub.price||'"}',',') WITHIN GROUP (ORDER BY sub.identifier)||']};' AS JSON
FROM (SELECT DECODE(ppc.customer_class_code, 'E', c.description, ppc.customer_class_code) AS IDENTIFIER, tpp.item_code, replace(tpp.price, ',', '.') AS ITEM_PRICE, REPLACE(avg(ppc.price), ',', '.') AS PRICE,
tpl.request_id, max(tpl.request_id) over (partition by tpp.item_code) as max_request
FROM table_price_list tpl
INNER JOIN table_price_product tpp ON tpp.list_header_id = tpl.list_header_id AND tpp.request_id = tpl.request_id
INNER JOIN prices_per_client ppc ON tpp.item_code = ppc.item_code
LEFT JOIN clients c ON ppc.customer_number = c.account_number
WHERE SYSDATE BETWEEN NVL(tpp.start_date_active, SYSDATE) AND NVL(tpp.end_date_active, SYSDATE+1)
GROUP BY DECODE(ppc.customer_class_code, 'E', c.description, ppc.customer_class_code), tpp.item_code, tpp.price, tpl.request_id) sub
WHERE sub.identifier IS NOT NULL
and sub.request_id = sub.max_request
GROUP BY sub.item_code, sub.item_price;
I zaktualizowane skrzypce z tym zapytaniem (Link )
Edycja 3:Dodano Zamień **Edycja 4:Dodano funkcję analityczną **