MySQL - 如何规范化包含分隔符分隔 ID 的列

2024-03-13

我正在尝试规范化一个表,该表是以前的开发人员设计的,其中有一列包含管道分隔的 ID,这些 ID 链接到同一个表中的其他行。

客户表

id    |    aliases (VARCHAR)
----------------------------
1     |    |4|58|76
2     |    
3     |
4     |    |1|58|76
...   |    
58    |    |1|4|76
...   |
76    |    |1|4|58

所以客户1、4、58和76都是彼此的“别名”。客户 2 和 3 没有别名,因此该字段包含空字符串。

我想废除整个“别名”系统,并对数据进行标准化,以便我可以将其他客户全部映射到一条记录。因此,我希望将客户 1、4、58 和 76 的相关表数据全部映射到客户 1。

我想我会填充一个新表,然后我可以加入其他表并对其执行更新。

连接表

id  |  customer_id  |  alias_id
-------------------------------
1   |  1            |  4
2   |  1            |  58
3   |  1            |  76

如何将第一个表中的数据转换为上述格式?如果这在纯 SQL 中绝对是一场噩梦,我将编写一个 PHP 脚本来尝试完成这项工作并插入数据。


当我开始回答这个问题时,我认为这会快速而简单,因为我曾经在 SQL Server 中做过一些非常类似的事情,但在翻译中证明这个概念很快就发展成了这个完整的解决方案。

您的问题中不清楚的一个警告是您是否有声明主 id 与别名 id 的条件。例如,此解决方案将允许 1 具有别名 4 以及 4 具有别名 1,这与简化示例问题中提供的数据一致。

为了设置此示例的数据,我使用了以下结构:

CREATE TABLE notnormal_customers (
  id INT NOT NULL PRIMARY KEY,
  aliases VARCHAR(10)
);

INSERT INTO notnormal_customers (id,aliases)
VALUES
(1,'|4|58|76'),
(2,''),
(3,''),
(4,'|1|58|76'),
(58,'|1|4|76'),
(76,'|1|4|58');

首先,为了表示一个客户与多个别名的一对多关系,我创建了此表:

CREATE TABLE customer_aliases (
    primary_id INT NOT NULL,
    alias_id INT NOT NULL,
    FOREIGN KEY (primary_id) REFERENCES notnormal_customers(id),
    FOREIGN KEY (alias_id)   REFERENCES notnormal_customers(id),
    /* clustered primary key prevents duplicates */
    PRIMARY KEY (primary_id,alias_id)
)

最重要的是,我们将使用custom SPLIT_STR功能 https://stackoverflow.com/questions/18304857/split-delimited-string-value-into-rows:

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');

然后我们将创建一个存储过程来完成所有工作。代码带有对源参考的注释。

DELIMITER $$
CREATE PROCEDURE normalize_customers()
BEGIN

  DECLARE cust_id INT DEFAULT 0;
  DECLARE al_id INT UNSIGNED DEFAULT 0;
  DECLARE alias_str VARCHAR(10) DEFAULT '';
  /* set the value of the string delimiter */
  DECLARE string_delim CHAR(1) DEFAULT '|';
  DECLARE count_aliases INT DEFAULT 0;
  DECLARE i INT DEFAULT 1;

  /*
    use cursor to iterate through all customer records
    http://burnignorance.com/mysql-tips/how-to-loop-through-a-result-set-in-mysql-strored-procedure/
  */
  DECLARE done INT DEFAULT 0;
  DECLARE cur CURSOR FOR
      SELECT `id`, `aliases`
      FROM `notnormal_customers`;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur;
  read_loop: LOOP

    /*
      Fetch one record from CURSOR and set to customer id and alias string.
      If not found then `done` will be set to 1 by continue handler.
    */
    FETCH cur INTO cust_id, alias_str;
    IF done THEN
        /* If done set to 1 then exit the loop, else continue. */
        LEAVE read_loop;
    END IF;

    /* skip to next record if no aliases */
    IF alias_str = '' THEN
      ITERATE read_loop;
    END IF;

    /*
      get number of aliases
      https://pisceansheart.wordpress.com/2008/04/15/count-occurrence-of-character-in-a-string-using-mysql/
    */
    SET count_aliases = LENGTH(alias_str) - LENGTH(REPLACE(alias_str, string_delim, ''));

    /* strip off the first pipe to make it compatible with our SPLIT_STR function */
    SET alias_str = SUBSTR(alias_str, 2);

    /*
      iterate and get each alias from custom split string function
      https://stackoverflow.com/questions/18304857/split-delimited-string-value-into-rows
    */
    WHILE i <= count_aliases DO

      /* get the next alias id */
      SET al_id = CAST(SPLIT_STR(alias_str, string_delim, i) AS UNSIGNED);
      /* REPLACE existing values instead of insert to prevent errors on primary key */
      REPLACE INTO customer_aliases (primary_id,alias_id) VALUES (cust_id,al_id);
      SET i = i+1;

    END WHILE;
    SET i = 1;

  END LOOP;
  CLOSE cur;

