在Oracle SQL Developer中简化SQL Select语句

时间:2018-10-26 16:01:07

标签: sql oracle

我现在面临的问题是我正在使用一个具有200行代码的SQL查询,此刻在多种情况下,我只是在此select语句中多次重复同一子查询。在下面的代码中,我使用了很多select语句中的两个“ avail_qty”和“ pct_avail”,它们中都包含方程式。在LOW_CNT _&%SELECT语句中,我一遍又一遍地使用前两个SELECT语句(这只是我的代码中的一个示例)。我希望能够一次创建方程式并将其分配给变量。有什么办法吗?我已经尝试过使用WITH子句,但是为此您需要使用FROM子句,我的FROM子句非常庞大,如果我要使用WITH子句的话,它看起来也很丑陋(加上现在不再重复SELECT语句,我只是重复FROM语句)。

我不想多次键入整个方程式的原因有两个,第一个原因是它使代码更易于阅读。我的另一个原因是因为有多个人编辑此查询,并且如果其他人要在一个位置编辑方程式却忘记在另一个位置进行编辑,那可能是不好的。同样,一遍又一遍地重复代码也不是很好的代码礼节。

SELECT 
    all_nbr.total_qty,
    NVL (avail_nbr.avail_qty, 0) AS avail_qty,
    100 * TRUNC ( (NVL (avail_nbr.avail_qty, 0) / all_nbr.total_qty), 2) AS pct_avail,

    CASE
        WHEN ((NVL (avail_nbr.avail_qty, 0)) < 35) 
        THEN CASE
                WHEN ((100 * TRUNC ( (NVL (avail_nbr.avail_qty, 0) / all_nbr.total_qty), 2)) < 35)
                THEN (35 - (NVL (avail_nbr.avail_qty, 0)))
                ELSE 0
             END
        ELSE 0
    END AS "LOW_CNT_&%"
FROM
...

任何帮助都会很棒!

2 个答案:

答案 0 :(得分:1)

如果子查询完全相同,则可以将其预先计算为通用表表达式(CTE)。例如:

with
cte1 as (
  select ... -- long, tedious, repetitive SELECT here
),
cte2 as (
  select ... -- you can reference/use cte1 here
)
select ...
  from cte1 -- you can use cte1 here, multiple times if you want
  join cte2 -- you can also reference/use cte2 here, also multiple times
  join ... -- all other joins

cte1(您可以使用任何名称)是可以多次使用的预先计算的表表达式。您也可以有多个CTE,每个CTE的名称不同。每个CTE都可以引用以前的内容。

答案 1 :(得分:0)

  

我尝试使用WITH子句,但是为此您需要使用FROM子句,我的FROM子句非常庞大,如果我要使用WITH子句(加上现在不再重复SELECT语句,我看起来也很丑)将只是重复FROM语句)。

您不需要重复from子句。您将所有查询(包括该子句)移至CTE;您只需将依赖较早计算的位插入主查询中即可,从而避免了代码重复。

结构类似于:

WITH cte AS (
    SELECT 
        all_nbr.total_qty,
        NVL (avail_nbr.avail_qty, 0) AS avail_qty,
        100 * TRUNC ( (NVL (avail_nbr.avail_qty, 0) / all_nbr.total_qty), 2) AS pct_avail,
    FROM
    ...
)
SELECT
    cte.total_qty,
    cte.avail_qty,
    cte.pct_avail,
    CASE
        WHEN cte.avail_qty, 0 < 35 
        THEN CASE
                WHEN cte.total_qty < 35
                THEN 35 - cte.avail_qty
                ELSE 0
             END
        ELSE 0
    END AS "LOW_CNT_&%"
FROM
    cte;

您的主查询只需要引用CTE(再次基于您所显示的内容),就可以(仅)引用CTE的功能,包括计算列。它看不到基础表,但不需要。

或者使用内联视图,其原理是相同的:

SELECT
    total_qty,
    avail_qty,
    pct_avail,
    CASE
        WHEN avail_qty < 35
        THEN CASE
                WHEN total_qty < 35
                THEN 35 - avail_qty
                ELSE 0
             END
        ELSE 0
    END AS "LOW_CNT_&%"
FROM
(
    SELECT 
        all_nbr.total_qty,
        NVL (avail_nbr.avail_qty, 0) AS avail_qty,
        100 * TRUNC ( (NVL (avail_nbr.avail_qty, 0) / all_nbr.total_qty), 2) AS pct_avail,
    FROM
    ...
);