sql >> Base de Datos >  >> RDS >> Oracle

Creación de JSON y edición de una consulta compleja (Oracle 11g)

Creo que puede reemplazar la mayor parte de su código con la siguiente consulta. Es posible que deba ajustar la cláusula IN, lo cual es una molestia si está cambiando mucho la lista de clientes. Pero esto replica tus resultados:

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));

Aquí hay una actualización fiddle .

En cuanto a la salida JSON, sería mucho más fácil si estuviera en una versión posterior, ya que ahora es parte de la funcionalidad principal.

EDITAR:Adición de funcionalidad XML por comentarios

Puede consultar esta consulta:

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;

Aquí hay un violín actualizado con esa consulta (Link ).

Lo que produce el siguiente resultado:

<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>

Edición 2:agregar JSON a través de la concatenación de cadenas

Lo siguiente generaría JSON a través de la concatenación directa de cadenas:

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;

Y un violín actualizado con esta consulta (Link )

Edición 3:Reemplazo agregado **Edición 4:función analítica agregada **