简体   繁体   English

在Oracle SQL Developer中简化SQL Select语句

[英]Simplifying a SQL Select Statement in Oracle SQL Developer

The problem I'm facing right now is I'm working with a SQL query that has over 200 lines of code and at the moment in multiple cases I'm just repeating the same sub-query multiple times in this select statement. 我现在面临的问题是我正在使用一个具有200行代码的SQL查询,此刻在多种情况下,我只是在此select语句中多次重复同一子查询。 In the code below I'm using two of the select statements a lot "avail_qty" and "pct_avail" which both having equations in them. 在下面的代码中,我使用了很多select语句中的两个“ avail_qty”和“ pct_avail”,它们中都包含方程式。 Inside the LOW_CNT_&% SELECT statement I use both of the previous two SELECT statements over and over (this is just one example in my code). 在LOW_CNT _&%SELECT语句中,我一遍又一遍地使用前两个SELECT语句(这只是我的代码中的一个示例)。 I would like to be able to make the equation once and assign it to a variable. 我希望能够一次创建方程式并将其分配给变量。 Is there any way of doing this? 有什么办法吗? I have tried using the WITH clause but for that you need to use a FROM clause, my FROM clause is massive and would look just as ugly if I were to use a WITH clause (plus instead of repeating the SELECT statement now I would be just repeating the FROM statement). 我已经尝试过使用WITH子句,但是为此您需要使用FROM子句,我的FROM子句非常庞大,如果我要使用WITH子句的话,它看起来也很丑陋(加上现在不再重复SELECT语句,我只是重复FROM语句)。

The reason I don't want to type out the whole equation multiple times is for a two reasons the first is it makes the code easier to read. 我不想多次键入整个方程式的原因有两个,第一个是它使代码更易于阅读。 My other reason is because multiple people edit this query and if someone else were to edit the equation in one spot but forgets to edit it in another spot, that could be bad. 我的另一个原因是因为有多个人编辑此查询,并且如果其他人要在一个位置编辑方程式却忘记在另一个位置进行编辑,那可能是不好的。 Also it doesn't feel like good code etiquette to repeat code over and over. 同样,一遍又一遍地重复代码也不是很好的代码礼节。

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

Any help would be awesome!! 任何帮助都是极好的!!

If the subquery is exactly the same one, you can pre-compute it as a Common Table Expression (CTE). 如果子查询完全相同,则可以将其预先计算为通用表表达式(CTE)。 For example: 例如:

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 (you can use any name) is a precomputed table expression that can be used multiple times. cte1 (您可以使用任何名称)是可以多次使用的预先计算的表表达式。 You can also have multiple CTEs, each one with different names; 您也可以有多个CTE,每个CTE的名称不同。 also each CTE can reference previous ones. 每个CTE都可以引用以前的CTE。

I have tried using the WITH clause but for that you need to use a FROM clause, my FROM clause is massive and would look just as ugly if I were to use a WITH clause (plus instead of repeating the SELECT statement now I would be just repeating the FROM statement). 我已经尝试过使用WITH子句,但是为此您需要使用FROM子句,我的FROM子句非常庞大,如果我要使用WITH子句的话,它看起来也很丑陋(加上现在不再重复SELECT语句,我只是重复FROM语句)。

You shouldn't need to repeat the from clause. 您不需要重复from子句。 You move all of the query, including that clause, into the CTE; 您将所有查询(包括该子句)移至CTE; you just pull out the bits that rely on earlier calculations into the main query, which avoids the code repetition. 您只需将依赖较早计算的位提取到主查询中即可,从而避免了代码重复。

The structure would be something like: 结构如下:

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;

Your main query only need to refer to the CTE (again, based on what you've shown), and can (only) refer to the prjoection of the CTE, incuding the calculated columns. 您的主要查询只需要引用CTE(再次基于您所显示的内容),就可以(仅)引用CTE的功能,包括计算列。 It can't see the underlying tables, but shouldn't need to. 它看不到基础表,但不需要。

Or with an inline view instead, the principal is the same: 或者使用内联视图,主体是相同的:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM