2013-04-04 2 views
0

У меня возникла проблема с формулировкой запроса, и мне было интересно, может ли кто-нибудь помочь. Я упростил информацию таблицы до минимума здесь, чтобы попытаться понять, что я пытаюсь сделать. У меня есть две таблицы A и B. A имеет столбец BId и поле Value. B имеет информацию, не связанную с вопросом. Что я хочу сделать, это вернуть набор B на основе произвольной логической логики на существование A, которые содержат BId и соответствуют некоторому значению. Кроме того, я хочу вернуть значения, которые были сопоставлены. Ниже приводится почти рабочий пример того, что я хочу в моем запросе:Проблема с MySQL-запросом

SELECT * FROM B 
    WHERE 
    (
     (
     EXISTS (
      SELECT a1.Value FROM A as a1 WHERE a1.BId = B.Id AND a1.Value = "X" 
     ) 
     AND EXISTS (
      SELECT a2.Value FROM A as a2 WHERE a2.BId = B.Id AND a2.Value = "Y" 
     ) 
     ) 
     OR EXISTS (
      SELECT a3.Value FROM A as a3 WHERE a3.BId = B.Id AND a3.Value = "Z" 
     ) 
); 

Это именно то, что я хочу, насколько B вернулся, однако мне нужно, чтобы иметь возможность возвращать значения, которые были подобраны. Так что если бы существовал A, у которого было значение X и другое значение A, имеющее значение Y, я бы хотел a1 и a2 со значениями X и Y, включенными в строку. Если бы не было A со значением Z, это вернулось бы NULL в строке. Я не уверен в синтаксисе или возможности сделать это. Другой подход, который я пытался использовал JOIN:

SELECT *, a1.Value, a2.Value FROM B 
    INNER JOIN A AS a1 ON a1.BId = B.Id 
    INNER JOIN A AS a2 on a2.BId = B.Id 
WHERE 
(
    (
    a1.Value = "X" AND a2.Value = "Y" 
) 
    OR 
    (
    a1.Value = "Z" 
) 
); 

Это правильно возвращает значения, однако она работает только тогда, когда X и Y совпадают. Если Z соответствует, поскольку для выполнения первой части есть два оператора JOIN, я получаю дублированные результаты. По этой причине я скептически отношусь к этому методу. Не похоже, чтобы использовать JOIN так. Если кто-то может понять, что я пытаюсь сделать, и указать мне в правильном направлении, которое было бы высоко оценено. Благодаря!

ответ

1

Возможно, вы уже знаете об этом, но я укажу на это в любом случае. Как вы говорите, ваш исходный SQL-запрос работает, но вы Мне нужно вернуть значения, которые были сопоставлены. Нет универсального ответа на то, как достичь этого, потому что это не так, как работает запрос. Синтаксис WHERE EXISTS (SELECT...) не будет соответствовать ни одной строке, он вернет TRUE, если найдет один или несколько соответствующих строк. Значение: Ваша база данных может содержать или не иметь несколько соответствие строк.

Если посмотреть дизайн базы данных, ваша таблица A, кажется, есть внешний ключ BId, который указывает на запись в B, и не говоря уже о каких-либо уникальных ключей, так что большинство likeyly, есть несколько строк, соответствующих Вашему условий, по крайней мере, для некоторых значений.

Если вы попытаетесь достичь того же с помощью JOINs, вам сначала нужно убедиться, что вы получаете только столько результатов, сколько у вас есть строки в B. (10 результатов в моем примере). Обычно это достигается с помощью предложения GROUP BY. Я также изменил синтаксис СЛЕВА JOIN и, таким образом, чтобы сгруппированных результаты будут возвращать ровно одну строку для каждой записи в B:

SELECT B.Id, MIN(a1.ID) AS MinA1, MIN(a2.ID) AS MinA2, MIN(a3.ID) as MinA3 FROM B 
LEFT JOIN A AS a1 ON a1.BId = B.Id AND a1.value='X' 
LEFT JOIN A AS a2 on a2.BId = B.Id AND a2.value='Y' 
LEFT JOIN A AS a3 ON a3.BId = B.Id AND a3.value='Z' 
GROUP BY B.Id 

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

HAVING (MinA1 IS NOT NULL AND MinA2 IS NOT NULL) OR (MinA3) IS NOT NULL 

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

+0

Ничего себе, это было очень хорошо. Получил его работу практически без изменений, спасибо! –

Смежные вопросы