Mysql查询帮助 - 更改这个mysql查询以获得这些结果?

时间:2010-05-28 02:44:06

标签: php mysql query-optimization

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

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 Sandeepan Nath在Tutor Details表中的记录(因为“Sandeepan”是Sandeepan Nath的名字,而Class在Sandeepan班级的名字中出现)
  2. 如果搜索“Class”,则会获取Tutor_details表中的两个导师,因为Class存在于两个导师创建的类的名称中。
  3. 以下是我到目前为止所做的(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”,它会正确返回Bob的行 如果搜索“Bob Cratchit”,它不会返回任何导师(而不仅仅是

1 个答案:

答案 0 :(得分: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行,从而解决了这个问题。