SQL: выберите ключи, которых нет в одной таблице - PullRequest
12 голосов
/ 18 июля 2011

Я получил таблицу с нормальной настройкой авто вкл.Идентификаторы.Некоторые строки были удалены, поэтому список идентификаторов может выглядеть примерно так:

(1, 2, 3, 5, 8, ...)

Затем из другого источника ( Редактировать: другой источник = НЕ в базе данных ) У меня есть этот массив:

(1, 3, 4, 5, 7, 8)

Я ищу запрос, который могу использовать в базе данных, чтобы получить список идентификаторов: НЕ в таблице из имеющегося у меня массива.Что будет:

(4, 7)

Существует ли такое?Мое решение сейчас - либо создать временную таблицу, чтобы команда «WHERE table.id IS NULL» работала, либо, возможно, хуже, используя PHP-функцию array_diff, чтобы увидеть, чего не хватает после получения всех идентификаторов из таблицы.

Поскольку список идентификаторов приближается к миллионам или строкам, я стремлюсь найти лучшее решение.

Спасибо!/ Thomas

Редактировать 2:

Моё основное приложение - довольно простая таблица, которая заполнена множеством строк.Это приложение администрируется с помощью браузера, и я использую PHP в качестве интерпретатора кода.

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

Проблема в том, что моя система не может быть на 100% уверена, что пользователь все сделал правильно, когда он/ она нажала клавишу «экспорт».Или, что в другой системе никогда не было создано ни одной строки.

Из другой системы я могу получить CSV-файл, где есть все строки, которые есть в этой системе.Таким образом, сравнивая файл CSV и мою таблицу, я могу увидеть, если: * В другой системе отсутствуют какие-либо строки, которые должны были быть импортированы * Если кто-то создал строки в другой системе

Проблема не в 'т "решение".Это лучшее решение, так как в строках столько данных.

Еще раз спасибо!

/ Thomas

Ответы [ 6 ]

20 голосов
/ 18 июля 2011

Мы можем использовать MYSQL без опции.

SELECT id
FROM table_one
WHERE id NOT IN ( SELECT id FROM table_two )

Отредактировано

Если вы получаете источник из файла CSV , тогда вы можете просто поместить эти значения непосредственно как:

Я предполагаю, что CSV похожи на 1,2,3, ..., n

SELECT id
FROM table_one
WHERE id NOT IN ( 1,2,3,...,n );

РЕДАКТИРОВАТЬ 2

Или Если вы хотите выбрать другой способ, вы можете использовать mysqlimport для импорта данных во временную таблицу в базе данных MySQL, а также для получения результата и удаления таблицы.

Как:

Создать таблицу

CREATE TABLE my_temp_table(
   ids INT,
);

загрузить файл .csv

LOAD DATA LOCAL INFILE 'yourIDs.csv' INTO TABLE my_temp_table
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(ids);

Выбор записей

SELECT ids FROM my_temp_table
WHERE ids NOT IN ( SELECT id FROM table_one )

перетаскиваемая таблица

DROP TABLE IF EXISTS my_temp_table
1 голос
/ 18 июля 2011

Как насчет использования left join;что-то вроде этого:

select second_table.id
from second_table
    left join first_table on first_table.id = second_table.id
where first_table.is is null


Вы также можете перейти с подзапросом;в зависимости от ситуации, он может или не может быть быстрее, хотя:

select second_table.id
from second_table
where second_table.id not in (
    select first_table.id
    from first_table
)

или с not exists:

select second_table.id
from second_table
where not exists (
    select 1
    from first_table
    where first_table.id = second_table.id
)
0 голосов
/ 24 октября 2013

У меня та же проблема: у меня есть список значений от пользователя, и я хочу найти подмножество, которое не существует в другой таблице.Я сделал это в oracle, построив псевдотаблица в операторе select. Вот способ сделать это в Oracle.Попробуйте это в MySQL без "from dual":

-- find ids from user (1,2,3) that *don't* exist in my person table
-- build a pseudo table and join it with my person table
select pseudo.id from (
  select '1' as id from dual
  union select '2' as id from dual
  union select '3' as id from dual
) pseudo
left join person
  on person.person_id = pseudo.id
where person.person_id is null
0 голосов
/ 18 июля 2011

ОК, я прочитал ваши правки / разработки.Синхронизация двух баз данных, где вторая не должна вставлять какие-либо новые строки, , но может сделать это , звучит как проблема, ожидающая своего появления.

Ни один из предложенных выше подходов (ГДЕ НЕ СУЩЕСТВУЕТ или СЛЕДУЕТ ПОДКЛЮЧИТЬСЯ) не является герметичным и ни один из способов не гарантирует логическую целостность между двумя системами.Они не сообщат вам, какая система создала строку в ситуациях, когда обе таблицы содержат строку с одинаковым идентификатором.Сейчас вы сосредотачиваетесь на пробелах, но другая проблема - дублирующиеся идентификаторы.

Например, если в обеих таблицах есть строка с идентификатором 13887, вы не можете предполагать, что база данных1 создала строку.Он мог быть вставлен в базу данных 2, а затем база данных 1 могла бы вставить новую строку, используя тот же идентификатор.Вы должны сравнить все значения столбцов, чтобы убедиться, что строки одинаковы или нет.

Поэтому я бы посоветовал вам также изучить GUID в качестве замены целых автоинкрементов.Вы не можете запретить database2 вставлять строки, но, по крайней мере, с GUID вы не столкнетесь с проблемой, когда вторая база данных вставила строку и присвоила ей значение первичного ключа, которое также может использовать ваша первая база данных, что приведет к двум различным строкам стот же идентификатор.Также могут быть полезны столбцы CreationDateTime и LastUpdateDateTime.

Однако правильное решение, если оно доступно вам, - это поддерживать только одну базу данных и предоставлять пользователям удаленный доступ к ней, например, через веб-интерфейс.Это устранило бы беспорядок и усложнение проблем репликации / синхронизации.

Если веб-интерфейс удаленного доступа невозможен, возможно, вы могли бы сделать одну из баз данных доступной только для чтения?Или database2 должен обновлять строки?Возможно, вы могли бы отказать в праве на вставку?Какой движок базы данных вы используете?

0 голосов
/ 18 июля 2011

Проблема в том, что T1 может иметь миллион строк или десять миллионов строк, и это число может измениться, поэтому вы не знаете, сколько строк должна иметь ваша таблица сравнения, T2, которая не имеет пробелов, для выполнение теста WHERE NOT EXIST или LEFT JOIN для NULL.

Но вопрос в том, почему вас волнует отсутствие пропущенных значений? Я утверждаю, что , когда приложение правильно спроектировано , не должно иметь значения, есть ли пробелы в автоинкрементной последовательности клавиш. Даже приложение, в котором пробелы имеют значение, например чековый регистр, не должно использовать первичный ключ с автоматическим включением в качестве синонима чекового номера.

Хотите уточнить детали вашего заявления?

0 голосов
/ 18 июля 2011

Функция, которую вы ищете, НЕ ВХОДИТ (псевдоним <> ALL)

Документация по MYSQL:

http://dev.mysql.com/doc/refman/5.0/en/all-subqueries.html

Пример его использования:

http://www.roseindia.net/sql/mysql-example/not-in.shtml

Наслаждайтесь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...