【问题标题】:Mysql query help - Alter this mysql query to get these results?Mysql 查询帮助 - 更改此 mysql 查询以获得这些结果?
【发布时间】:2010-05-28 02:44:05
【问题描述】:

请先执行以下查询进行设置,以便您帮助我:-

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);
  • 在我提供的当前系统数据中,名为“Sandeepan Nath”的导师创建了名为“My Class”的班级,名为“Bob Cratchit”的导师创建了名为“Sandeepan Class”的班级。

要求-

执行一个对结果有限制的查询,以按照搜索关键字的 AND 逻辑显示搜索结果,如下所示:-

  1. 如果搜索“Sandeepan Class”,则返回 Tutor Details 表中的 Tutor Sandeepan Nath 记录(因为“Sandeepan”是 Sandeepan Nath 的名字,而 Class 存在于 Sandeepan 班级的班级名称中)
  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 的行(而不是 Bothutors ) 如果搜索“Bob Class”,则正确返回 Bob 的行 如果搜索“Bob Cratkit”,它不会返回任何导师(而不仅仅是

【问题讨论】:

    标签: php mysql query-optimization


    【解决方案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 不能来自同一个关系表。它们始终是 Class/Tutors 或 Tutors/Class 永远不会有 Class/Class 或 Tutors/Tutors 标记集的行(请记住,Class 关系表中有一个 Sandeepan 标记)。这意味着您无法搜索“Sandeepan”、“Nash”或“Bob”“Cratkit”,因为在这两种情况下,这些标签都只存在于一个表中。

    我的方式:

    +--------+-----------+--------+-----------+
    | 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 行,从而解决了这个问题。

    【讨论】:

    • 嗨,迈克,感谢您的解决方案。它运行完美,我绝对同意“尝试通过连接进行这种搜索会变得非常非常繁重”。但是我并不完全理解您所说的“解决方案,如果您想在 SQL 中执行此操作,就是生成用于每个导师/班级关系的标签的所有 2 个搜索词排列”的意思。如果你至少能给我一些更多的线索,让我得到一个更清晰的画面,那就太好了。再次感谢您的帮助
    • 嗨,迈克,这个查询会像我们看到的那样变得非常繁重。请检查我的问题stackoverflow.com/questions/2927142/… 用户提供了更好的解决方案。请看看您是否可以进一步帮助我,谢谢
    • 嗨,迈克,我已经稍微改进了我的搜索逻辑。为了降低连接的复杂性和数量,我现在在搜索执行期间创建一个名为 All_Tag_Relations 的临时表,其中包含来自 Tutors_Tag_Relations 和 Webclasses_Tag_Relations 的所有数据(暂时忽略 Learning_Packs_Tag_Relations)。但是,还有一个问题,请检查我的新问题,如果你能帮助stackoverflow.com/questions/3030022/…
    猜你喜欢
    • 2011-03-03
    • 1970-01-01
    • 2011-05-08
    • 2011-11-07
    • 2011-07-19
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多