2015-07-02 5 views
2

Я получаю повторяющиеся строки, потому что B.column1 неоднозначен.MySql: Conditional Join

Вот почему я хочу только строки таблицы B где column2 имеются записи как 'x' или 'y' (она состоит из т.е. 'x', 'y', 'z').

Приоритет 'x' составляет более 'y', поэтому пользователь скорее 'x', чем 'y'. Я думал, что условие в последней строке будет решить эту проблему:

SELECT 
    * 
FROM A 
    LEFT JOIN B on B.column1=A.column1 
     AND B.column2= (IF(B.column2 = 'x','x','y')) 

Но оказалось, что это то же самое, как я написал бы

AND (B.column2 = 'x' OR B.column2 = 'y') 

-> он соединяет обе строки вместо одной.

Есть (хорошее) решение этой проблемы? Имейте в виду, что я могу присоединиться к более таблицам, чем к одному.


Edit:

не будет работать

(B.column2 = 'x' XOR B.column2 = 'y') 

не будет работать

(B.column2 = 'x' OR B.column2 = 'y') AND NOT (B.column2 = 'x' AND B.column2 = 'y') 

, который я бы даже не принимать, так как его не 'x' rather than'y', но either 'x' or 'y'. Но это показывает мне, что я, вероятно, имея ложный подход


Edit2:

Я использовал slighty другой подход Жан Юнгу:

я решил дать более глубокое представление в Задачу, так как я не могу решить проблему с conditional joins. Теперь вот как это выглядит с несколькими таблицами, к которым я хочу присоединиться:

SELECT 
    * 
FROM A 
    LEFT JOIN I on I.unique = A.unique 
    LEFT JOIN B on B.column1 = I.column1 
    LEFT JOIN J on J.unique = A.unique 
    LEFT JOIN B AS C on C.column1 = J.column1 and B.column2 = C.column2 
    LEFT JOIN K on K.unique = A.unique 
    LEFT JOIN B AS D on D.column1 = K.column1 and C.column2 = D.column2 
WHERE B.column2 = 'x' 
UNION 
SELECT 
    * 
FROM A 
    LEFT JOIN I on I.unique = A.unique 
    LEFT JOIN B on B.column1 = I.column1 
    LEFT JOIN J on J.unique = A.unique 
    LEFT JOIN B AS C on C.column1 = J.column1 and B.column2 = C.column2 
    LEFT JOIN K on K.unique = A.unique 
    LEFT JOIN B AS D on D.column1 = K.column1 and C.column2 = D.column2 
WHERE B.column2 = '' AND A.unique NOT IN (
    SELECT 
     A.unique 
    FROM A 
     LEFT JOIN I on I.unique = A.unique 
     LEFT JOIN B on B.column1 = I.column1 
     LEFT JOIN J on J.unique = A.unique 
     LEFT JOIN B AS C on C.column1 = J.column1 and B.column2 = C.column2 
     LEFT JOIN K on K.unique = A.unique 
     LEFT JOIN B AS D on D.column1 = K.column1 and C.column2 = D.column2 
    WHERE B.column2 = 'x' 
) 

Это занимает довольно долгое время, но выполняет свою работу. Я не удовлетворен, поскольку кажется очень неэлегантным, но если нет лучшего решения, я пойду с этим (и, честно говоря, я действительно не понимаю, почему это работает).

+0

Ваш вопрос немного неясен, но всего несколько примечаний: 1) вы также можете использовать 'IN ('x', 'y', ...)', если у вас несколько записей (но не переходите несколько сотен, например 200, или у вас могут возникнуть проблемы с первичными функциями, потому что это не использует индекс). 2) Пробовали ли вы использовать 'GROUP BY b.column2'? – Hamed

+0

У меня есть проблема, что 'GROUP BY b.column2' doesnt всегда получает мне строку с 'x', но иногда строка с' y'. Но я скорее хочу строку с 'x', чем с помощью' y'. Есть ли способ получить там условие? 'IN ('x', 'y',)' даст мне две строки, но, как указано выше, я только строкой с 'x'. Если theres нет 'x' в' GROUP BY b.column2', тогда я хочу 'y', другой, поэтому он не должен присоединяться к строке – InsOp

+1

@Hamed Я думаю, что он не мог использовать' IN', потому что ему нужен уровень приоритета в ' 'х', 'y''. Если запись соответствует '' x'', тогда он должен игнорировать другую запись, которая соответствует '' y'', так? –

ответ

0

Если я правильно понимаю ваш вопрос, это возможный подход:

SELECT A.*, IF(B_X.column1 IS NOT NULL, B_X.column2, B_Y.column2), IF(B_X.column1 IS NOT NULL, B_X.column3, B_Y.column3), ... 
FROM A 
LEFT OUTER JOIN B B_X ON A.column1 = B_X.column1 AND B_X.column2 = 'x' 
LEFT OUTER JOIN B B_Y ON A.column1 = B_Y.column1 AND B_Y.column2 = 'y' 

Вы должны перечислить каждый столбец, который из B в IF(), в вашем ЗЕЬЕСТЕ, для того, чтобы получить значения «x» перед значениями «y».