【问题标题】:Store subquery results to be reused throughout query存储要在整个查询中重用的子查询结果
【发布时间】:2018-02-15 01:48:05
【问题描述】:

我正在尝试重新使用子查询的结果,这样我就不必在我的代码中一直调用它,我尝试过:

WITH MAX_VERSIONS AS (
    SELECT MAX(vernum) AS VERNUM, MAX(defvern) AS DEFVERN
    FROM   llattrdata, DTREE DT 
    WHERE  id = dt.dataid 
            AND defid = 3070056 
            AND attrid = 4
) 
SELECT ID
FROM   llattrdata ad, DTREE DT 
WHERE  ad.id = dt.dataid 
        AND ad.defid = 3070056 
        AND ad.attrid = 4
        AND ad.VERNUM = MAXVERSIONS.VERNUM
        AND ad.DEFVERN = MAXVERSIONS.DEFVERN;

【问题讨论】:

    标签: sql database oracle plsql


    【解决方案1】:

    您可以使用CROSS JOIN,因为它只返回单行:

    ;WITH MAX_VERSIONS AS 
    (
        SELECT MAX(vernum) AS VERNUM, MIN(defvern) AS DEFVERN
        FROM    llattrdata
                INNER JOIN DTREE DT
                    ON id = dt.dataid 
        WHERE   defid = 3070056 
                AND attrid = 4
    ) 
    SELECT  ID
    FROM    llattrdata ad
            INNER JOIN DTREE DT 
                ON ad.id = dt.dataid 
            CROSS JOIN MAX_VERSIONS mv
    WHERE   defid = 3070056 
            AND attrid = 4
            AND DT.VERNUM = mv.VERNUM    -- must also define which table the column
            AND DT.DEFVERN = mv.DEFVERN; -- is coming from to avoid ambiguity
                                         -- not sure whether it is from [ad] or [DT]
    

    作为替代方案,如果您想在不使用 CTE 的情况下一遍又一遍地重用该值,您可以声明该值并将其存储在变量中:

    DECLARE
        MAX_VERNUM NUMBER(10);
        MAX_DEFVERN  NUMBER(10);
    
    SELECT  MAX(vernum), MIN(defvern)
            INTO MAX_VERNUM, MAX_DEFVERN
    FROM    llattrdata
            INNER JOIN DTREE DT
                ON id = dt.dataid 
    WHERE   defid = 3070056 
            AND attrid = 4
    
    SELECT  ID
    FROM    llattrdata ad
            INNER JOIN DTREE DT 
                ON ad.id = dt.dataid 
    WHERE   defid = 3070056 
            AND attrid = 4
            AND VERNUM = MAX_VERNUM
            AND DEFVERN = MAX_DEFVERN;
    

    【讨论】:

    • 我知道mv 已断开连接
    • 这就是我的想法,但 Oracle 说“mv 与连接图的其余部分断开连接”。然后当我运行它时,我得到"column ambiguously defined"
    • @Batman 您还应该指定 VERNUM 和 DEFVERN 的来源。就像...DT.VERNUM = mv.VERNUM AND DT.DEFVERN = mv.DEFVERN; 我不太确定是哪个表,但这只是一个例子。
    • 做到了。我想知道使用WITH 的替代方法是什么。我只想存储这两个值Max(vernum/defvern),这样我就可以在同一脚本的多个查询部分中重用它们?
    • 我使用变量而不是 CTE 更新了用户。
    【解决方案2】:

    既然可以使用窗口函数,为什么还要经历这些麻烦:

    SELECT ID
    FROM (SELECT ID,
                 RANK() OVER (PARTITION BY defid, attrid, ORDER BY versum, defvern DESC) as seqnum
          FROM llattrdata ad JOIN
               DTREE DT 
               ON ad.id = dt.dataid 
          WHERE ad.defid = 3070056 
         ) ad
    WHERE seqnum = 1;
    

    窗口函数应该比JOINGROUP BY 有更好的性能。

    【讨论】:

    • 对不起,不完全确定这是如何存储 MAX(vernum), MAX(defvern) 以供重复使用
    • @蝙蝠侠。 . .它没有。它以一种更高效、更简洁的方法完成了您可能想要的查询。
    • 好的,但是如果我必须为 1 份报告执行 6 次,它仍然有效吗?
    • @蝙蝠侠。 . .这应该比joingroup by 更有效。我不知道你为什么要为一个报告多次这样做。
    • 我正在查看的报告多次执行此操作,因为他们希望使用返回的两个最大值作为其他查询的参数。所以他们所做的是每次他们需要这些参数时,他们都会打电话。这就是为什么我正在寻找一种方法来获取这些值一次,然后重复使用它们。
    猜你喜欢
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-23
    • 2021-11-09
    • 2014-12-23
    • 2017-11-22
    相关资源
    最近更新 更多