admin

WHERE条件下的SQL IF ELSE / CASE子句

sql

我有一个很大的MySQL语句,通过php foreach循环,并且每个循环都通过union
all连接到先前的循环。我会将语句简化为问题的核心,如果需要的话,我当然也可以在以后根据要求添加更多详细信息。

我有这张桌子

+--------+-----------+-----------+
|   ID   |   LANG    |   TITLE   |
+--------+-----------+-----------+
|   1    |    EN     |   T-A     |
+--------+-----------+-----------+
|   1    |    FR     |   T-A     |
+--------+-----------+-----------+
|   2    |    FR     |   T-B     |
+--------+-----------+-----------+
|   3    |    DE     |   T-C     |
+--------+-----------+-----------+
|   3    |    EN     |   T-C     |
+--------+-----------+-----------+

我想在SQL SELECT中写一个 WHERE 条件,该条件应显示 每个ID最多一个结果 。但是, 仅当LANG为FR或EN时,
它才应显示结果。最重要的是, 应该优先使用FR, 并且仅当ID没有可用的FR时,才应显示EN作为替代。因此结果将如下所示。

+--------+-----------+-----------+
|   ID   |   LANG    |   TITLE   |
+--------+-----------+-----------+
|   1    |    FR     |   T-A     |
+--------+-----------+-----------+
|   2    |    FR     |   T-B     |
+--------+-----------+-----------+
|   3    |    EN     |   T-C     |
+--------+-----------+-----------+

我曾尝试使用IF-ELSE / CASE自己构建一些东西,但是我对SQL的经验不是很丰富,因此将不胜感激。

我尝试过的简化SQL就像

SELECT * FROM `table` 
WHERE `table`.`ID` = 1
IF `table`.`LANG` = 'FR' 
BEGIN
  AND `table`.`LANG` = 'FR' 
END
ELSE
BEGIN
  AND `table`.`LANG` = 'EN' 
END

union all 
SELECT * FROM `table` 
WHERE `table`.`ID` = 2
IF `table`.`LANG` = 'FR' 
BEGIN
  AND `table`.`LANG` = 'FR' 
END
ELSE
BEGIN
  AND `table`.`LANG` = 'EN' 
END

union all 
SELECT * FROM `table` 
WHERE `table`.`ID` = 3
IF `table`.`LANG` = 'FR' 
BEGIN
  AND `table`.`LANG` = 'FR' 
END
ELSE
BEGIN
  AND `table`.`LANG` = 'EN' 
END

网站说明我可能无法将ORDER BY与LIMIT 1结合使用任何构造,因为我每次循环都要通过php将SQL循环多次。

编辑: 对我 有用的 解决方案

SELECT * FROM `table1`
WHERE ID = 1
AND lang = 'FR'
OR (lang = 'EN' AND ID NOT IN (SELECT ID FROM table1 WHERE lang = 'FR'))

阅读 551

收藏
2021-06-07

共1个答案

admin

使用复杂的查询优化器的最优雅,最有效的解决方案是:

SELECT * FROM (
    SELECT * FROM `table`
    WHERE ID IN (
      SELECT id FROM `table` 
      WHERE lang = 'EN'
      EXCEPT
      SELECT id FROM `table`
      WHERE lang = 'FR'
    ) OR table.LANG ='FR'
) t1
WHERE id = ?

这将为您提供所需的结果,并按ID过滤。但是,如果优化器无法降低性能,则id = ?您可能必须自己进行操作才能获得不错的性能:

  SELECT * FROM `table`
    WHERE id = ? AND (ID IN (
      SELECT id FROM `table` 
      WHERE lang = 'EN' AND ID = ?
      EXCEPT
      SELECT id FROM `table`
      WHERE lang = 'FR' AND ID = ?
    ) OR table.LANG ='FR')

但是,如果可以的话,我将立即获得所有结果,而不是首先遍历ID:

SELECT * FROM `table`
WHERE ID IN (
  SELECT id FROM `table` 
  WHERE lang = 'EN'
  EXCEPT
  SELECT id FROM `table`
  WHERE lang = 'FR'
) OR table.LANG ='FR'

这将为您提供所有带有lang’EN’且没有相应的’FR’以及所有’FR’的ID。另外,您也可以尝试:

SELECT * FROM `table`
WHERE lang = 'FR'
OR (lang = 'EN' AND ID NOT IN (SELECT ID FROM table WHERE lang = 'FR'))

或者

SELECT * FROM `table`
WHERE lang = 'FR'
OR (table.LANG = 'EN' AND NOT EXISTS (SELECT * FROM table t1 WHERE lang = 'FR' AND t1.id = table.id))

但是我的猜测是第一个查询最快。

2021-06-07