简体   繁体   English

使用以及WHERE和OR选择左联接

[英]SELECT LEFT JOIN with USING and WHERE AND OR

I'm struggling with the following sql query to display a search result from a mysql db 我正在尝试以下SQL查询来显示来自mysql数据库的搜索结果

This works 这有效

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

This works too 这也有效

SELECT
    *
FROM
    lagerbestand
LEFT JOIN
    verkaufspreis USING (materialnummer)
WHERE
    lagerbestand.materialnummer='$suche' OR verkaufspreis.bezeichnung_fr LIKE '%$suche%'

But this doesn't work 但这行不通

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

The only difference is the last bit. 唯一的不同是最后一点。

lagerbestand.materialkurztext is changed to verkaufspreis.bezeichnung_fr lagerbestand.materialkurztext更改为verkaufspreis.bezeichnung_fr

Then the script just loads for ever. 然后脚本将永远加载。

I would start by using indexes to speed the query. 我将从使用索引加快查询速度开始。 Also, drop the quotes from 2 if it is not necessary: 另外,如果没有必要,请将引号从2删除:

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

For this query, you want an index on lagerbestand(level, bezeichnung_fr) and verkaufspreis(materialnummer, bezeichnung_fr) . 对于此查询,您需要在lagerbestand(level, bezeichnung_fr)verkaufspreis(materialnummer, bezeichnung_fr)lagerbestand(level, bezeichnung_fr)索引。

I'm not guaranteeing this will result in great performance, but it is a place to start. 我不保证这会带来出色的性能,但这是一个起点。

EDIT: 编辑:

OR can be hard to optimize for a query. OR可能难以优化查询。 The next idea is to use union all : 下一个想法是使用union all

SELECT *
FROM lagerbestand l LEFT JOIN
     verkaufspreis v
     USING (materialnummer)
WHERE l.level = 2 AND l.materialnummer = '$suche'
UNION ALL
SELECT *
FROM lagerbestand l JOIN
     verkaufspreis v
     USING (materialnummer)
WHERE l.level = 2 AND (l.materialnummer <> '$suche' AND v.materialnummer LIKE '%$suche%');

This might be faster, because the subqueries might be optimized more efficiently. 这可能会更快,因为可能会更有效地优化子查询。 You can try each one independently to see if there still a performance problem. 您可以独立尝试每一个,以查看是否仍然存在性能问题。

If I wanted to return set specified in the last query, I think the best bet for optimal performance is going to be to break that up into two distinct sets, and combine those with a UNION ALL set operator. 如果我想返回上一个查询中指定的集合,则我认为最佳性能的最佳选择是将其分解为两个不同的集合,然后将它们与UNION ALL集合运算符组合。

(If $such is meant to be variable that is substituted into the SQL text, I would make sure that it has been properly escaped, before it is included.) (如果$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','%')

Then I would tune each of those SELECT separately, using EXPLAIN , making sure appropriate indexes are available. 然后,我将使用EXPLAIN分别调整每个SELECT,以确保可以使用适当的索引。

 ON verkaufspreis (materialnummer, bezeichnung_fr, ... )

 ON lagerbestand (level, materialnummer, ... )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM