Php 选择使用和WHERE与或左连接

Php 选择使用和WHERE与或左连接,php,mysql,sql,select,Php,Mysql,Sql,Select,我正在努力使用下面的sql查询来显示来自mysql数据库的搜索结果 这很有效 SELECT * FROM lagerbestand LEFT JOIN verkaufspreis USING (materialnummer) WHERE lagerbestand.level='2' AND (lagerbestand.materialnummer='$suche' OR lagerbestand.materialkurztext LIKE '%$suche%')

我正在努力使用下面的sql查询来显示来自mysql数据库的搜索结果

这很有效

SELECT
    *
FROM
    lagerbestand
LEFT JOIN
    verkaufspreis USING (materialnummer)
WHERE
    lagerbestand.level='2' AND (lagerbestand.materialnummer='$suche' OR lagerbestand.materialkurztext LIKE '%$suche%')
这也行

SELECT
    *
FROM
    lagerbestand
LEFT JOIN
    verkaufspreis USING (materialnummer)
WHERE
    lagerbestand.materialnummer='$suche' OR verkaufspreis.bezeichnung_fr LIKE '%$suche%'
但这不起作用

SELECT
    *
FROM
    lagerbestand
LEFT JOIN
    verkaufspreis USING (materialnummer)
WHERE
    lagerbestand.level='2' AND (lagerbestand.materialnummer='$suche' OR verkaufspreis.bezeichnung_fr LIKE '%$suche%')
唯一的区别是最后一位

lagerbestand.MATERALKURZTEXT更改为verkaufspreis.BEZEICHNUG\U fr


然后脚本将永远加载。

我将首先使用索引来加速查询。此外,如果不需要,请从2中删除引号:

SELECT *
FROM lagerbestand l LEFT JOIN
     verkaufspreis v
     USING (materialnummer)
WHERE l.level = 2 AND (l.materialnummer = '$suche' OR v.materialnummer LIKE '%$suche%');
对于这个查询,您需要一个关于lagerbestandlevel、bezeichnung\u fr和verkaufspreismaterialnummer、bezeichnung\u fr的索引

我不能保证这会带来很好的表现,但这是一个开始

编辑:

或者很难对查询进行优化。下一个想法是使用union all:


这可能会更快,因为子查询可能会更有效地优化。您可以单独尝试每一个,以查看是否仍然存在性能问题。

如果我想返回上一个查询中指定的集合,我认为最佳性能的最佳选择是将其分解为两个不同的集合,并使用UNION ALL set运算符将其组合

如果$such是被替换到SQL文本中的变量,我会确保在包含它之前,它已经被正确转义

 SELECT l.*, v.*
   FROM lagerbestand l
   LEFT JOIN verkaufspreis v USING (materialnummer)
  WHERE l.level = '2'
    AND l.materialnummer = '$suche'

  UNION ALL

 SELECT l.*, v.*
   FROM lagerbestand l
   JOIN verkaufspreis v USING (materialnummer)
  WHERE l.level = '2'
    AND NOT ( l.materialnummer <=> '$suche' )
    AND v.bezeichnung_fr LIKE CONCAT('%','$suche','%')

可能值得一看全文索引和匹配。。。反对:也可以尝试解释查询-直接在MySQL上运行它,例如通过Workbench或PMA,但在它前面加上解释-这可能会让你更好地处理问题。在下面的答案和上面的评论中提供了所有精彩的帮助之后,如果你仍在挣扎,请参阅@草莓谢谢,我试着想出一个例子我刚发现左连接v。。。哪里或v…=。。。太复杂了,无法理解。这不是我发明的,但也不难理解。作为一个简化忽略级别,OP希望第一个表中的所有suches,然后第二个表中的所有suche部分匹配。谢谢,但这给了我与OP中的第三个脚本相同的错误。页面仅为EverEver加载问题查询,根据问题中的OP在bezeichnung_fr列上有一个类似的谓词。此答案中的查询不包括该谓词。除此之外。。。是的,运行两个单独的SELECT并使用UNION ALL set运算符组合结果是获得合理执行计划的最佳选择。这两个SELECT可以单独优化,使用EXPLAIN查看执行计划,添加合适的索引等+10。@spencer7593是的,我知道,所以我将v.materialnummer更改为v.bezeichnung_fr以获得所需的结果。但这就是我得到错误的地方。我认为这与我尝试比较两个表的值有关谢谢,我尝试过了,但现在我得到了一个错误致命的错误:调用一个成员函数fetch_assoc on boolean in…我认为这与选择query$results=$conn->query$sql之后的部分有关;而$row=$results->fetch\u assoc{@theFinges:错误最可能的解释是查询执行失败。查询后代码应该检查$results,如果为FALSE,则获取错误消息。在这个回答中,我在SQL中没有看到错误。如果是我,我将分别测试两个SELECT语句。就性能而言,我希望第二个SELECT语句会出现错误我没有发现SQL有任何明显的问题,除了通过$suche注入SQL的可能性。@theFinges:1分别测试SELECT 2使用EXPLAIN查看执行计划3如果没有合适的索引,请添加合适的索引
 SELECT l.*, v.*
   FROM lagerbestand l
   LEFT JOIN verkaufspreis v USING (materialnummer)
  WHERE l.level = '2'
    AND l.materialnummer = '$suche'

  UNION ALL

 SELECT l.*, v.*
   FROM lagerbestand l
   JOIN verkaufspreis v USING (materialnummer)
  WHERE l.level = '2'
    AND NOT ( l.materialnummer <=> '$suche' )
    AND v.bezeichnung_fr LIKE CONCAT('%','$suche','%')
 ON verkaufspreis (materialnummer, bezeichnung_fr, ... )

 ON lagerbestand (level, materialnummer, ... )