【问题标题】:How to optimize this huge and ugly query, ignoring duplicates?如何优化这个巨大而丑陋的查询,忽略重复?
【发布时间】:2011-05-19 15:43:38
【问题描述】:

我不是 SQL 专家,这是我对表“Query”(键:SystemId、TopicId、DocumentId,也是外键)的 SQLite 查询,它获取外键并插入避免重复。但它又大又丑,我必须执行数千次:

command.CommandText = "INSERT INTO Query (SystemId, TopicId, DocumentId) " +
  "(SELECT Id FROM System WHERE Tag = @SystemTag COLLATE NOCASE), " +
  "(SELECT Id FROM Topic WHERE Number = @TopicNumber COLLATE NOCASE), " +
  "(SELECT Id FROM Document WHERE Number = @DocNumber COLLATE NOCASE) " +
  "WHERE NOT EXISTS (SELECT 1 FROM Query WHERE " +
    "SystemId = (SELECT Id FROM System WHERE Tag = @SystemTag) AND " +
    "TopicId = (SELECT 1 FROM Topic WHERE Number = @TopicNumber) AND " +
    "DocumentId = (SELECT Id FROM Document WHERE Number = @DocNumber))";

问题:任何方式告诉 sql“不要担心重复,忽略插入语句”。或者可能使用变量/临时表、AD 语句?

编辑:直接查询:

INSERT INTO Query (SystemId, TopicId, DocumentId)
  (SELECT Id FROM System WHERE Tag = @SystemTag COLLATE NOCASE),
  (SELECT Id FROM Topic WHERE Number = @TopicNumber COLLATE NOCASE),
  (SELECT Id FROM Document WHERE Number = @DocNumber COLLATE NOCASE)
  WHERE NOT EXISTS (SELECT 1 FROM Query WHERE 
    SystemId = (SELECT Id FROM System WHERE Tag = @SystemTag) AND
    TopicId = (SELECT 1 FROM Topic WHERE Number = @TopicNumber) AND
    DocumentId = (SELECT Id FROM Document WHERE Number = @DocNumber));

【问题讨论】:

    标签: sql sqlite optimization duplicates


    【解决方案1】:

    为了防止插入重复,你需要做两件事:

    一个表定义,用于标识需要唯一的列。例如:

    CREATE TABLE Query (
     SystemId INTEGER, 
     TopicId INTEGER,
     DocumentId INTEGER,
     PRIMARY KEY (SystemId, TopicId, DocumentId));
    

    CREATE TABLE Query (
     SystemId INTEGER, 
     TopicId INTEGER,
     DocumentId INTEGER,
     PRIMARY KEY (SystemId, TopicId, DocumentId));
    

    还有一个conflict clause。您可以通过以下两种方式之一执行此操作,或者在您的表定义中(保持它像上面那样将使其默认为 IGNORE,这几乎是您想要的),或者在您的插入命令中:

    INSERT OR IGNORE INTO Query...
    

    如果你的表设置带有 UNIQUE 约束,你真的不需要更改你的 INSERT 查询(除了删除公认的丑陋的WHERE NOT EXISTS 位。

    缺点是,是的,它会使您的代码尝试各种插入并失败。但换个角度看:它使您的数据库按照您希望的方式运行。这是使用数据库的关键,您不希望在执行操作时必须对所有表进行完全手动扫描。你想让数据库做脏活。

    【讨论】:

      【解决方案2】:

      我不知道您如何在 SQL Lite 中执行此操作(如果存在任何特定于平台的语法问题),但删除重复项的常用方法是使用 GROUP BY。

      W3Schools 有一个很好的通用 SQL 示例:

      http://www.w3schools.com/sql/sql_groupby.asp

      另一个选项是 DISTINCT,但在大型数据集中可能会出现问题。

      最后,作为一项观察,您可能希望研究使用 JOIN 而不是嵌套的 SELECT。

      http://www.w3schools.com/sql/sql_join.asp

      【讨论】:

      • 在不存在的地方插入,为什么 GROUP BY 应该是相关的?
      • 我想我应该更清楚一点,使用连接时避免重复的常用方法是按定义相等的属性进行分组,然后选择前 1 条记录。当您进行嵌套选择时,它在您粘贴的场景中不起作用。
      【解决方案3】:

      关于忽略重复的问题,您需要调查 DISTINCT

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-17
        • 2012-12-22
        相关资源
        最近更新 更多