Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Сложный запрос в MySQL
 
 автор: Progar   (03.04.2007 в 11:50)   письмо автору
 
 

Суть такая. Храню инфу о сайте в двух таблицах. В первой общую инфу по сайту, напр:

CREATE TABLE sponsorsite (
sponsorsiteID INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(64) NOT NULL,
url VARCHAR(128) NOT NULL
);

Во второй к каким категориям принадлежит сайт, ну напр итальянско-франзуские принадлежат и в категорию ITALIAN (8) и FRANCE (2):

CREATE TABLE categorysponsorsite (
categorysponsorsiteID INT PRIMARY KEY AUTO_INCREMENT,
sponsorsiteID INT NOT NULL,
categoryID INT NOT NULL
);

1) Пытаюсь выбрать сайты которые принадлжат вышеуказанным двум категориям, но выдает ноль результатов, вот запрос:

select sponsorsite.name, sponsorsite.url from sponsorsite, categorysponsorsite where (categorysponsorsite.categoryID=8 AND categorysponsorsite.categoryID=2) AND categorysponsorsite.sponsorsiteID=sponsorsite.sponsorsiteID;

А если оставить только одну категорию (напр categorysponsorsite.categoryID=2), то нормально выдает французские.

2) Пробовал использовать JOIN, что то не выходит, напр:

SELECT name, url FROM sponsorsite LEFT JOIN categorysponsorsite on sponsorsite.sponsorsiteID=categorysponsorsite.sponsorsiteID WHERE (categorysponsorsite.categoryID=8 AND categorysponsorsite.categoryID=2);

Получается как и предыдущий запрос.
--

Извиняюсь если натупил, давно не программил :)

   
 
 автор: Trianon   (03.04.2007 в 11:55)   письмо автору
 
   для: Progar   (03.04.2007 в 11:50)
 


select sponsorsite.name, sponsorsite.url 
 FROM  sponsorsite 
  JOIN  categorysponsorsite ON  categorysponsorsite.sponsorsiteID=sponsorsite.sponsorsiteID
 where (categorysponsorsite.categoryID=8 OR categorysponsorsite.categoryID=2);
  

либо


select sponsorsite.name, sponsorsite.url 
 FROM  sponsorsite 
 JOIN  categorysponsorsite ON  categorysponsorsite.sponsorsiteID=sponsorsite.sponsorsiteID
  where categorysponsorsite.categoryID IN(2,8);

   
 
 автор: Progar   (03.04.2007 в 12:14)   письмо автору
 
   для: Trianon   (03.04.2007 в 11:55)
 


select sponsorsite.name, sponsorsite.url 
 FROM  sponsorsite 
  JOIN  categorysponsorsite ON  categorysponsorsite.sponsorsiteID=sponsorsite.sponsorsiteID
 where (categorysponsorsite.categoryID=8 OR categorysponsorsite.categoryID=2); 


Дает ошибку

