2014-02-12 7 views
0

У меня есть следующий запрос mySQL, который возвращает список идентификаторов. Я хочу, чтобы удалить строки с каждым идентификатором списка из таблицы «serverking_user»SQL: Удалить по результату Select with Join

SELECT serverking_user.id FROM (serverking_user 
INNER JOIN serverking_logins 
ON serverking_user.id=serverking_logins.uid) 
WHERE serverking_logins.time < 3600 
GROUP BY serverking_user.id 
HAVING COUNT(serverking_logins.login) = 1 

Одним из возможных вариантов будут Переберите каждый идентификатор с помощью «в». Но поскольку «in» деактивирован на моем сервере Sql, мне нужно решить это с помощью «join».

Любые идеи?

ответ

1
DELETE FROM serverking_user 
WHERE EXISTS 
(SELECT * 
FROM (serverking_user 
INNER JOIN serverking_logins 
ON serverking_user.id=serverking_logins.uid) 
WHERE serverking_logins.time < 3600 
GROUP BY serverking_user.id 
HAVING COUNT(serverking_logins.login) = 1) a 
+0

# 1093 - Вы не можете указать целевую таблицу 'serverking_logins' для обновления в предложении FROM. – user1474444

+0

Извините, у меня была опечатка, которая не соответствовала вашим именам таблиц. Повторите попытку, дважды проверяя правильность имен таблиц. – Sev09

+0

thx, но все же: # 1093 - Вы не можете указать целевую таблицу 'serverking_user' для обновления в предложении FROM – user1474444

2

Это было некоторое время, так как я сделал развитие MySQL, но если я правильно помню, это должно работать для вас:

DELETE su 
FROM serverking_user su 
INNER JOIN serverking_logins sl 
ON su.id=sl.uid 
WHERE sl.time < 3600 
GROUP BY su.id 
HAVING COUNT(sl.login) = 1 

В общем, если вы хотите удалить записи из одной таблицы в JOIN, вы просто указать, что таблица (или его псевдоним) после DELETE

Обновлено QUERY
кажется, что MySQL не любит удалять, где сгруппированы Quer y, так что другая возможность - использовать анти-соединение. Тем не менее, я уверен, что характеристики производительности этого запроса будут субоптимальными. Возможно, лучше использовать два отдельных запроса. Тем не менее, здесь есть решение с использованием анти-соединяет:

DELETE su 
FROM serverking_user su 
INNER JOIN serverking_logins sl 
ON su.id=sl.uid 
LEFT JOIN serverking_logins antisl 
ON sl.uid = antisl.uid 
AND sl.id <> antisl.id 
WHERE sl.time < 3600 
AND antisl.id IS NULL 
+0

# 1064 - У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с «GROUP BY su.id HAVING COUNT (sl.login) = 1» в строке 6 – user1474444

+0

Вы можете использовать анти-соединение, но я не уверен если это будет работать лучше, чем два отдельных запроса, как описано в ответе @ Luaan ниже. –

+0

и как это будет выглядеть? – user1474444

1

Может быть, вы могли бы хранить результаты выбора внутри табличной переменной, а затем присоединиться к этим?

declare @Ids table 
(
    Id int 
); 

insert into @Ids (Id) 
SELECT serverking_user.id FROM (serverking_user 
INNER JOIN serverking_logins 
ON serverking_user.id=serverking_logins.uid) 
WHERE serverking_logins.time < 3600 
GROUP BY serverking_user.id 
HAVING COUNT(serverking_logins.login) = 1; 

delete yt from YourTable yt 
inner join @Ids Ids on Ids.Id = yt.id; 

Обратите внимание, что согласованность этого зависит от конфигурации транзакции, так как вы делаете здесь два отдельных запроса.

+0

Хм, должно быть более эффективное решение:/ – user1474444

+0

@ user1474444 О, я только заметил, что вы просите решение MySQL. Неужели это так медленно? – Luaan

+0

Я не знаю, как это будет медленным, но для меня это выглядит немного сложно, так как я не очень хорош в sql ... – user1474444