在sql中获取两行之间的数据

ykejflvf  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(374)
id col  op  value
1  math >=   75
2  math <=   82
3  sci  =    72
4  geo  >    45
5  geo  <    50

从我的表中选择值;
我有一张这样的table。我想要oracle sql中的输出,比如46,47..49,72,75,76,77…82。

dtcbnfnu

dtcbnfnu1#

知道了!有点复杂,但希望评论能有所帮助。这是一个使用公共表表达式(commontableexpressions,cte)分解成步骤的查询。这证明它是可以做到的,但我强烈建议找到一个更好的方法来解决你的问题。

-- Original data
WITH tbl(ID, COL, op, val) AS (
  SELECT 1, 'math', '>=', 75 FROM dual UNION ALL
  SELECT 2, 'math', '<=', 82 FROM dual UNION ALL
  SELECT 3, 'sci',  '=',  72 FROM dual UNION ALL
  SELECT 4, 'geo',  '>',  45 FROM dual UNION ALL
  SELECT 5, 'geo',  '<',  50 FROM dual
),
-- Find the ranges based on the col and it's operator
range_tbl(ID, start_val, end_val) AS (
  SELECT ID,  
    CASE op
      WHEN '>' 
        THEN val + 1
      ELSE val
    END AS start_val,
    CASE op
      WHEN '>='
        THEN (SELECT val
              FROM tbl tbl1
              WHERE tbl1.COL=tbl.COL
              AND op = '<=')
      WHEN '>'
        THEN (SELECT val-1
              FROM tbl tbl1
              WHERE tbl1.COL=tbl.COL
              AND op = '<')     
      WHEN '='
        THEN val       
    END AS end_val
FROM tbl
),
-- "Loop" through each range using connect by
nbr_tbl(nbr) AS (
  SELECT start_val + (LEVEL-1) AS nbr
  FROM range_tbl
  WHERE end_val IS NOT NULL
  CONNECT BY LEVEL <= (end_val - start_val)+1
    AND PRIOR ID = ID
    AND PRIOR SYS_GUID() IS NOT NULL
)
-- Now put them into a single row using listagg
SELECT LISTAGG(nbr, ',')
         WITHIN GROUP (ORDER BY nbr) AS nbr_list
FROM nbr_tbl
;

输出:

NBR_LIST                                                                        
-------------------------------------------
46,47,48,49,72,75,76,77,78,79,80,81,82                                          
1 row selected.
mbjcgjjk

mbjcgjjk2#

你想输出范围吗,像这样的?
数学:75,76,77,78,79,80,81,82
科学院:72
地理位置:46,47,48,49
如果是这样的话,单独使用sql是错误的。您可以使用sql在另一个工具(可能是pl/sql)中帮助构建动态表达式。

jbose2ul

jbose2ul3#

我想你得去拿 min 以及 max 值并按如下方式生成数字:

SQL> WITH YOUR_TABLE(id, col,  op,  value) AS
  2  (SELECT 1,  'math', '>=',   75 FROM DUAL UNION ALL
  3  SELECT 2,  'math', '<=',   82 FROM DUAL UNION ALL
  4  SELECT 3,  'sci',  '=',    72 FROM DUAL UNION ALL
  5  SELECT 4,  'geo',  '>',    45 FROM DUAL UNION ALL
  6  SELECT 5,  'geo',  '<',    50 FROM DUAL)
  7  -- YOUR QUERY STARTS FROM HERE
  8  SELECT
  9  LISTAGG(V.COLUMN_VALUE, ',') WITHIN GROUP( ORDER BY V.COLUMN_VALUE) AS RES
 10    FROM (
 11  SELECT COL,
 12         MIN( CASE WHEN OP IN( '=', '>=') THEN VALUE
 13         WHEN OP = '>' THEN VALUE + 1
 14         END ) AS MINVAL,
 15         MAX( CASE WHEN OP IN( '=', '<=') THEN VALUE
 16         WHEN OP = '<' THEN VALUE - 1
 17         END ) AS MAXVAL
 18    FROM YOUR_TABLE
 19   GROUP BY COL) T
 20   CROSS JOIN TABLE ( CAST(MULTISET(
 21  SELECT T.MINVAL + LEVEL - 1
 22    FROM DUAL CONNECT BY LEVEL <= T.MAXVAL - T.MINVAL + 1
 23  ) AS SYS.ODCIVARCHAR2LIST) ) V;

RES
---------------------------------------------------
46,47,48,49,72,75,76,77,78,79,80,81,82

SQL>

相关问题