如何在没有昂贵查询的情况下更快地自连接表(Oracle SQL)

Posted

技术标签:

【中文标题】如何在没有昂贵查询的情况下更快地自连接表(Oracle SQL)【英文标题】:How to self join a table faster without expensive query (Oracle SQL) 【发布时间】:2020-04-16 16:56:22 【问题描述】:

场景

在 VER_ID(主键)的表中,数据存储在具有不同 ATTR_SPEC_ID 的多行中。 我想要一些数据,但我想要它以列格式(见屏幕截图),以便我可以将它与其他 CTE 连接。

而且我不希望查询成本很高,因为在生产中它需要时间。 那么处理这种情况的最佳方法是什么?

表格内容

期望的输出

我关心的部分问题

完整查询

SELECT COUNT(CUST_ORD_NO),ORDER_DELIVERY_DATE,SCENARIO
FROM
(WITH 
CFS_ORD AS --- To Filter and get details of Running Retail Order
(  
SELECT CF.ORD_NO,CF.CUST_ORD_NO,CF.RFS_DATE AS ORDER_DELIVERY_DATE
    FROM OM_CFS_ORD CF
    JOIN OPBS_DICT_VALUE OD ON CF.STAGE=OD.VALUE
        WHERE CF.CFS_SPEC_ID ='C16080300451141'  -- SPEC_ID OF EU_ACCESS 
        AND CF.ORD_STATE NOT IN('F','C')    -- To exclude order that has reached end state
        AND OFFER_NAME='Retail Access'
        AND OD.DICT_ID = 'OM_ORD_STAGE'
        AND STATE='A'
        AND CF.RFS_DATE < TRUNC(SYSDATE)
        AND CF.RFS_DATE > TRUNC(SYSDATE-60)
),
CFS_MAIN AS -- To Get VER_ID of EU_ACCESS of the Order
(
SELECT VER_ID,CUST_ORD_NO,SERVICE_NO,CREATE_ORD
    FROM SRV_CFSVER_CT_MAIN
    WHERE VER_STATE='O'
    AND CFS_SPEC_ID ='C16080300451141' -- TO filter EU Access of Retail orders   
),
CFS_ATTR AS (  -- To get necessary attributes
SELECT DISTINCT CFS_ATTRO.VER_ID,
        (SELECT ATTR_VAL FROM SRV_CFS_VER_ATTR WHERE VER_ID=CFS_ATTRO.VER_ID AND ATTR_ID='C16080300451141.APPOINTMENT_ACT_TYPE' ) AS APPOINTMENT_ACTIVITY_TYPE,
        (SELECT ATTR_VAL FROM SRV_CFS_VER_ATTR WHERE VER_ID=CFS_ATTRO.VER_ID AND ATTR_ID='C16080300451141.NL_TYPE' ) AS NL_TYPE,
        (SELECT ATTR_VAL FROM SRV_CFS_VER_ATTR WHERE VER_ID=CFS_ATTRO.VER_ID AND ATTR_ID='C16080300451141.PATCHLESS' ) AS PATCH_LESS,
        (SELECT ATTR_VAL FROM SRV_CFS_VER_ATTR WHERE VER_ID=CFS_ATTRO.VER_ID AND ATTR_ID='C16080300451141.CARRIER_TECH_TYPE' ) AS TECHNOLOGY_TYPE,
        (SELECT ATTR_VAL FROM SRV_CFS_VER_ATTR WHERE VER_ID=CFS_ATTRO.VER_ID AND ATTR_ID='C16080300451141.CARRIER_TYPE' ) AS CARRIER_TYPE
FROM SRV_CFS_VER_ATTR CFS_ATTRO  
     WHERE CFS_ATTRO.ATTR_ID IN ('C16080300451141.PATCHLESS','C16080300451141.NL_TYPE','C16080300451141.APPOINTMENT_ACT_TYPE','C16080300451141.CARRIER_TECH_TYPE')
),
APPOINTMENT AS 
(
SELECT ORD_NO,APPOINTMENT_NO 
    FROM OM_ORD_TIMESLOT
    WHERE STATE='A'
)   
SELECT CFS_ORD.CUST_ORD_NO,CFS_ORD.ORDER_DELIVERY_DATE,
        CASE
            WHEN    CFS_ATTR.APPOINTMENT_ACTIVITY_TYPE IS NULL  AND CFS_ATTR.CARRIER_TYPE <> 'Fiber' THEN 'nDIY'
            WHEN    CFS_ATTR.PATCH_LESS = 'Y' THEN 'PATCHLESS'
            WHEN    CFS_ATTR.APPOINTMENT_ACTIVITY_TYPE IS NOT NULL THEN 'DIY'
            WHEN    APPOINTMENT.APPOINTMENT_NO IS NOT NULL  AND CFS_ATTR.CARRIER_TYPE = 'Fiber' THEN 'DIY'
            WHEN    APPOINTMENT.APPOINTMENT_NO IS NULL  AND CFS_ATTR.CARRIER_TYPE = 'Fiber' THEN 'nDIY'
        END AS SCENARIO
    FROM CFS_ORD
        JOIN CFS_MAIN ON CFS_ORD.ORD_NO=CFS_MAIN.CREATE_ORD
        JOIN CFS_ATTR ON CFS_MAIN.VER_ID=CFS_ATTR.VER_ID
        LEFT JOIN APPOINTMENT ON APPOINTMENT.ORD_NO=CFS_ORD.ORD_NO
        --WHERE CFS_ORD.CUST_ORD_NO LIKE '%@KPN_CM'
        ) 
GROUP BY ORDER_DELIVERY_DATE,SCENARIO
ORDER BY ORDER_DELIVERY_DATE

【问题讨论】:

【参考方案1】:

听起来您需要使用 PIVOT https://www.techonthenet.com/oracle/pivot.php

如果您可以使用您提供的测试数据(基于所需的输出)填充 http://sqlfiddle.com/ 示例,如果您遇到困难,我可以帮助您编写查询。

【讨论】:

以上是关于如何在没有昂贵查询的情况下更快地自连接表(Oracle SQL)的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有任何重复行的情况下连接 cognos 中的两个表?

如何在没有任何重复行的情况下连接两个表中的表?

如何在没有重复数据的情况下对两个具有连接的表进行求和?

我如何在没有重复数据的情况下对两个具有连接的表求和?

如何优化多表连接视图以获得更快的响应?

连接多个大表时如何进行更快的查询?