END$$
DELIMITER ;

最后,您可以通过调用以下命令来简单地运行它:

CALL normalize_customers();

然后就可以在console中查看数据了:

mysql> select * from customer_aliases;
+------------+----------+
| primary_id | alias_id |
+------------+----------+
|          4 |        1 |
|         58 |        1 |
|         76 |        1 |
|          1 |        4 |
|         58 |        4 |
|         76 |        4 |
|          1 |       58 |
|          4 |       58 |
|         76 |       58 |
|          1 |       76 |
|          4 |       76 |
|         58 |       76 |
+------------+----------+
12 rows in set (0.00 sec)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL - 如何规范化包含分隔符分隔 ID 的列 的相关文章

  • PHP 如果不存在,则从字符串中删除 ','

    我正在运行这段代码 stmt pdo conn gt prepare SELECT from admin where support emails support emails and logged logged and disabled
  • Postgres、更新和锁定顺序

    我正在研究 Postgres 9 2 有 2 个更新 每个更新都有自己的事务 一个看起来像 UPDATE foo SET a 1 WHERE b IN 1 2 3 4 另一个也类似 UPDATE foo SET a 2 WHERE b IN
  • Node.js 进行 rsa 加密的正确方法?

    我正在尝试创建一个 WS 来发出肥皂请求 在消息正文中有一个包含加密文本的字段 我有公钥来加密文本 但我获得的唯一结果是文本无法识别 我使用节点的加密模块来发出请求 并且文本已加密 但我不知道为什么没有正确加密 PS我用 openssl p
  • PHP/MySQL:如何在网站中创建评论部分[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我不会问 如何使用 PHP MySQ
  • PHP 相等变量

    我想知道是否有任何方法可以检查大量变量是否相等 如果我只有几个变量 我可以这样做 if a b a c b c 但是 如果我有 20 个变量 则需要一些时间来编写所有组合 还有其他方法吗 if count array unique arra
  • 从 PDO 准备好的语句中获取原始 SQL 查询字符串

    在准备好的语句上调用 PDOStatement execute 时 有没有办法让原始 SQL 字符串执行 出于调试目的 这将非常有用 我假设您的意思是您想要最终的 SQL 查询 并将参数值插入其中 我知道这对于调试很有用 但这不是准备好的语
  • SQL Server 相当于 MySQL 的 USING

    在 MySQL 中 当您连接不同表中具有相同名称的列时 可以在连接中使用关键字 USING 例如 这些查询产生相同的结果 SELECT FROM user INNER JOIN perm USING uid SELECT FROM user
  • 如何从控制器访问 Zend Framework 应用程序的配置?

    我有一个基于 Zend 框架的应用程序快速开始 http framework zend com docs quickstart setup 我已经让演示工作起来 现在正在实例化一个新的模型类来完成一些实际工作 在我的控制器中 我想将配置参数
  • 我可以在一个查询中更新/选择表吗?

    我需要在查看页面时选择数据并更新 视图 列 有没有一种方法可以在一个查询中执行此操作 或者我是否必须使用不同的查询 如果您不想 不需要使用事务 则可以创建一个存储过程 该过程首先更新视图计数 然后选择值并将其返回给用户
  • Twig:选择某些块并渲染它们

    我正在将 twig 模板引擎集成到 PHP 应用程序中 特别是 我想使用 twig 引擎来渲染表单 了解了 symfony2 如何使用 twig 渲染表单小部件后 他们有一个巨大的模板文件 其中包含所有小部件 如下所示 block pass
  • 如何在Sequelize中从主模型同一级别的包含模型返回结果?

    这是我在项目中完成的代码和结果 我想获得包含模型的结果与主模型相同的结果 下面的代码是我所做的 序列化查询 User findAll include model Position attributes POSITION NAME then
  • Yii 查询时对相关模型的限制

    我遇到了极限问题 我正在使用的代码如下 model PostCategory model record model gt with array posts gt array order gt posts createTime DESC li
  • Laravel 8、Sanctum、Fortify /logout 在 Postman 中抛出“CSRF 令牌不匹配”

    我安装了 L8 Sanctum 和 Fortify 进行身份验证 我以前可以 login 使用了Pre request Script设置X XSRF TOKEN 我什至得到了 api user成功地 但当我这样做时 logout 我在 Po
  • Laravel 5.3:护照实现 - {“error”:“invalid_client”,“message”:“客户端身份验证失败”}

    我按照中提到的确切步骤进行操作Laracast Laravel 5 3 的新增功能 Laravel Passport https laracasts com series whats new in laravel 5 3 episodes
  • PHP 时间间隔

    我正在寻找一个看起来应该非常简单的解决方案 但似乎我不能在这里找到任何好的答案 而且我自己似乎无法让它发挥作用 我正在寻找的是设置开始时间 结束时间 然后迭代给定时间间隔之间的一组时间 例如 上午 9 00 下午 5 00 是开始时间 这些
  • 高效插入和更新时检查唯一性

    我的员工表中有 2 列 每列值必须是唯一的 staff code staff name staff id staff code staff name 1 MGT Management 2 IT IT staff 当向表中插入或更新项目时 我
  • 如何在动态查询中将行值连接到列名

    我正在开发一个允许配置问题和答案的应用程序 目前最多可以有 20 个答案 但也可能更少 我的结构如下 问题 ID FormId QuestionText AnswerField 1 1 Name Answer01 2 1 Address A
  • PHP简单的html dom解析器与wordpress冲突吗?

    PHP简单的html dom解析器与wordpress冲突吗 因为每当我尝试将其与此代码一起包含在我的标头中时 一切都变成空白 感谢您提前提供任何帮助 当我尝试在 HTML 文档中使用 PHP 包含时 我遇到了同样的问题 但当我使用func
  • 案例陈述以确定我是否应该结合

    我目前想做某种条件联合 给出以下示例 SELECT age name FROM users UNION SELECT 25 AS age Betty AS name 假设我只想在 用户 计数 gt 2 时合并第二个语句 否则不合并两者 总之
  • 哪个是识别关系或非识别关系中的子表?

    在表之间的识别和非识别关系的上下文中 MySQL 文档大量将表称为父表和子表 如何判断哪个表是父表 哪个表是子表 子表 A K A 弱实体 http en wikipedia org wiki Weak entity 是一个表 其主键属性d

随机推荐

  • 无法执行目标 org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile)

    我知道这是一个重复的问题 但其他主题的答案对我没有帮助 我正在使用 Eclipse Photon Java 版本 10 我已在 eclipse 和 pom xml 文件中将 jdk jre 版本设置为 10 我已经更改了 eclipse i
  • Python-查找文本文件中单词列表的词频

    我正在尝试加快我的项目来计算词频 我有 360 多个文本文件 我需要获取单词总数以及另一个单词列表中每个单词出现的次数 我知道如何使用单个文本文件来做到这一点 gt gt gt import nltk gt gt gt import os
  • 同时可靠地使用核心数据

    我正在构建我的第一个 iOS 应用程序 理论上它应该非常简单 但我很难让它足够安全 让我有信心将其提交到 App Store 简而言之 主屏幕有一个表视图 在选择一行后 它会转到另一个表视图 该表视图以主从方式显示与所选行相关的信息 底层数
  • Angular - 拼接函数总是删除最后一个元素

    我有一个对象数组 我想在单击删除键时删除某些对象 但是 无论我创建了多少行 它总是从行数组中删除最后一项 即使我明确地放入这样的行 scope rows splice 1 1 它仍然会删除最后一个元素 而不是第二个元素 JS angular
  • 无法通过数字键盘使用小数(Android 上的 Xamarin Forms)

    我已经尝试了几个论坛上给出的几种解决方案 也在 Xamarin 论坛上提问 但都没有结果 我想在 Xamarin Forms 中创建一个条目 用户可以在其中添加十进制数 问题是我的数字键盘禁用了逗号 我可以使用自定义渲染器添加点 但由于我住
  • 如何在IIS中部署Angular Universal?

    我在 IIS 中部署角度通用应用程序时遇到问题 在角度通用中 创建了两个 dist 文件夹 一个是用于客户端的 dist 另一个是 dist 服务器 当我尝试托管时 我给出了 dist 文件夹的路径 站点正在运行 但页面未从服务器渲染 我遇
  • HTMLInputElement 没有方法“parent”

    我的页面上有两个非常相似的表单 我在 jquery 中进行简单的验证 以检查每个字段是否都有值 然后再使用 ajax 将数据发送到使用该数据的 php 处理程序 由于表单之间的相似性 我无法知道提交的是哪个表单 所以我想尝试通过表单容器 d
  • 将 Google-Play-Services 添加到库项目

    我正在开发一个地图库 并且正在使用 Google Play Services 到目前为止 一切都很好 问题是这样的 我将 Google Play Services 库项目包含在我的地图库中 使用 属性 gt android gt 添加库 使
  • 我是否应该始终在 Dispose 方法中断开事件处理程序的连接?

    我使用 C 工作 我的工作场所有一些代码标准 其中之一是我们连接的每个事件处理程序 例如KeyDown 必须在断开Dispose方法 这有什么好的理由吗 除非您期望事件的发布者比订阅者活得更久 否则没有理由删除事件处理程序 不是 这是民间传
  • 即使 Access-Control-Allow-Origin 设置为 *,为什么仍会发送多个 OPTIONS 请求?

    我已经构建了一个 API api example com 并希望可以从 www example com 访问它我还希望可以从其他域访问它 为此 我添加了 Access Control Allow Origin 但是当我打开 www exam
  • 如何比较两个边缘图像(在 OpenCV 中)?

    在我的项目中 我需要与图像进行比较 一张图像显示渲染模型 另一张图像是照片 其中显示模型中表示的真实对象 我到底想要什么 该算法必须比较两个图像并返回一个描述相似度的数字 假设数字越低 图像就越吻合 两个图像都表示为二进制图像 仅包含真实渲
  • iOS PNG图像旋转90度

    在我正在编写的 iOS 应用程序中 我处理 PNG 因为我处理 Alpha 通道 由于某种原因 我可以将 PNG 加载到我的imageView很好 但是当需要将图像从我的应用程序复制到粘贴板上或将图像保存到我的相机胶卷时 图像会旋转 90
  • 如何在 swagger 中成功记录多种内容类型的 GET 响应

    假设我们有一个 json swagger 规范示例 swagger 2 0 info version 1 0 0 title Some API basePath api v1 consumes application json produc
  • 如何在 Swift 中使用 dropbox api 获取共享链接?

    我想制作一个应用程序 让用户将文件上传到保管箱 然后获得共享该文件的选项 如何获取文件的保管箱链接 看来我可以用 client sharing createSharedLink 路径 myfile 但我如何以字符串形式访问该数据 这是一个如
  • Windows:自动挂起整个进程? [复制]

    这个问题在这里已经有答案了 使用 Win32 API 只能使用以下命令挂起单个线程SuspendThread 但不是一次调用就能完成完整的过程 迭代进程线程并一次挂起它们并不是一个好的选择 因为它可能会导致死锁和意外行为 这应该是使用 DD
  • thread_local 的成本

    现在C 正在添加thread local存储作为一种语言功能 我想知道一些事情 What is the cost of thead local likely to be 在记忆中 用于读和写操作 与之相关的是 操作系统通常如何实现这一点 看
  • 修复页面滚动时的标题转换

    我一生都无法弄清楚这一点 有谁知道这个网站上的滚动效果是如何创建的 http blindbarber com news http blindbarber com news 我正在开发一个项目 该效果将非常有帮助 这样我的固定导航在滚动时不会
  • 将日期从字符串格式转换为 OLE 自动化日期

    我有一个日期字符串21 Apr 2018 如何将此日期字符串转换为 python 中的 OLE 自动化日期 我正在使用Python v3 6 OLE 日期的定义可以在此处找到 https msdn microsoft com en us l
  • JpaRepository 与枚举:findAllByOfferState_ACTIVE。没有这样的元素异常

    我想获得所有报价 其中 OfferState 等于 ACTIVE 是否可以仅使用方法名称使用 Spring Data 或者我必须使用 Query Repository public interface OfferRepository ext
  • MySQL - 如何规范化包含分隔符分隔 ID 的列

    我正在尝试规范化一个表 该表是以前的开发人员设计的 其中有一列包含管道分隔的 ID 这些 ID 链接到同一个表中的其他行 客户表 id aliases VARCHAR 1 4 58 76 2 3 4 1 58 76 58 1 4 76 76