我有一个非常大的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'))
答案 0 :(得分: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'
这将为您提供所有标有“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))
但我的猜测是第一个查询最快。
答案 1 :(得分: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'
答案 2 :(得分:0)
您可以在这样的问题中得到确切的结果:
SELECT * FROM `table`
WHERE lang = 'FR'
OR (lang = 'EN' AND ID NOT IN (SELECT ID FROM `table` WHERE lang = 'FR'))
如果你真的想每次都能提供身份证件
SELECT * FROM `table`
WHERE (ID=1) AND
( lang = 'FR'
OR (lang = 'EN' AND ID NOT IN (SELECT ID FROM `table` WHERE lang = 'FR'))
)
每个ID(Fiddle-example)仅提供一个结果。
您还可以使用多个ID
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'))
)
并从脚本构建(1,2,3)
并执行select。
请参阅Fiddle-example。
答案 3 :(得分: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
答案 4 :(得分:-1)
SELECT * FROM TABLE WHERE ( LANG='FR' OR (lang='EN' AND ID NOT IN (SELECT ID FROM TABLE WHERE lang='FR' )))