2

我有一张桌子eng-jap,它基本上只是一个翻译,所以有一个英文和一个日文专栏。我制作的一个脚本以某种方式导致每个插入都有一个克隆,因此该表中有 1000 个重复条目,例如:

重复示例 A

eng                        jap
"mother washes every day"  "母は毎日洗濯する"
"mother washes every day"  "母は毎日洗濯する"

如果它只是一列,我可以使用查询:

SELECT eng, COUNT(*) c FROM `eng-jap` GROUP BY eng HAVING c > 1

但是由于该表可以合法地在 eng 或 jap 中具有重复项,只要它不在两者中即可。例如:

重复示例 B

eng                        jap
"mother washes every day"  "母は毎日洗濯する"
"every day mother washes"  "母は毎日洗濯する"

这是为了让一个句子有多个翻译。所以我需要更改查询以查找重复项作为两列的组合我猜你可以说。

再次明确。示例 B 很好,我想选择示例 A 之类的所有重复项,以便我可以制作一个脚本来删除所有重复项之一。谢谢,麻烦您了!

4

3 回答 3

2

我认为您只需要按 eng 和 jap 分组:

SELECT eng, jap, COUNT(*) c FROM `eng-jap` GROUP BY eng, jap HAVING c > 1

如果您想删除所有重复项,如果您的行有id,则此查询会显示您必须保留的所有 id:

select
  SUBSTRING_INDEX(GROUP_CONCAT(CAST(id AS CHAR) order by id), ',', 1) as id
from `eng-jap`
group by eng, jap

(这是一种GROUP_CONCAT用于查找每个组合的第一个 id 的技巧eng/jap)。此查询显示您必须删除的行的 ID:

select id
from
  `eng-jap`
     left join
  (select
     SUBSTRING_INDEX(GROUP_CONCAT(CAST(id AS CHAR) order by id), ',', 1) as id
     from `eng-jap`
     group by eng, jap) `eng-jap-dup`
  on `eng-jap`.id = `eng-jap-dup`.id
where `eng-jap-dup`.id is null

我只使用 join 重写了这个查询,它必须快一点,但如果你的表太大,它可能仍然很慢。

如果它仍然太慢并且仍然无法正常工作,我建议您在表格中再添加两列:

  • eng-hash, 你可以在哪里保存MD5(eng)
  • jap-hash, 你可以在哪里保存MD5(jap)

然后像这样更新您的所有记录:

update `eng-jap` set `eng-jap`.`eng-hash` = MD5(eng), `eng-jap`.`jap-hash` = MD5(jap)

然后您可以在两列的表上添加唯一索引,忽略所有错误,并让 MySql 为您完成消除重复的工作:

alter ignore table `eng-jap` add unique index (eng-hash, jap-hash);

(如果您在创建索引时遇到错误,请参阅以下问题:MySQL: ALTER IGNORE TABLE Gives "Integrity constraint violation"

于 2012-11-11T08:35:18.367 回答
1

您可以临时添加一列,您只需在其中连接两个当前列的值。然后,您按该列对查询进行分组并消除匹配的行。之后,您再次删除该列。

当然,查询本身也可以这样做,只需按包含两个物理列连接的合成结果列进行分组。

于 2012-11-11T07:58:31.080 回答
0

我不确定你是否已经在这里得到了答案。我也不确定您是否尝试仅读取重复的行,或者您想要一个没有重复的结果集。这完全取决于您对副本的定义是什么。

1)假设你只需要重复的行(正如你的标题所说):

a)如果在示例 A 中有重复项,而在示例 B 中没有重复项,则只需:

SELECT eng, COUNT(*) c FROM `eng-jap` GROUP BY eng, jap HAVING c > 1

b)如果即使在示例 B 中也发现重复项(因为 jap 部分相同),则:

SELECT   * 
FROM     (
          SELECT   * 
          FROM     (
                    SELECT   * 
                    FROM     `eng-jap` 
                    GROUP BY eng 
                    HAVING   COUNT(*) > 1

                    UNION ALL

                    SELECT   * 
                    FROM     `eng-jap` 
                    GROUP BY jap 
                    HAVING   COUNT(*) > 1
                   ) AS t
          GROUP BY eng
             ) AS v
GROUP BY jap

2)如果您正在查看没有重复行的记录(因为您在最后说i want to select all duplicates like example A so i can make a scrip to remove one of all of the duplicates):

a)如果在示例 A 中有重复项,而在示例 B 中没有重复项,则只需:

SELECT eng, COUNT(*) c FROM `eng-jap` GROUP BY eng, jap

b)如果即使在示例 B 中也发现重复项(因为 jap 部分相同),则:

SELECT   * 
FROM     (SELECT c.eng, c.jap FROM `eng-jap` c GROUP BY c.eng) t 
GROUP BY t.jap
于 2012-11-11T15:17:56.110 回答