ERROR 1064 at line 3: You have an error in your SQL syntax near 'ON categoryspon
sorsite.sponsorsiteID=sponsorsite.sponsorsiteID where (categorysp' at line 1

и второй тоже



select sponsorsite.name, sponsorsite.url 
 FROM  sponsorsite 
 JOIN  categorysponsorsite ON  categorysponsorsite.sponsorsiteID=sponsorsite.sponsorsiteID
  where categorysponsorsite.categoryID IN(2,8); 


ERROR 1064 at line 2: You have an error in your SQL syntax near 'ON categoryspo
nsorsite.sponsorsiteID=sponsorsite.sponsorsiteID where categorysp' at line 1

А вообще OR вряд ли поможет, потому как мне нужно чтоб было франзуско-итальянский, а не француские И итальянские. Ну например фильм франзуско-итальянский же бывает.

   
 
 автор: Trianon   (03.04.2007 в 12:35)   письмо автору
 
   для: Progar   (03.04.2007 в 12:14)
 

У меня оба запроса проходят. Наверное, какая-то ошибка при копировании...

Теперь по сути.

То есть Вы хотите отобрать такие записи в sponsorsite которым в categorysponsorsite соответствуют сразу две строки?
Это, конечно, меняет дело.
Я бы предложил что-то такое

SELECT name,url FROM sponsorsite WHERE sponsorsiteID IN
(
  SELECT sponsorsiteID 
    FROM  categorysponsorsite  WHERE categoryID IN(2,8)
   GROUP BY sponsorsiteID 
   HAVING COUNT(categorysponsorsiteID) = 2
)

   
 
 автор: Progar   (03.04.2007 в 14:08)   письмо автору
 
   для: Trianon   (03.04.2007 в 12:35)
 


SELECT name,url FROM sponsorsite WHERE sponsorsiteID IN
(
  SELECT sponsorsiteID 
    FROM  categorysponsorsite  WHERE categoryID IN(2,8)
   GROUP BY sponsorsiteID 
   HAVING COUNT(categorysponsorsiteID) = 2



Спасибо.. хочется верить что работает, но пока не получается у меня, такую ошибку дает:

ERROR 1064: You have an error in your SQL syntax near 'SELECT sponsorsiteID
FROM categorysponsorsite WHERE categoryID IN(2,8)

Может где то надо поставить ";"? Я запускаю в командой строке.. а если через файл (mysql < file.sql) то не хочет, разрывы между строк как то неправильно интерпретирует :(

   
 
 автор: Trianon   (03.04.2007 в 14:27)   письмо автору
 
   для: Progar   (03.04.2007 в 14:08)
 

(пожав плечами)

Z:\usr\local\mysql5\bin>mysql.exe -u user -p
Enter password: *****
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 33 to server version: 5.0.18-max

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test
Database changed
mysql> select name,url from sponsorsite where sponsorsiteID IN
    -> (
    -> SELECT sponsorsiteID
    ->  FROM  categorysponsorsite  WHERE categoryID IN(2,8)
    ->    GROUP BY sponsorsiteID
    ->  HAVING COUNT(categorysponsorsiteID) = 2
    -> )
    -> ;
Empty set (0.00 sec)

mysql>



Точка-с-запятой - не часть SQL-запроса. Это признак конца оператора. При работе в MySQL её, конечно, нужно ставить....

   
 
 автор: Progar   (03.04.2007 в 14:40)   письмо автору
 
   для: Trianon   (03.04.2007 в 14:27)
 

Ду уж.. у меня по другому че то выходит :) Может версия mysql старая? Уж года 4 у меня лежит..


I:\Documents and Settings\user1>mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 42 to server version: 3.23.46-nt

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use store;
Database changed
mysql> select name,url from sponsorsite where sponsorsiteID IN
    ->   (
    ->   SELECT sponsorsiteID
    ->    FROM  categorysponsorsite  WHERE categoryID IN(2,8)
    ->      GROUP BY sponsorsiteID
    ->    HAVING COUNT(categorysponsorsiteID) = 2
    ->   )
    ->   ;
ERROR 1064: You have an error in your SQL syntax near 'SELECT sponsorsiteID
   FROM  categorysponsorsite  WHERE categoryID IN(2,8)
    ' at line 3
mysql>

   
 
 автор: Trianon   (03.04.2007 в 14:47)   письмо автору
 
   для: Progar   (03.04.2007 в 14:40)
 

3.23.46-nt

Неудивительно. Это очень старый сервер.
Сейчас 5.2, если не ошибаюсь, считается стабильной.

   
 
 автор: Progar   (03.04.2007 в 14:55)   письмо автору
 
   для: Trianon   (03.04.2007 в 14:47)
 

Ок, сейчас попробую поставить поновей! Дам знать результаты..

   
 
 автор: Progar   (03.04.2007 в 17:15)   письмо автору
 
   для: Trianon   (03.04.2007 в 12:35)
 


SELECT name,url FROM sponsorsite WHERE sponsorsiteID IN
(
  SELECT sponsorsiteID 
    FROM  categorysponsorsite  WHERE categoryID IN(2,8)
   GROUP BY sponsorsiteID 
   HAVING COUNT(categorysponsorsiteID) = 2



Гениально! :) Мало того написать, я осмыслить запрос пока не могу.. Может со временем пока буду кат-энд-пейстить в будущем осенит меня :)

   
 
 автор: Trianon   (03.04.2007 в 17:34)   письмо автору
 
   для: Progar   (03.04.2007 в 17:15)
 

Внутренний запрос читается так:
а)из таблицы categorysponsorsite выбрать все строки, в которых categoryID попадают в список(2,8)
б)строки с одним и тем же значением поля sponsorsiteID объединить в группы
в)вывести в качестве результата поле sponsorsiteID тех групп, в которых число строк равно двойке.

