Помогите найти ошибку в запросе с JOIN LEFT

grey109

Новичок
Помогите найти ошибку в запросе с JOIN LEFT

Задача: есть список урлов, нужно по ним кликать через прокси раз, например, в 24 часа. После того как прокси использован для одного урла он станивится неактивным на какое-то время, в тоже время для другого урла он активный. Для того, чтобы получить список активных прокси есть 3 условия:
1. прокси еще не использовался
2. прокси использовался для данного урла более чем 24 часа назад
3. прокси использовался для другого урла не важно когда

У меня есть этого есть 3 таблицы:

create table proxy (
id_proxy int(8) not null auto_increment primary key,
proxy text not null
);

create table url (
id_url int(8) not null auto_increment primary key,
url text not null
;

create table stat (
id_stat int(8) not null auto_increment primary key,
id_url int(8) not null,
time datetime not null,
id_proxy int(8) not null
);

Я над запросом бьюсь уже несколько дней. Вот мой вариант, который работает не совсем правильно:

SELECT proxy.id_proxy, proxy.proxy FROM proxy LEFT JOIN stat ON proxy.id_proxy=stat.id_proxy
LEFT JOIN url ON stat.id_url=url.id_url WHERE
(
stat.id_proxy IS NULL // условие №1
OR
((UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(stat.time)-(24*60*60))>0) and proxy.id_proxy=stat.id_proxy and stat.id_url='1' // условие №2
OR
(proxy.id_proxy=stat.id_proxy and stat.id_url!='1') // условие №3, вот внем кажется и ошибка
)


Помогите, плз, найти ошибку.
 

grey109

Новичок
Ну почему сразу накрутчик? Скприт будет использоваться для "мирных" целей.
 

zap

Guest
...
OR
(proxy.id_proxy=stat.id_proxy and stat.id_url<>'1') // условие №3, вот внем кажется и ошибка
)
...
 

[sid]

Новичок
Насколько я понимаю, надо получить список проксей активных по данным правилам для какого-то УРЛ'а...

Я бы решил эту задачу так.

SELECT
proxy.*
FROM
proxy
LEFT JOIN
stat
ON
stat.id_proxy = proxy.id_proxy
LEFT JOIN
url.id_url = stat.id_url
WHERE
url.id_url = '1' // ID проверяемого линка
AND (
proxy.id_proxy IS NULL
OR
UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(stat.time) > 86400
)
 

grey109

Новичок
[sid]
У тебя ошибка в запросе. Вот исправленный вариант:

SELECT proxy.* FROM proxy
LEFT JOIN stat ON stat.id_proxy = proxy.id_proxy
LEFT JOIN url ON url.id_url = stat.id_url
WHERE
url.id_url = '1' AND
(proxy.id_proxy IS NULL
OR
(UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(stat.time) > 86400))

Он всегда возващает 0.
 

grey109

Новичок
[sid]
Конечно. Могу дать дам таблицы, чтоб ты сам мог выполнить запрос.
 

grey109

Новичок
[sid]

DROP TABLE IF EXISTS proxy;
DROP TABLE IF EXISTS url;
DROP TABLE IF EXISTS stat;

create table proxy (
id_proxy int(8) not null auto_increment primary key,
proxy text not null
);

INSERT INTO proxy VALUES ('', '1.2.3.4:8080');
INSERT INTO proxy VALUES ('', '5.6.7.8:8080');

create table url (
id_url int(8) not null auto_increment primary key,
url text not null
);

INSERT INTO url VALUES ('', 'http://111.222');
INSERT INTO url VALUES ('', 'http://333.444');


create table stat (
id_stat int(8) not null auto_increment primary key,
id_url int(8) not null,
time datetime not null,
id_proxy int(8) not null
);

INSERT INTO `stat` VALUES (1, 1, NOW(), 1);
INSERT INTO `stat` VALUES (2, 1, NOW(), 2);
INSERT INTO `stat` VALUES (3, 2, NOW(), 1);


В результате запроса по ИД = 1, должен быть возвращно 0 прокси, по ИД = 2 - 1 прокси (5.6.7.8:8080).
 

[sid]

Новичок
Оказалось, что LEFT JOIN тут не при чем :)

Одним запросом тут не обойтись. Надо сначало вычислить id-шники неактивных проксей!
SELECT id_proxy FROM stat WHERE id_url = 2 AND NOW()-time<240000

А затем выбрать все прокси, кроме неактивных

SELECT * FROM proxy WHERE id_proxy NOT IN( /* RECORD SET предыдущего запроса */ )

Если MySQL/4.1 и выше то можно сделать все это за один запрос с помощью subQuery
SELECT * FROM proxy WHERE id_proxy NOT IN (SELECT id_proxy FROM stat WHERE id_url = 2 AND NOW()-time<240000)

Если четверка нулевая или тройка, все равно можно за один сеанс решить задачу, пусть не так красиво, но все таки.
Создаешь в памяти временную таблицу. Вставляешь в нее промежуточный рекордсет.
А затем объединяешь ее с таблицей проксей RIGHT JOIN'ом (или в обратном порядке LEFT JOIN'ом) и делаешь горизонтальный фильтр по temp_table.id_proxy IS NULL

Итого...

CREATE TEMPORARY TABLE temp_table(
`id_proxy` int(8) NOT NULL
) TYPE=HEAP;

INSERT INTO temp_table (id_proxy) SELECT id_proxy FROM stat WHERE id_url = 2 AND NOW()-time<240000;

SELECT proxy.*
FROM
proxy
LEFT JOIN
temp_table USING(id_proxy)
WHERE
temp_table.id_proxy IS NULL;
 

grey109

Новичок
[sid]
Спасибо, за ответ. У меня MySQL 3.x, так что для меня подходит последний вариант.

Только с ним такая непонятность: вставляют твой запрос в phpmyadmin - работает все как надо, делаю запрос в скрипте:

$sql = "
CREATE TEMPORARY TABLE ... = HEAP;
INSERT INTO temp_table ... time<240000;
SELECT ... temp_table.id_proxy IS NULL;
";

mysql_query($sql) or die(mysql_error());

Получаю "You have an error in your SQL syntax near ';".

Что может быть не так?
 

[sid]

Новичок
Дело в том, что интерфейс mysql'а в PHP не может выполнять несколько запросов за один вызов функции mysql_query. Разбей это дело на три вызова и все будет в порядке!
 
Сверху