я тебя понял, не вопрос :)
|
Gozar, довольно предсказуемо рано или поздно сесть в лужу если говорить о вещах которые не понимаешь.
Программирование - это инженерная профессия к которой надо относиться с уважением, потому что если без уважения так: Цитата:
Цитата:
Случай конечно зачетный, годами мне хватит его приводить в пример квалификации так называемых "специалистов". А данное простое задание запишу себе - если придется проводить собеседование с кем то - будет на почетном втором месте из заданий. Насчет обоюдного уважения(к профессии раньше) это касается также и всего остального - отношений между людьми например: Сам то ты форум переполнил своей критикой, начиная от содержания английских слов в чужих сообщения и выпадами типа "да неужели?!", а когда тебе задали конкретные критические вопросы, не имея ответа, ты способен только на: Цитата:
x-yuri, ну что показываешь как сделал? Больше никто не интересуется все равно. |
Цитата:
|
Вот еще вариант, уже без подзапроса:
Код:
SELECT u.idu, b.idu , b.idb |
удалено.
|
[offtop]
Опа опа. попкорн всегда при мне. [/offtop] |
мой вариант:
в двух словах: идея заключается в том, чтобы помещать в таблицу банов 2 строки на каждую связь (два направления), тогда drop table if exists users_2; create table users_2 ( id int primary key ); insert into users_2 values (1), (2), (3), (4), (5), (6); drop table if exists banned_3; create table banned_3 ( user_1_id int, user_2_id int, origin enum('1', '2'), primary key(user_1_id, user_2_id) ); insert into banned_3 values (2, 3, '1'), (3, 2, '2'), (1, 3, '1'), (3, 1, '2'), (3, 4, '1'), (4, 3, '2'), (3, 5, '1'), (5, 3, '2'); SELECT u.* FROM users_2 u LEFT JOIN banned_3 f ON u.id = f.user_1_id && f.user_2_id = 3 WHERE f.user_1_id IS NULL && u.id != 3 ORDER BY RAND() LIMIT 1; |
x-yuri, ну ты немного подогнал структуру базы, чтобы выполнить легко этот запрос(соединиться с одним полем второй таблицы). Дублирование информации все таки есть. Тут может оно и не критично, но например программировать операцию "Пользователь разбанивает всех своих забаненных" одним запросом не пройдет.
Цитата:
Почитай подпись у B~Vladi Цитата:
Еще и минусанул смельчак. Правда глаза режет? Ребенок отомстил . :D . А на мои вопросы ответов так и нет у тебя. Это просто пипец. Мне тебя жаль. Идешь в игнор. |
а теперь давайте сравним
создание таблиц: -- users_2 drop table if exists users_2; create table users_2 ( id int primary key ); insert into users_2 values (1), (2), (3), (4), (5), (6); -- banned_2 drop table if exists banned_2; create table banned_2 ( idu int, idb int, primary key(idu, idb) ); insert into banned_2 values (2, 3), (1, 3), (3, 4), (3, 5); -- banned_3 drop table if exists banned_3; create table banned_3 ( user_1_id int, user_2_id int, origin enum('1', '2'), primary key(user_1_id, user_2_id) ); insert into banned_3 values (2, 3, '1'), (3, 2, '2'), (1, 3, '1'), (3, 1, '2'), (3, 4, '1'), (4, 3, '2'), (3, 5, '1'), (5, 3, '2'); explain: EXPLAIN SELECT u.* FROM users_2 u LEFT JOIN banned_3 f ON u.id = f.user_1_id && f.user_2_id = 3 WHERE f.user_1_id IS NULL && u.id != 3 ORDER BY RAND() LIMIT 1; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: u type: index possible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 6 Extra: Using index; Using temporary; Using filesort *************************** 2. row *************************** id: 1 select_type: SIMPLE table: f type: eq_ref possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: u.id,const rows: 1 Extra: Using where; Using index; Not exists EXPLAIN SELECT u.id FROM users_2 u WHERE u.id != 3 AND u.id NOT IN ( SELECT IF(b.idu = 3, b.idb, b.idu) FROM banned_2 b WHERE b.idu = 3 OR b.idb = 3 ) ORDER BY RAND() LIMIT 1; *************************** 1. row *************************** id: 1 select_type: PRIMARY table: u type: index possible_keys: PRIMARY key: PRIMARY key_len: 4 ref: NULL rows: 6 Extra: Using where; Using index; Using temporary; Using filesort *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: b type: index possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 3 Extra: Using where; Using index EXPLAIN SELECT id FROM users_2 U WHERE ISNULL((SELECT id FROM banned_2 WHERE idu=3 && idb=U.id || idb=3 && idu=U.id )) ORDER BY RAND() LIMIT 1; *************************** 1. row *************************** id: 1 select_type: PRIMARY table: U type: index possible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 6 Extra: Using where; Using index; Using temporary; Using filesort *************************** 2. row *************************** id: 2 select_type: DEPENDENT SUBQUERY table: banned_2 type: index possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 3 Extra: Using where; Using index EXPLAIN SELECT u.id, b.idu , b.idb FROM users_2 u LEFT JOIN banned_2 b ON ((b.idu = 3 OR b.idb = 3) AND (u.id = b.idu OR u.id = b.idb)) WHERE ( (b.idu IS NULL) AND (b.idb IS NULL)) ORDER BY RAND() LIMIT 1; *************************** 1. row *************************** id: 1 select_type: SIMPLE table: u type: index possible_keys: NULL key: PRIMARY key_len: 4 ref: NULL rows: 6 Extra: Using index; Using temporary; Using filesort *************************** 2. row *************************** id: 1 select_type: SIMPLE table: b type: index possible_keys: PRIMARY key: PRIMARY key_len: 8 ref: NULL rows: 3 Extra: Using where; Using index; Not exists запуск на более-менее реальных данных: mysql> SELECT u.* -> FROM users_2 u -> LEFT JOIN filters_2 f ON u.id = f.user_1_id && f.user_2_id = 5 -> WHERE f.user_1_id IS NULL && u.id != 5 -> ORDER BY RAND() -> LIMIT 1; +------+ | id | +------+ | 6569 | +------+ 1 row in set (0.28 sec) mysql> SELECT u.id -> FROM users u -> WHERE u.id != 5 -> AND u.id NOT IN -> ( -> SELECT IF(b.idu = 5, b.idb, b.idu) -> FROM banned b -> WHERE b.idu = 5 OR b.idb = 5 -> ) -> ORDER BY RAND() -> LIMIT 1; +-------+ | id | +-------+ | 25324 | +-------+ 1 row in set (1 min 56.50 sec) mysql> SELECT id -> FROM users_2 U -> WHERE -> ISNULL((SELECT id -> FROM banned_2 -> WHERE idu=5 && idb=U.id || idb=5 && idu=U.id -> )) -> ORDER BY RAND() -> LIMIT 1; +------+ | id | +------+ | 5419 | +------+ 1 row in set (1 min 56.53 sec) mysql> SELECT u.id, b.idu , b.idb -> FROM users_2 u -> LEFT JOIN banned b -> ON ((b.idu = 5 OR b.idb = 5) AND (u.id = b.idu OR u.id = b.idb)) -> WHERE ( (b.idu IS NULL) AND (b.idb IS NULL)) -> ORDER BY RAND() -> LIMIT 1; +------+------+------+ | id | idu | idb | +------+------+------+ | 9609 | NULL | NULL | +------+------+------+ 1 row in set (2 min 1.47 sec) |
интересно, кстати, micscr, что хоть твой подзапрос вроде никак не связан с внешним, но mysql его пометил как DEPENDENT SUBQUERY
Цитата:
Цитата:
и я не говорил, что нужно недопустить дублирования. Дублирование оно тоже разное бывает по поводу разбанивания: Код:
DELETE FROM banned_3 кстати, негативные последствия моего решения меня интересуют, ага :) |
Часовой пояс GMT +3, время: 23:08. |