Как оптимизировать этот огромный и безобразный запрос, игнорируя дубликаты? - PullRequest
1 голос
/ 03 декабря 2010

Я не эксперт по SQL, вот мой SQLite-запрос к таблице «Запрос» (ключ: SystemId, TopicId, DocumentId, все также внешние ключи), который получает внешние ключи и вставляет, избегая дубликатов.Но это огромно, безобразно, и я должен выполнить его тысячи раз:

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?

EDIT: прямой запрос:

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));

Ответы [ 3 ]

1 голос
/ 05 декабря 2010

Чтобы предотвратить вставку дубликата, вам нужно две вещи:

Определение таблицы, которая определяет столбцы как уникальные. Например:

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));

И конфликтное предложение . Вы можете сделать это одним из двух способов, либо в своем определении таблицы (оставив его, как указано выше, по умолчанию установите значение IGNORE, что вам очень нужно), либо в вашей команде вставки:

INSERT OR IGNORE INTO Query...

Если вы настроили таблицу с ограничением UNIQUE, вам действительно не нужно изменять запрос INSERT (кроме удаления заведомо некрасивого WHERE NOT EXISTS бита.

Недостаток в том, что да, он заставляет ваш код пытаться выполнить всевозможные вставки и завершиться неудачно. Но посмотрите на это по-другому: ваша база данных будет вести себя так, как вы хотите. И это ключ к работе с базами данных, вам не нужно выполнять полное сканирование всех таблиц вручную, когда вы выполняете операцию. Вы хотите, чтобы база данных сделала грязную работу.

0 голосов
/ 03 декабря 2010

Я не знаю, как вы это делаете в 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

0 голосов
/ 03 декабря 2010

В вашем вопросе о игнорировании дубликатов вам нужно исследовать DISTINCT

...