使用从CASE语句返回的相同值填充整个列

时间:2018-12-28 14:26:54

标签: sql oracle case

我试图通过整个s_date / part_no分组中的结果CASE语句填充具有相同结果值的列。

我们尝试了多种不同的途径来使递归能够满足我们的需求,但是没有运气。计算非常棘手,并且我们知道SQL并不是递归的最佳选择,因此我们正试图找到一种替代途径,暂时满足客户需求和时间紧迫。

SELECT
        s_date,
        part_no,
        i_group,
        s_level,
        p_category,
        qty_filled,
        qty_total,
        relief_amt,
        extreme_amt,
        curr_mth_note,
        CASE
            WHEN curr_mth_note IS NOT NULL
                 AND i_group = '1'
                 AND s_level = '80' THEN qty_filled
            ELSE NULL
        END AS g1s1_filled
        FROM
        (
            SELECT
                t1.s_date,
                t1.part_no,
                t1.i_group,
                t1.s_level,
                t1.p_category,
                t1.qty_filled,
                t1.qty_total,
                mv.relief_amt,
                mv.extreme_amt,
                mv.curr_mth_note,
            FROM
                multi_table mv,
                t_table t1
            WHERE
                t1.part_no = mv.part_no
                AND mv.part_no = 'xxxx'
                AND t1.s_date = mv.s_date
                AND t1.s_date = '201805'
            GROUP BY
                t1.s_date,
                t1.i_group,
                t1.s_level,
                t1.part_no,
                t1.p_category,
                t1.qty_filled,
                t1.qty_total,
                mv.relief_amt,
                mv.extreme_amt,
                mv.curr_mth_note,
            ORDER BY
                t1.s_date,
                t1.i_group,
                t1.s_level DESC
        )
ORDER BY
    s_date,
    part_no,
    i_group,
    DECODE(s_level, '80', 1, '100', 2, 'Late', 3)

以上内容的当前输出如下:

enter image description here

我要/希望得到的是整个g1s1_filled列,以显示相同的67金额,其中i_group = '1' and s_level = '80'用于所有可用的日期/部分组合。

因此该列应显示以下内容:

G1S1_FILLED
67
67
67
67
67

我研究了如何尝试在没有运气的情况下使用where而不是when。  这样会有很多其他的列,我最终也可以在这些列上进行计算。

4 个答案:

答案 0 :(得分:2)

您可以在SELECT子句中使用条件分析最小值。我没有您的数据,因此我将在SCOTT.EMP表上进行类似的查询来说明-假设我想用一位特定员工的薪水填补NEWCOL。我会这样:

select empno, ename, sal, job, deptno,
       min(case when empno = 7499 and ename = 'ALLEN' then sal end) over () as newcol
from   scott.emp;

     EMPNO ENAME             SAL JOB           DEPTNO     NEWCOL
---------- ---------- ---------- --------- ---------- ----------
      7369 SMITH             800 CLERK             20       1600
      7499 ALLEN            1600 SALESMAN          30       1600
      7521 WARD             1250 SALESMAN          30       1600
      7566 JONES            2975 MANAGER           20       1600
      7654 MARTIN           1250 SALESMAN          30       1600
      7698 BLAKE            2850 MANAGER           30       1600
      7782 CLARK            2450 MANAGER           10       1600
      7788 SCOTT            3000 ANALYST           20       1600
      7839 KING             5000 PRESIDENT         10       1600
      7844 TURNER           1500 SALESMAN          30       1600
      7876 ADAMS            1100 CLERK             20       1600
      7900 JAMES             950 CLERK             30       1600
      7902 FORD             3000 ANALYST           20       1600
      7934 MILLER           1300 CLERK             10       1600

如果(在您遇到的问题中)I_GROUPS_LEVEL中只有一行包含值的“特殊”组合,则可以使用(有条件的,分析的)MINMAX甚至AVGSUM-它们都等于单个值,在您的情况下为67。如果有多个这样的值,那么您将需要做出选择:您想要MINMAXAVG还是其他东西。无论如何,您仍然可以使用相同的想法。

答案 1 :(得分:2)

我认为您想要一个窗口函数:

    SUM(CASE WHEN curr_mth_note IS NOT NULL AND i_group = '1' AND
                  s_level = '80'
             THEN qty_filled
        END) OVER (PARTITION BY s_date, part_no)  AS g1s1_filled

答案 2 :(得分:0)

代替case语句,为其编写一个子查询

(select qty_filled 
  from t_Table 
  where 
    i_group = '1' and 
    s_level = '80' and
    rownum = 1 
) as g1s1_filled

答案 3 :(得分:0)

您可以删除CASE表达式并将整个查询(ORDER BY子句除外)移至CTE。然后,您可以自我JOIN,将相关的g1s1_filled附加到每一行。

注意:定义自连接条件时必须小心;我在下面提供了一个建议,您可能需要对其进行完善。

查询:

WITH cte AS (
    SELECT
        s_date,
        part_no,
        i_group,
        s_level,
        p_category,
        qty_filled,
        qty_total,
        relief_amt,
        extreme_amt,
        curr_mth_note
        FROM
        (
            SELECT
                t1.s_date,
                t1.part_no,
                t1.i_group,
                t1.s_level,
                t1.p_category,
                t1.qty_filled,
                t1.qty_total,
                mv.relief_amt,
                mv.extreme_amt,
                mv.curr_mth_note,
            FROM
                multi_table mv,
                t_table t1
            WHERE
                t1.part_no = mv.part_no
                AND mv.part_no = 'xxxx'
                AND t1.s_date = mv.s_date
                AND t1.s_date = '201805'
            GROUP BY
                t1.s_date,
                t1.i_group,
                t1.s_level,
                t1.part_no,
                t1.p_category,
                t1.qty_filled,
                t1.qty_total,
                mv.relief_amt,
                mv.extreme_amt,
                mv.curr_mth_note,
            ORDER BY
                t1.s_date,
                t1.i_group,
                t1.s_level DESC
        )
)
SELECT a.*, b.qty_filled as g1s1_filled
FROM 
    cte AS a
    INNER JOIN cte as b 
        ON  b.s_date = a.s_date 
        AND b.part_no = a.part_no 
        AND b.i_group = '1' 
        AND b.s_level = '80'
        AND b.curr_mth_note IS NOT NULL
ORDER BY
    a.s_date,
    a.part_no,
    a.i_group,
    DECODE(a.s_level, '80', 1, '100', 2, 'Late', 3)