You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PSQL技术需求:基于视图中PARENT列唯一值实现CHILD列值的唯一性

解决PARENT与CHILD唯一映射的更新方案

首先咱们明确需求:要让视图里每个唯一的PARENT值对应唯一的CHILD值,如果当前CHILD被多个PARENT共享,就通过在CHILD的-符号前追加字符的方式修改,最终达到一一映射的目的。

问题分析

看你给出的初始数据,存在两个冲突场景:

  • BBB - 364同时对应ABC - 123GHI - 789两个PARENT
  • NNN - 679同时对应JKL - 343MNO - 524两个PARENT

咱们的目标就是给这些冲突的PARENT对应的CHILD添加唯一标识,让每个PARENT有专属的CHILD。

解决方案思路

  1. 识别冲突组:用窗口函数找出每个CHILD对应的PARENT数量,标记出被多个PARENT共享的CHILD
  2. 生成唯一后缀:对每个冲突CHILD下的PARENT分组,给每个PARENT分配唯一的序号,用序号对应字母追加到CHILD前缀后
  3. 更新CHILD列:根据标记的冲突记录,修改对应的CHILD值

具体SQL实现(以MySQL为例)

第一步:先查看冲突记录(可选,用于验证)

SELECT 
    ID,
    PARENT,
    CHILD,
    -- 统计当前CHILD对应的不同PARENT数量
    COUNT(DISTINCT PARENT) OVER (PARTITION BY CHILD) AS parent_count,
    -- 给当前CHILD下的PARENT排序,序号用于生成唯一标识
    ROW_NUMBER() OVER (PARTITION BY CHILD ORDER BY ID) AS rn
FROM your_view;

这个查询会帮你清晰看到哪些CHILD存在冲突,以及每个PARENT在冲突组里的排序。

第二步:执行更新操作

UPDATE your_view
JOIN (
    SELECT 
        PARENT,
        COUNT(DISTINCT PARENT) OVER (PARTITION BY CHILD) AS parent_count,
        ROW_NUMBER() OVER (PARTITION BY CHILD ORDER BY ID) AS rn
    FROM your_view
) AS sub ON your_view.PARENT = sub.PARENT
SET CHILD = CONCAT(
    -- 拆分CHILD的前缀部分(-之前的内容)
    SUBSTRING_INDEX(your_view.CHILD, '-', 1),
    -- 给排序序号>1的记录追加字母(rn=2对应A,rn=3对应B,以此类推)
    CASE WHEN sub.rn > 1 THEN CHAR(64 + sub.rn) ELSE '' END,
    '-',
    -- 拆分CHILD的后缀部分(-之后的内容)
    SUBSTRING_INDEX(your_view.CHILD, '-', -1)
)
-- 只更新存在冲突且不是组内第一条的记录
WHERE sub.parent_count > 1 AND sub.rn > 1;

代码说明

  • PARTITION BY CHILD:按CHILD分组,统计每个CHILD对应的PARENT数量
  • ROW_NUMBER() OVER (...):给每个CHILD组内的PARENT排序,这里按ID排序,你可以改成按PARENT或者其他字段,决定哪个PARENT保留原CHILD值
  • CHAR(64 + sub.rn):利用ASCII码生成字母,65是A,所以rn=2对应A,rn=3对应B,刚好满足追加唯一字符的需求
  • SUBSTRING_INDEX:拆分CHILD的前缀和后缀,保证修改后只改变-前的部分

匹配示例效果

执行完上面的SQL后,你的数据会和预期结果一致:

  • ABC - 123对应的CHILD变成BBBA - 364(因为它是BBB - 364组内的第二条记录,rn=2,追加A)
  • 如果要改成示例里JKL - 343对应的NNNQ - 679,只需要把CHAR(64 + sub.rn)改成自定义的字符映射即可,比如用CASE语句指定特定字符:
    CASE 
        WHEN sub.rn = 2 THEN 'Q'
        WHEN sub.rn = 3 THEN 'R'
        ELSE '' 
    END
    

如果是其他数据库(比如SQL Server、Oracle),只需要调整字符串拆分函数即可:

  • SQL Server用LEFT(CHILD, CHARINDEX('-', CHILD)-1)RIGHT(CHILD, LEN(CHILD)-CHARINDEX('-', CHILD))
  • Oracle用SUBSTR(CHILD, 1, INSTR(CHILD, '-')-1)SUBSTR(CHILD, INSTR(CHILD, '-')+1)

内容的提问来源于stack exchange,提问作者JJ13596

火山引擎 最新活动