#mysql
Вопрос:
У меня есть две таблицы, в одной из которых содержатся потенциальные элементы, в другой-завершенные элементы.
Таблица потенциальных товаров в настоящее время содержит записи, которые также были добавлены в таблицу завершенных товаров. Я хочу удалить (либо удалив, либо выбрав новые результаты) уже завершенные элементы из списка потенциальных элементов.
В обеих таблицах элементы могут появляться несколько раз, и я хочу удалить только количество завершенных элементов, а не все, которые совпадают.
Реальный набор данных, конечно, больше, но вот примеры.
Потенциальные предметы:
mysqlgt; select * from stack; ---------- ------ ------ | stack_id | type | name | ---------- ------ ------ | 3 | a | aa | | 4 | b | bb | | 5 | c | cc | | 6 | d | dd | | 7 | a | aa | | 8 | b | bb | ---------- ------ ------ 6 rows in set (0.00 sec)
Завершенные пункты
mysqlgt; select * from temp; ---------- ------ ------ | item_id | type | name | ---------- ------ ------ | 1 | a | aa | | 2 | b | bb | | 6 | b | bb | ---------- ------ ------ 3 rows in set (0.00 sec)
Идентификаторы между таблицами не коррелируют, поэтому их следует игнорировать при поиске совпадений.
Я хочу опустить 1 экземпляр a/aa и 2 экземпляра b/bb, так как они были заполнены и существуют в другой таблице.
когда я попробую это:
mysqlgt; select stack.* from stack where (type,name) not in (select type,name from temp);
Я понимаю это:
---------- ------ ------ | stack_id | type | name | ---------- ------ ------ | 5 | c | cc | | 6 | d | dd | ---------- ------ ------ 2 rows in set (0.03 sec)
Но при этом были опущены оба экземпляра type=»a» и name=»aa», и я хочу опустить только один из них (поскольку он существует только один раз в таблице завершенных элементов).
Как мне это получить?
---------- ------ ------ | stack_id | type | name | ---------- ------ ------ | 5 | c | cc | | 6 | d | dd | | 7 | a | aa | ---------- ------ ------
Мне все равно, какой экземпляр a/aa будет удален (будь то id=7 или id=3)
Лучшее, что я смог придумать, — это использовать PHP, а не MySQL, чтобы перебирать каждую запись в temp и удалять с ОГРАНИЧЕНИЕМ 1 из стека.
Но я бы предпочел не запускать код для этого, я бы хотел делать это в запросах, так лучше работает в моем рабочем процессе
Спасибо!
Комментарии:
1. Ваш вопрос не совсем ясен. Вы ищете запрос для включения или исключения элементов из одного списка, если они появляются в другом списке?
2. Я хотел бы либо запросить удаление повторяющихся строк, либо выбрать не повторяющиеся строки. Мое текущее решение состоит в том, чтобы использовать php для генерации набора запросов «удалить из…. ограничение 1».
3. Вы ищете первое появление [‘a’, ‘aa’] в списке стеков, тогда вы можете использовать
select min(stack_id), type, name from stack group by type, name
илиselect min(stack_id), s.type, s.name from stack s inner join temp using (type, name) group by s.type, s.name
таким образом объединить две таблицы.
Ответ №1:
CREATE TABLE `test`.`stack` ( `stack_id` INT UNSIGNED NOT NULL, `type` VARCHAR(45) NULL, `name` VARCHAR(45) NULL, PRIMARY KEY (`stack_id`)); CREATE TABLE `test`.`temp` ( `item_id` INT UNSIGNED NOT NULL, `type` VARCHAR(45) NULL, `name` VARCHAR(45) NULL, PRIMARY KEY (`item_id`));
и чем-то вроде этого:
select min(stack_id), type, name from stack _s inner join ( select min(item_id) item_id, type, name from temp group by type, name ) _t using(type, name) group by _s.type, _s.name
даст вам только один первый пункт в temp:
stack_id | Тип | Имя |
---|---|---|
3 | a | aa |
4 | b | бб |