【问题标题】:how to perform sql actions/query for duplicate rows如何对重复行执行 sql 操作/查询
【发布时间】:2021-08-19 15:45:57
【问题描述】:

我有 2 张桌子:

1-brokers(这是一家可以有多个经纪人个人的公司)

2-brokerIndividuals(一个person/individuals表,有所属经纪公司的外键和个人信息)

我正在尝试为 brokers 表创建一个唯一索引列,其中字段 companyName 是唯一的,isDeleted 是 NULL。目前,该表已经填充,所以我想编写一个 SQL QUERY 来查找重复的行,只要有相同的行 companyNameisDeleted=NULL,我想执行 2 个操作/查询:

1-保持第一行不变并将其他重复行(第一个重复行之后的行)行的isDeleted 列值更改为true

2- 为第一行的重复行关联或更改brokerIndividuals 中的外键。

我正在尝试做的口头描述是:软删除重复的行并将它们对应的brokerIndividuals 与第一次出现的重复相关联。表需要出现 1 次 companyName,其中 isDeletedNULL

我正在使用 knex.js ORM,所以如果有帮助,您还可以建议使用 knex 函数的解决方案,但 knex 还不支持部分索引(Knex.js - How to create unique index with 'where' clause?)所以我必须使用原始 SQL 方法。另外我使用的数据库是 mssql(version: 6.0.1)。

【问题讨论】:

  • 这听起来像是一次性操作——这是标准 SQL 中的一项简单操作,您需要特定于 knex 的解决方案吗?如果不标记具体的数据库平台。
  • 嗨@Stu,我不介意knex 特定的解决方案,但我认为SQL 查询会更受欢迎。我们使用的数据库是MySql。
  • 尝试在其中一个值可以是 null 的组合上创建直接 UNIQUE 约束时会遇到问题,因为 null = null 不会违反约束。跨度>
  • 您向我展示的错误似乎不是 MySQL 错误。您真正使用的是什么数据库(和版本)?调整有问题的标签以匹配。如果错误来自您的接口层,则您可能有与数据库无关或数据库之外的限制。

标签: sql sql-server knex.js


【解决方案1】:

这是一个完整的测试用例(已注释),带有指向小提琴的链接:

Working test case, tested with MySQL 5.5, 5.6, 5.7, 8.0 and MariaDB up to 10.6

创建表并插入带有重复company_name 条目的初始数据:

CREATE TABLE brokers (
     id           int  primary key auto_increment
   , company_name VARCHAR(30)
   , isDeleted    boolean default null
);

CREATE TABLE brokerIndividuals (
     id           int  primary key auto_increment
   , broker_id    int references brokers (id)
);

INSERT INTO brokers (company_name) VALUES
     ('name1')
   , ('name1')
   , ('name1')
   , ('name1')
   , ('name123')
   , ('name123')
   , ('name123')
   , ('name123')
;

INSERT INTO brokerIndividuals (broker_id) VALUES
    (2)
  , (7)
;

SELECT * FROM brokers;

+----+--------------+-----------+
| id | company_name | isDeleted |
+----+--------------+-----------+
|  1 | name1        |      null |
|  2 | name1        |      null |
|  3 | name1        |      null |
|  4 | name1        |      null |
|  5 | name123      |      null |
|  6 | name123      |      null |
|  7 | name123      |      null |
|  8 | name123      |      null |
+----+--------------+-----------+


SELECT * FROM brokerIndividuals;

+----+-----------+
| id | broker_id |
+----+-----------+
|  1 |         2 |
|  2 |         7 |
+----+-----------+

根据MIN(id) per company_name 调整代理以确定isDeleted:

UPDATE brokers
  JOIN (
         SELECT company_name, MIN(id) AS id
           FROM brokers
          GROUP BY company_name
       ) AS x
    ON x.company_name = brokers.company_name
   AND isDeleted IS NULL
   SET isDeleted = CASE WHEN (x.id <> brokers.id) THEN 1 END
;

更新的经纪人内容:

SELECT * FROM brokers;

+----+--------------+-----------+
| id | company_name | isDeleted |
+----+--------------+-----------+
|  1 | name1        |      null |
|  2 | name1        |         1 |
|  3 | name1        |         1 |
|  4 | name1        |         1 |
|  5 | name123      |      null |
|  6 | name123      |         1 |
|  7 | name123      |         1 |
|  8 | name123      |         1 |
+----+--------------+-----------+

对于brokerIndividuals,找到/设置正确的broker_id

UPDATE brokerIndividuals
  JOIN brokers AS b1
    ON b1.id = brokerIndividuals.broker_id
  JOIN brokers AS b2
    ON b1.company_name = b2.company_name
   AND b2.isDeleted IS NULL
   SET brokerIndividuals.broker_id = b2.id
;

新内容:

SELECT * FROM brokerIndividuals;

+----+-----------+
| id | broker_id |
+----+-----------+
|  1 |         1 |
|  2 |         5 |
+----+-----------+

【讨论】:

  • 运行此查询会出现语法错误。我得到的错误是:迁移失败并出现错误:UPDATE OriginationAdmin.Brokers JOIN ( SELECT CompanyName, MIN(Id) AS Id FROM OriginationAdmin.Brokers GROUP BY CompanyName ) AS x ON x.CompanyName = OriginationAdmin.Brokers.CompanyName AND isDeleted IS NULL SET isDeleted = CASE WHEN (x.Id &lt;&gt; OriginationAdmin.Brokers.Id) THEN 1 END - Incorrect syntax near the keyword 'AS'. RequestError: Incorrect syntax near the keyword 'AS'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-30
相关资源
最近更新 更多