2013-09-06 1 views
2

У меня очень большой оператор MySQL, зацикливаемый через php foreach, и каждый цикл, связанный с предыдущим, объединяет все. Я упрощу это заявление в ядре своей проблемы, при необходимости я, конечно, могу добавить дополнительные сведения позже по запросу.SQL IF ELSE/CASE предложение в условии WHERE

У меня есть эта таблица

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

Я хочу написать WHERE условие в SQL SELECT, который должен показать мне для каждого ID максимум один результат. Но он должен показывать результаты , только если LANG - FR или EN. Наверх FR следует предпочесть и EN должны отображаться только в качестве альтернативы, если для идентификатора нет FR. Таким образом, результат будет выглядеть следующим образом.

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

Я пытался создать что-то самостоятельно с IF - ELSE/CASE, но я не очень опытный с SQL, так что любая помощь будет намного appreaciated.

Упрощенный 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, так как я зацикливание на SQL через PHP для каждого цикла несколько раз.

EDIT: решение, которое работает для меня

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 = ? вы, возможно, придется сделать это самостоятельно, чтобы получить достойную производительность:

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

Однако, если вы можете, я хотел бы получить все результаты сразу, а не перебирать идентификаторы в первую очередь:

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-х. В качестве альтернативы можно также попробовать:

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

Но мое предположение было бы первый запрос является самым быстрым.

+0

ОП запрашивает запрос, который возвращает только 1 строку на идентификатор. Этот запрос не сделает этого, так как ваш внешний запрос может возвращать несколько строк для каждого идентификатора во внутреннем запросе. – Dan

+0

Хорошо, это было очень непонятно, так как его примерная таблица была последовательной из нескольких строк. Но, очевидно, это может быть просто включено в выборку для определенной строки. –

+0

Я думаю, что ваш второй вариант DOES дает правильный результат. 'SELECT * FROM table WHERE lang = 'FR' OR (lang = 'EN' И ID NOT IN (SELECT ID FROM table WHERE lang = 'FR'))'. Он дает один результат за идентификатор, если нет одинакового идентификатора с одним и тем же языком. См. [Fiddle] (http://sqlfiddle.com/#!2/9c167/6) ./ – Rik

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' 
+0

Какой смысл в объединение с неограниченным выбором? –

+0

Я забыл, где условие, первый выбор ограничен fr. второй выбор возвращает только en – Marek

+0

Хорошо, теперь это имеет смысл. Я исправлю свой голос, как только мне позволено. –

0

Вы можете получить точный результат в вашем вопросе, как это:

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

См Fiddle-example

Если вы действительно хотите, чтобы дать идентификатор каждый раз, когда вы можете сделать

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

Вы также можете использовать несколько идентификаторов

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) из вашего сценария и выполнить выбор. См. Fiddle-example.

0

для лучшего знания саза в MySQL

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

для лучшего знания, если заявление в MySQL

http://dev.mysql.com/doc/refman/5.0/en/if.html 
-1
SELECT * FROM TABLE WHERE (LANG='FR' OR (lang='EN' AND ID NOT IN (SELECT ID FROM TABLE WHERE lang='FR'))) 
Смежные вопросы