2

我有一个非常大的 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

Sitenote 我可能不会使用 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'))
4

5 回答 5

1

具有复杂查询优化器的最优雅和最有效的解决方案是:

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))

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

于 2013-09-06T13:24:44.790 回答
0
select * from table where lang = 'FR' union
select t_en.* from table t_en left join table t_fr 
on (t_fr.id = t_en.id and t_fr.lang = 'FR' and t_en.lang = 'EN')
where t_fr.id is null and t_en.lang = 'EN'
于 2013-09-06T13:36:48.273 回答
0

为了更好地了解mysql中的case语句

http://dev.mysql.com/doc/refman/5.0/en/case.html

为了更好地了解 mysql 中的 if 语句

http://dev.mysql.com/doc/refman/5.0/en/if.html
于 2013-11-12T11:56:14.887 回答
0

You can get your exact result in your question like this:

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

See Fiddle-example

If you really want to give the ID each time you can do

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

This gives just one result per ID (Fiddle-example).

You can also use multiple ID's

SELECT * FROM `table`
WHERE (ID in (1,2,3)) AND
( lang = 'FR'
  OR (lang = 'EN' AND ID NOT IN (SELECT ID FROM `table` WHERE lang = 'FR'))
)

and build the (1,2,3) from your script and execute the select. See Fiddle-example.

于 2013-09-06T14:27:24.787 回答
-1
SELECT * FROM TABLE WHERE ( LANG='FR' OR (lang='EN' AND ID NOT IN (SELECT ID FROM TABLE WHERE lang='FR' )))
于 2015-07-15T07:28:24.683 回答