使用Oracle SQL动态创建列

时间:2018-07-20 10:25:15

标签: sql oracle plsql

当前,我正在研究固定资产注册报告棒,并且需要在主查询中添加Projection列。

          Depreciation  Remaining Life of
Assed_No        Amount    asset in months
--------  ------------  -----------------
       1           400                  6
       2           200                  3
       3           100                  4
       4           600                  1

现在,我想在SQL中进行修改,以根据应以月为单位的资产剩余寿命来生成。对于以月为单位的第一个资产的剩余寿命为6,因此总共6个投影列的值应为400。如果剩余寿命小于最大编号。即6,则其余列应为0。

我想要如下所示的最终解决方案,

          Depreciation  Remaining Life of
Assed_No        Amount    asset in months  Projection 1  Projection 2  Projection 3  Projection 4  Projection 5  Projection 6
--------  ------------  -----------------  ------------  ------------  ------------  ------------  ------------  ------------
       1           400                  6           400           400           400           400           400           400
       2           200                  3           200           200             0             0             0             0
       3           100                  4           100           100           100           100             0             0
       4           600                  1           600             0             0             0             0             0

3 个答案:

答案 0 :(得分:2)

您可以为每个投影使用一个简单的case表达式:

-- CTE for sample data
with your_table (asset_no, amount, remaining_months) as (
            select 1, 400, 6 from dual
  union all select 2, 200, 3 from dual
  union all select 3, 100, 4 from dual
  union all select 4, 600, 1 from dual
)
-- query using my CTE column names
select asset_no, amount, remaining_months,
  case when remaining_months >= 1 then amount else 0 end as proj_1,
  case when remaining_months >= 2 then amount else 0 end as proj_2,
  case when remaining_months >= 3 then amount else 0 end as proj_3,
  case when remaining_months >= 4 then amount else 0 end as proj_4,
  case when remaining_months >= 5 then amount else 0 end as proj_5,
  case when remaining_months >= 6 then amount else 0 end as proj_6
from your_table;

  ASSET_NO     AMOUNT REMAINING_MONTHS     PROJ_1     PROJ_2     PROJ_3     PROJ_4     PROJ_5     PROJ_6
---------- ---------- ---------------- ---------- ---------- ---------- ---------- ---------- ----------
         1        400                6        400        400        400        400        400        400
         2        200                3        200        200        200          0          0          0
         3        100                4        100        100        100        100          0          0
         4        600                1        600          0          0          0          0          0

答案 1 :(得分:1)

这基本上是Alex查询的动态版本(作为奖励!)

请注意refcursor绑定变量的使用。当您在SQl * Plus中运行它,或者在SQL开发人员或Toad中作为脚本(F5)运行它时,它将起作用。

您也可以在Oracle 12c及更高版本中使用DBMS_SQL.RETURN_RESULT进行此操作。

VARIABLE x REFCURSOR;
DECLARE
v_case_expr VARCHAR2(1000);
BEGIN
SELECT
    listagg('CASE WHEN remaining_months > = '
              || level
              || ' 
                         then amount else 0 end as proj_'
              || level,',') WITHIN GROUP ( ORDER BY level)
INTO v_case_expr
FROM
    dual
CONNECT BY
    level <= (
        SELECT
            MAX(remaining_months)
        FROM
            assets
    );            

OPEN :x FOR 'select asset_no, amount, remaining_months, '
           || v_case_expr
           || ' FROM assets';END;
/

PRINT x;

PL/SQL procedure successfully completed.



  ASSET_NO     AMOUNT REMAINING_MONTHS     PROJ_1     PROJ_2     PROJ_3     PROJ_4     PROJ_5     PROJ_6
---------- ---------- ---------------- ---------- ---------- ---------- ---------- ---------- ----------
         1        400                6        400        400        400        400        400        400
         2        200                3        200        200        200          0          0          0
         3        100                4        100        100        100        100          0          0
         4        600                1        600          0          0          0          0          0

答案 2 :(得分:0)

当计算量增加时,有时枢轴可能会更好。 在这里,我之前使用笛卡尔积来创建数据:

import cv2
import pytesseract
from PIL import Image
import numpy as np
# import bm3d
img = cv2.imread('1_2_2.png')
# img = cv2.medianBlur(img, 5)
img = cv2.GaussianBlur(img,(13,13),0)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# gray = cv2.medianBlur(, 5)
# cv2.imshow("img", gray)
# gray = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | 
cv2.THRESH_OTSU) 
[1]
v = np.median(gray)
sigma = 0.33
#---- apply automatic Canny edge detection using the computed median-- 
--
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
gray = cv2.Canny(img,lower,upper)
# ret,gray = cv2.threshold(gray,110,255,cv2.THRESH_BINARY)
kernel = np.ones((4,4),np.uint8)
gray = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
gray = cv2.dilate(gray,kernel,iterations = 1)
# gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)\
# gray = cv2.erode(gray,kernel,iterations = 1)
gray = cv2.bitwise_not(gray)
cv2.imshow("threshold", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
# gray = cv2.medianBlur(gray, 3)
text = pytesseract.image_to_string(gray)
print(text)

在这里认为用case表达式的解决方案更好