Справка по запросу mysql - изменить этот запрос mysql, чтобы получить эти результаты?

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

CREATE TABLE IF NOT EXISTS `Tutor_Details` (
`id_tutor` int(10) NOT NULL auto_increment,
`firstname` varchar(100) NOT NULL default '',
`surname` varchar(155) NOT NULL default '',
PRIMARY KEY (`id_tutor`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=41 ;

INSERT INTO `Tutor_Details` (`id_tutor`,`firstname`, `surname`) VALUES
(1, 'Sandeepan', 'Nath'),
(2, 'Bob', 'Cratchit');   

CREATE TABLE IF NOT EXISTS `Classes` (
`id_class` int(10) unsigned NOT NULL auto_increment,
`id_tutor` int(10) unsigned NOT NULL default '0',
`class_name` varchar(255) default NULL,
PRIMARY KEY (`id_class`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=229 ;

INSERT INTO `Classes` (`id_class`,`class_name`, `id_tutor`) VALUES
(1, 'My Class', 1),
(2, 'Sandeepan Class', 2);

CREATE TABLE IF NOT EXISTS `Tags` (
`id_tag` int(10) unsigned NOT NULL auto_increment,
`tag` varchar(255) default NULL,
PRIMARY KEY (`id_tag`),
UNIQUE KEY `tag` (`tag`),
KEY `id_tag` (`id_tag`),
KEY `tag_2` (`tag`),
KEY `tag_3` (`tag`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=18 ;

INSERT INTO `Tags` (`id_tag`, `tag`) VALUES
(1, 'Bob'),
(6, 'Class'),
(2, 'Cratchit'),
(4, 'Nath'),
(3, 'Sandeepan'),
(5, 'My');

CREATE TABLE IF NOT EXISTS `Tutors_Tag_Relations` (
`id_tag` int(10) unsigned NOT NULL default '0',
`id_tutor` int(10) default NULL,
KEY `Tutors_Tag_Relations` (`id_tag`),
KEY `id_tutor` (`id_tutor`),
KEY `id_tag` (`id_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `Tutors_Tag_Relations` (`id_tag`, `id_tutor`) VALUES
(3, 1),
(4, 1),
(1, 2),
(2, 2);

CREATE TABLE IF NOT EXISTS `Class_Tag_Relations` (
`id_tag` int(10) unsigned NOT NULL default '0',
`id_class` int(10) default NULL,
`id_tutor` int(10) NOT NULL,
KEY `Class_Tag_Relations` (`id_tag`),
KEY `id_class` (`id_class`),
KEY `id_tag` (`id_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `Class_Tag_Relations` (`id_tag`, `id_class`, `id_tutor`) VALUES
(5, 1, 1),
(6, 1, 1),
(3, 2, 2),
(6, 2, 2);
  • В данных существующей системы, которые я предоставил, наставник по имени «Сандипан Нат» создал класс с именем «Мой класс», а наставник по имени «Боб Крэтчит» создал класс с именем «Класс Сандипан».

Требование -

Чтобы выполнить один запрос с ограничением результатов для отображения результатов поиска в соответствии с логикой И для ключевых слов поиска, например: -

  1. Если выполняется поиск «Класс Сандипана», возвращается запись наставника Сандипана Натха из таблицы сведений о наставнике (поскольку «Сандипан» - это имя Сандипана Натха, а класс присутствует в имени класса класса Сандипана)
  2. Если ищется "Class", выбираются оба наставника из таблицы Tutor_details, потому что Class присутствует в имени класса, созданного обоими наставниками.

Вот что я до сих пор достиг (PHP Mysql): -

<?php
$searchTerm1 = "Sandeepan";
$searchTerm2 = "Class";

mysql_select_db("test");


$sql = "SELECT td.*
FROM Tutor_Details AS td
LEFT JOIN Tutors_Tag_Relations AS ttagrels ON td.id_tutor = ttagrels.id_tutor
LEFT JOIN Classes AS wc ON td.id_tutor = wc.id_tutor
LEFT JOIN Class_Tag_Relations AS wtagrels ON td.id_tutor = wtagrels.id_tutor

LEFT JOIN Tags as t1 on ((t1.id_tag = ttagrels.id_tag) OR (t1.id_tag = wtagrels.id_tag))
LEFT JOIN Tags as t2 on ((t2.id_tag = ttagrels.id_tag) OR (t2.id_tag = wtagrels.id_tag))


where t1.tag LIKE '%".$searchTerm1."%'
AND t2.tag LIKE '%".$searchTerm2."%'

GROUP BY td.id_tutor
LIMIT 10
";

$result = mysql_query($sql);
echo $sql;
if($result)
{

while($rec = mysql_fetch_object($result)) $recs[] = $rec;
//$rec = mysql_fetch_object($result);
echo "<br><br>";

if(is_array($recs))
{
foreach($recs as $each)
{
print_r($each);
echo "<br>";
}

}

}
?>

Но результаты такие: -

Если выполняется поиск «Sandeepan Nath», он не возвращает ни одного наставника (вместо только строки Sandeepan). Если выполняется поиск «Sandeepan Class», он возвращает строку Sandeepan (вместо «Оба наставника»). Если выполняется поиск «Bob Class», он правильно возвращает Строка Боба. При поиске «Боб Крэтчит» не возвращается ни одного репетитора (а только


person Sandeepan Nath    schedule 28.05.2010    source источник


Ответы (1)


Проблема в том, что у вас есть 2 условия поиска, и вы не генерируете никаких строк, в которых вы можете искать два тега из одной и той же таблицы отношений (это легко увидеть, если вы посмотрите на результаты своего запроса, не ограничивая их td, *). Решение, если вы хотите сделать это в SQL, состоит в том, чтобы сгенерировать все 2 перестановки поисковых терминов для тегов, используемых для каждого отношения наставник / класс (опять же, это объяснение имеет гораздо больший смысл, если вы посмотрите на полные результаты запроса). Во всяком случае, вот мой подход к исправлению SQL так, как вы это делаете:

SELECT td.*
FROM Tutors_Tag_Relations AS ttagrels1 
JOIN Tutors_Tag_Relations AS ttagrels2 ON 
    ttagrels2.id_tutor = ttagrels1.id_tutor AND 
    ttagrels2.id_tag != ttagrels1.id_tag
JOIN Class_Tag_Relations AS wtagrels1 ON 
    wtagrels1.id_tutor = ttagrels1.id_tutor AND
    wtagrels1.id_tag != ttagrels1.id_tag AND
    wtagrels1.id_tag != ttagrels2.id_tag
JOIN Class_Tag_Relations AS wtagrels2 ON 
    wtagrels2.id_tutor = ttagrels1.id_tutor AND
    wtagrels2.id_tag != wtagrels1.id_tag AND
    wtagrels2.id_tag != ttagrels1.id_tag AND
    wtagrels2.id_tag != ttagrels2.id_tag
JOIN Tags as t1 ON
    t1.id_tag = ttagrels1.id_tag OR
    t1.id_tag = ttagrels2.id_tag OR
    t1.id_tag = wtagrels1.id_tag OR
    t1.id_tag = wtagrels2.id_tag
JOIN Tags as t2 ON
    t2.id_tag != t1.id_tag AND
    (t2.id_tag = ttagrels1.id_tag OR
    t2.id_tag = ttagrels2.id_tag OR
    t2.id_tag = wtagrels1.id_tag OR
    t2.id_tag = wtagrels2.id_tag)
LEFT JOIN Tutor_Details as td ON ttagrels1.id_tutor = td.id_tutor
LEFT JOIN Classes AS wc ON td.id_tutor = wc.id_tutor
WHERE 
    t1.tag LIKE '%Sandeepan%' AND
    t2.tag LIKE '%Nath%'
GROUP BY td.id_tutor

Хотя на самом деле я бы так не поступил. Будет очень, очень тяжело пытаться выполнить такой поиск через объединения, и будет только хуже, если вы добавите больше поисковых запросов.

Объяснение отсутствующей перестановки:

Эти таблицы создаются путем удаления предложения where, предложения group, удаления дубликатов и отображения только столбцов td1 и td2.

Твой путь:

+--------+-----------+--------+-----------+
| id_tag | tag       | id_tag | tag       |
+--------+-----------+--------+-----------+
|      1 | Bob       |      3 | Sandeepan |
|      1 | Bob       |      6 | Class     |
|      2 | Cratchit  |      3 | Sandeepan |
|      2 | Cratchit  |      6 | Class     |
|      3 | Sandeepan |      1 | Bob       |
|      3 | Sandeepan |      2 | Cratchit  |
|      3 | Sandeepan |      5 | My        |
|      3 | Sandeepan |      6 | Class     |
|      4 | Nath      |      5 | My        |
|      4 | Nath      |      6 | Class     |
|      5 | My        |      3 | Sandeepan |
|      5 | My        |      4 | Nath      |
|      6 | Class     |      1 | Bob       |
|      6 | Class     |      2 | Cratchit  |
|      6 | Class     |      3 | Sandeepan |
|      6 | Class     |      4 | Nath      |
+--------+-----------+--------+-----------+

Теперь, если мы посмотрим на это, мы увидим, что td1.id_tag ​​создается из существующих отношений класса или наставников. Также td2.id_Tag создается из имеющихся отношений класса или наставника. Однако для любой 1 строки этого результата td1.id_Tag и td2.id_tag ​​не могут быть из одной и той же таблицы отношений. Они всегда являются классом / репетитором или репетитором / классом, и никогда не бывает строки для набора тегов класса / класса или репетиторов / репетиторов (помните, что в таблице отношений классов есть тег Sandeepan). Это означает, что у вас нет возможности искать "Sandeepan", "Nash" или "Bob" "Cratchit", потому что в обоих случаях эти теги присутствуют только в одной таблице.

Мой метод:

+--------+-----------+--------+-----------+
| id_tag | tag       | id_tag | tag       |
+--------+-----------+--------+-----------+
|      1 | Bob       |      2 | Cratchit  |
|      1 | Bob       |      3 | Sandeepan |
|      1 | Bob       |      6 | Class     |
|      2 | Cratchit  |      1 | Bob       |
|      2 | Cratchit  |      3 | Sandeepan |
|      2 | Cratchit  |      6 | Class     |
|      3 | Sandeepan |      1 | Bob       |
|      3 | Sandeepan |      2 | Cratchit  |
|      3 | Sandeepan |      4 | Nath      |
|      3 | Sandeepan |      5 | My        |
|      3 | Sandeepan |      6 | Class     |
|      4 | Nath      |      3 | Sandeepan |
|      4 | Nath      |      5 | My        |
|      4 | Nath      |      6 | Class     |
|      5 | My        |      3 | Sandeepan |
|      5 | My        |      4 | Nath      |
|      5 | My        |      6 | Class     |
|      6 | Class     |      1 | Bob       |
|      6 | Class     |      2 | Cratchit  |
|      6 | Class     |      3 | Sandeepan |
|      6 | Class     |      4 | Nath      |
|      6 | Class     |      5 | My        |
+--------+-----------+--------+-----------+

Все, что делает мой SQL, - это генерировать недостающие строки Class / Class Tutors / Tutors, что устраняет проблему.

person Mike    schedule 28.05.2010
comment
Привет, Майк, спасибо за решение. Он работает отлично, и я абсолютно согласен с тем, что Вещи будут очень, очень тяжелыми, пытаясь выполнять такого рода поиск через объединения. Но я не совсем понял, что вы имели в виду, говоря, что решение, если вы хотите сделать это в SQL, должно генерировать все 2 перестановки поисковых запросов тегов, используемых для каждого отношения наставник / класс. Если бы вы могли хотя бы дать мне еще несколько подсказок, чтобы я получил более четкое представление, было бы здорово. Еще раз спасибо за помощь - person Sandeepan Nath; 28.05.2010
comment
Привет, Майк, как мы видели, этот запрос стал бы очень сложным. Пожалуйста, проверьте мой вопрос stackoverflow.com/questions/2927142/, где пользователь дал лучшее решение. Пожалуйста, посмотрите, можете ли вы мне помочь, спасибо - person Sandeepan Nath; 03.06.2010
comment
Привет, Майк, я немного улучшил свою логику поиска. Чтобы уменьшить сложность и количество объединений, я сейчас создаю временную таблицу во время выполнения поиска под названием All_Tag_Relations, которая содержит все данные из Tutors_Tag_Relations и Webclasses_Tag_Relations (на данный момент игнорируя Learning_Packs_Tag_Relations). Но проблема все еще существует, пожалуйста, проверьте мой новый вопрос, если вы можете помочь stackoverflow.com/questions/3030022/ - person Sandeepan Nath; 13.06.2010