внешний запрос: вывести поля name,url тех строк таблицы sponsorsite, поле sponsorsiteID которых имеется в списке результата вложенного запроса.

   
 
 автор: Progar   (03.04.2007 в 17:42)   письмо автору
 
   для: Trianon   (03.04.2007 в 17:34)
 

Вроде б попонятней немного, спасибо..

Правда один человек на другом форуме написал:

HAVING COUNT(categorysponsorsiteID) = 2
выбирает из всех предъидущей выборки те сайты , которые принадлежать только двум! категориям.

Но мой тест показал, что вроде попадают.. т.е. напр попадают франзуско-итальянско-американские.. а он считает что не попадут.. потому как попадают только с двумя категориями..

Тест говорит обратное, но интересно твое мнение.

   
 
 автор: Trianon   (03.04.2007 в 17:55)   письмо автору
 
   для: Progar   (03.04.2007 в 17:42)
 

попадут.
категория американских ...этих... штучек... я забыл, о чем речь :) ... не пройдет через фильтр WHERE ..IN(2,8) внутреннего запроса.
Естественно, двойка в запросе HAVING должна быть равна длине списка WHERE ..IN

Другой вопрос, что чисто итало-французкие штучки так получить нельзя. Тогда запрос должен быть еще сложнее. Может быть коллега с другого форума имеет в виду именно это?

   
 
 автор: Progar   (03.04.2007 в 18:15)   письмо автору
 
   для: Trianon   (03.04.2007 в 17:55)
 

> Может быть коллега с другого форума имеет в виду именно это?

Мне кажется он просто ошибся в своем предположении.

> Другой вопрос, что чисто итало-французкие штучки так получить нельзя.

Да не, чисто не надо.. можно чтоб принадлежали к разных категориям, главное чтоб были итало-франц, напр.. а еще если какие-то, ничего страшного

У меня еще будут аналогичные запросы, где неограниченное кол-во категорий, напр 5-10.. Соответсвенно так будем меняться запрос, напр для 5?


SELECT name,url FROM sponsorsite WHERE sponsorsiteID IN
(
SELECT sponsorsiteID
FROM categorysponsorsite WHERE categoryID IN(2,8,9,26,31)
GROUP BY sponsorsiteID
HAVING COUNT(categorysponsorsiteID) = 5



Вообще я нормально спроектипровал эти таблицы, не будет слишком большой нагрузки на базу из-за таких запросов?

   
 
 автор: Trianon   (03.04.2007 в 18:34)   письмо автору
 
   для: Progar   (03.04.2007 в 18:15)
 

Нормально.
если на всех ключах, всех искомых и приравниваемых полях построены индексы - всё Ок.

   
 
 автор: Progar   (03.04.2007 в 20:17)   письмо автору
 
   для: Trianon   (03.04.2007 в 18:34)
 

Ага, про ключи помню. Спасибо! :)

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования