Oracle SQL将行中的一列与同一列中的前一行进行比较

如何解决Oracle SQL将行中的一列与同一列中的前一行进行比较

这是我的表(Table1)当前在Oracle数据库中的方式。

<CustomTooltip id="123"><Text>...</Text></CustomTooltip>

我试图获得一个输出,该输出将每一行的Product列进行比较,以得到如下所示的内容: 在这里,我正在比较第1行和第2行,以查看第2行是否具有第1行中没有的新产品(NEW_PRODUCTS)。

似乎我可以使用LAG或LEAD函数,但由于产品之间使用ID Year_Mth Product 123 201901 1,2,3 123 201902 1,4,5 123 201903 2,3,6 123 201904 1,5,6 分隔符,因此似乎很棘手。

,

解决方法

这是一种选择。看起来和您的数据模型一样丑陋:)查看代码中的注释。如果您不确定每个CTE的功能,建议您分步运行以下代码并查看其结果。

为了便于阅读,我将其分为几部分。

SQL> with
  2  test (id,year_mth,product) as
  3    -- your sample data (as well as some of my sample data)
  4    (select 123,201901,'1,2,3'   from dual union all
  5     select 123,201902,4,5' from dual union all
  6     select 123,201903,'2,3,6' from dual union all
  7     select 123,201904,5,6' from dual union all
  8     --
  9     select 888,'apple,banana' from dual union all
 10     select 888,banana' from dual union all
 11     select 888,lemon'  from dual
 12    ),
 13  py as
 14    (select id,15            year_mth ymp,-- "this" year_mth
 16            lead(year_mth) over (partition by id order by year_mth) ymn  -- "next" year_mth
 17     from test
 18     order by id,year_mth
 19    ),20  tabp as
 21    -- products that belong to "THIS" year_mth split to rows
 22    (select
 23        t.id,24        t.year_mth,25        p.ymp,26        p.ymn,27        regexp_substr(t.product,'[^,]+',1,c.column_value) product
 28      from test t join py p on t.id = p.id and t.year_mth = p.ymp cross join
 29        table(cast(multiset(select level from dual
 30                            connect by level <= regexp_count(product,',') + 1
 31                           ) as sys.odcinumberlist)) c
 32    ),33  tabn as
 34    -- products that belong to "NEXT" year_mth split to rows
 35    (select
 36        t.id,37        t.year_mth,38        p.ymp,39        p.ymn,40        regexp_substr(t.product,c.column_value) product
 41      from test t join py p on t.id = p.id and t.year_mth = p.ymn cross join
 42        table(cast(multiset(select level from dual
 43                            connect by level <= regexp_count(product,') + 1
 44                           ) as sys.odcinumberlist)) c
 45    ),
  • 46  newprod as
    47    -- MINUS set operator finds differences between "NEXT" and "THIS" year_mth
    48    (select id,ymn,product from tabn
    49     minus
    50     select id,product from tabp
    51    )
    52  -- finally,aggregate new products (result of the previous MINUS set operation)
    53  select
    54    t.id,55    t.year_mth,56    t.product,57    listagg(case when t.rn = 1 then t.product else n.product end,')
    58      within group (order by n.product) new_products
    59  from (select a.id,60          a.year_mth,61          a.product,62          row_number() over (partition by a.id order by a.year_mth) rn
    63        from test a
    64       ) t left join newprod n on t.id = n.id and t.year_mth = n.ymn
    65  group by t.id,t.year_mth,t.product
    66  order by t.id,t.year_mth;
    
  •        ID   YEAR_MTH PRODUCT      NEW_PRODUCTS
    

          123     201901 1,3        1,3
          123     201902 1,5      4,5
          123     201903 2,6      3,6
          123     201904 1,6      1,5
          888     201901 apple,banana apple,banana
          888     201902 apple,banana
          888     201903 apple,lemon  lemon
    

    已选择7行。

    SQL>

,

在需要使用此类定界字符串的情况下,使用xml函数(例如fn:string-join(),fn:tokenize())通常非常方便。

例如:

xmltable(
       'let $x:=tokenize($a,","),$y:=tokenize($b,")
        return fn:string-join($x[not(.=$y)],")'
       passing product as "a",prev_product as "b"
     columns New_Products varchar(100) path '.'
    ) x

此xmltable()拆分输入参数product和prev_product,并从prev_product中不在product中的那些子字符串中返回:

  1. 函数tokenize($a,")使用逗号作为分隔符来拆分输入字符串$ a。
  2. $x[not(.=$y)]从$ x返回$ y中不存在的那些值
  3. 函数string-join($arg1,")使用逗号作为分隔符来连接$ arg1中的值。

完整示例:

with
test (id,product) as
  -- your sample data (as well as some of my sample data)
  (select 123,3'   from dual union all
   select 123,5' from dual union all
   select 123,6' from dual union all
   select 123,6' from dual union all
   --
   select 888,banana' from dual union all
   select 888,lemon'  from dual
  )
select
    t.*,x.*
from 
    (
     select 
        t.*,lag(t.product)over(partition by id order by year_mth) prev_product
     from test t
    ) t,xmltable(
       'let $x:=tokenize($a,prev_product as "b"
     columns New_Products varchar(100) path '.'
    ) x;

我使上面的xquery很久了,只是为了使其更具可读性。 在现实生活中,xquery会更短: fn:string-join(tokenize($a,")[not(.=tokenize($b,"))],")

with
test (id,xmltable(
       'fn:string-join(tokenize($a,prev_product as "b"
     columns New_Products varchar(100) path '.'
    ) x
,

与我的相似,如果要重新透视,请在末尾添加一个listagg和group-by查询...

WITH
input(id,product) AS (
          SELECT 123,3'    FROM dual
UNION ALL SELECT 123,5'  FROM dual
UNION ALL SELECT 123,6'  FROM dual
UNION ALL SELECT 123,6'  FROM dual
),i(i) AS (
           SELECT 1 FROM dual
 UNION ALL SELECT 2 FROM dual
 UNION ALL SELECT 3 FROM dual
 UNION ALL SELECT 4 FROM dual
 UNION ALL SELECT 5 FROM dual
),unpivot AS (
  SELECT
    id,i,REGEXP_SUBSTR(product,'\d+',i) AS prd
  FROM input CROSS JOIN i
  WHERE REGEXP_SUBSTR(product,i) <> ''
)
SELECT 
  *,CASE 
    WHEN LAG(year_mth) OVER(PARTITION BY id,prd ORDER BY year_mth) IS NULL
    THEN 'new'
    ELSE 'old'
   END
FROM unpivot ORDER BY 3,4;
-- out  id  | i | year_mth | prd | case 
-- out -----+---+----------+-----+------
-- out  123 | 1 |   201901 | 1   | new
-- out  123 | 2 |   201901 | 2   | new
-- out  123 | 3 |   201901 | 3   | new
-- out  123 | 1 |   201902 | 1   | old
-- out  123 | 2 |   201902 | 2   | old
-- out  123 | 3 |   201902 | 4   | new
-- out  123 | 4 |   201902 | 5   | new
-- out  123 | 1 |   201903 | 2   | old
-- out  123 | 2 |   201903 | 3   | old
-- out  123 | 3 |   201903 | 4   | old
-- out  123 | 4 |   201903 | 6   | new
-- out  123 | 1 |   201904 | 1   | old
-- out  123 | 2 |   201904 | 4   | old
-- out  123 | 3 |   201904 | 5   | old
-- out  123 | 4 |   201904 | 6   | old

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-