MySQL INNER JOIN - как добавить дополнительный оператор IF? - PullRequest
0 голосов
/ 12 января 2019

Я только что узнал, как использовать JOINS (поэтому, пожалуйста, будьте осторожны;)), и написал этот запрос:

SELECT 1
FROM `T1` 
INNER JOIN `T2` ON `T1`.`T1_ID` = `T2`.`REQUIREMENT`
WHERE `T2`.`T1_ID` = XXX
  AND `T1`.`STATEMENT` = YYY
  AND `T2`.`REQUIREMENT` != 0 //last row does not work as intended!

Отлично работает без последнего условия: если T1_ID из T1 соответствует REQUIREMENT из T2 для заданного T1_ID (XXX) - это работает. Я хотел, чтобы дополнительные STATEMENT из T1 соответствовали (ГГГГ) - и это все еще работает.

Но потом я понял, что мне нужно исключить одну причину: когда T2. REQUIREMENT равно 0, я хочу, чтобы этот запрос возвращал 1 независимо от формулы JOIN. Проблема в том, что если T2. REQUIREMENT = 0, я точно знаю, что не будет ни одной записи T1. T1_ID, которая бы соответствовала требованиям JOIN. Итак, я понимаю, что это последнее условие не имеет права работать, как хотелось бы.

Мне нужно какое-то утверждение IF. Что-то, что будет работать как:

SELECT 1 
    IF (`T2`.`REQUIREMENT`!=0) //if true, don't even go to join, and return 1
       OR (my previous join query)

Дело в том, что я понятия не имею, как реализовать такое выражение IF в mysql.

Есть идеи? Спасибо.

Пример данных:

T1:

id   STATEMENT  T1_ID
1    irrelevant   1
2    irrelevant   5
* +1032 * Т2:
id  T1_ID REQUIREMENT
1    1     0
2    2     0
3    3     1
4    4     3
5    5     4
6    6     5
7    7     6

Такая настройка должна возвращать 1 для T1_ID, равного 1, 2, 3, 6.

Кроме того, если это возможно даже в одном запросе, я бы хотел, чтобы он также возвращал 1, даже если T1 был пуст, для всех T2. REQUIREMENT = 0 - в данном случае T1_ID равно 1, 2.

Ответы [ 3 ]

0 голосов
/ 12 января 2019

если T2.REQUIREMENT = 0, я точно знаю, что не будет Запись T1.T1_ID, соответствующая требованиям JOIN

Таким образом, чтобы получить 1, возвращаемый при T2.REQUIREMENT=0, объединение также должно соответствовать этому условию:

SELECT 1
FROM `T1` INNER JOIN `T2`
ON `T1`.`T1_ID` = `T2`.`REQUIREMENT` OR `T2`.`REQUIREMENT`=0
WHERE `T2`.`T1_ID`=XXX
AND `T1`.`STATEMENT`=YYY

Редактировать :
или просто добавьте 1 s с UNION для всех строк, которые имеют T2.REQUIREMENT=0:

SELECT 1
FROM `T1` INNER JOIN `T2`
ON `T1`.`T1_ID` = `T2`.`REQUIREMENT`
WHERE `T2`.`T1_ID`=XXX
AND `T1`.`STATEMENT`=YYY
UNION ALL
SELECT 1
FROM `T2`
WHERE `T2.REQUIREMENT=0`

это будет работать, даже если T1 пусто.

0 голосов
/ 12 января 2019

Просто к сведению, хорошее начало для вашего поста и пример ... всегда должны быть предоставлены ссылки на tableName.columnName (или alias.columnName), чтобы не допустить неоднозначности того, что другие не знают структуру вашей таблицы. Кроме того, вам действительно нужны только галочки для таких вещей, как зарезервированные слова или имена столбцов, в которых есть пробелы (в любом случае, никогда не такие).

Из моего прочтения ваш вопрос и примеры таблиц T1 и T2 ... T1 кажутся некой таблицей поиска и имеют идентификаторы и описания, связанные с указанными идентификаторами. Ваша таблица T2, по-видимому, является таблицей, основанной на деталях / транзакциях, и может иметь или не иметь фактическое требование, поэтому вы всегда хотите включать эти записи без специального требования.

Если это так, звучит так, будто вам нужны «все подробные записи, которые имеют некоторое условие НЕЗАБЫВАЕМОГО идентификатора соответствия, найденного в таблице поиска». Если это верно, вы будете искать

Select
      T2.T1_ID,
      coalesce( T1.Statement, '' ) StatementFromT1Table
   from
      SomeMainTable T2
         LEFT JOIN SomeLookupTable T1
            on T2.T1_ID = T1.T1_ID
   where
         T2.T1_ID = SomeIdParameterValue
      AND (  T1.T1_ID is NULL
         OR  T1.Statement = SomeOtherParameterValue )

Соединение между таблицами. Я всегда стараюсь сначала перечислить левую таблицу, затем сделать отступ для правой таблицы, и мое условие ВКЛ показывает left.column = right.column, чтобы вы всегда видели взаимосвязь и то, как таблица A попадает в таблицу B (и вкладывается больше, когда в игру вступают другие объединения).

Различие между (INNER) JOIN и LEFT JOIN состоит в том, что (INNER) JOIN ТРЕБУЕТ запись, которая всегда совпадает в обеих таблицах. LEFT JOIN означает, что я хочу, чтобы все данные из таблицы на левой стороне НЕЗАВИСИМО от фактического соответствия в правой таблице.

Итак, на данный момент я сначала получаю все из таблицы псевдонимов T2 независимо от ответа в псевдониме T1. Теперь, как бороться с нулевым значением идентификатора замечаний. Если ноль означает, что вы ЗНАЕТЕ, что в T1 совпадения не будет, то вы можете просто сказать, что я хочу, чтобы все записи на стороне T2 были, если сторона T1 равна NULL ... Но вы также заботитесь о конкретном утверждении, следовательно, ИЛИ в скобках тест.

Первая часть где - это если вы специально искали все значения T1_ID = некоторого значения, так что это основной параметр и применимо только к стороне T2 ... вы определяете сторону T1 через AND (нулевой или другой критерий равенства) условие.

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

Если я рядом и вам нужны дополнительные разъяснения, пожалуйста, сообщите и / или отредактируйте исходный пост с дополнительными образцами данных и окончательным выводом ... такими как параметры, которые также фильтруются.

РАЗЪЯСНЕНИЕ ПОЧТЫ.

По вашим комментариям, вот пояснения ...

"SomeMainTable T2" ​​- это фактически действительное имя таблицы в вашей базе данных, а "T2" - это ссылка на ALIAS. Представьте, что ваша таблица называется «SomethingReallyLongDetail». Вы бы предпочли написать свой запрос что-то вроде

select
      SomethingReallyLongDetail.Column1,
      SomethingReallyLongDetail.Column7,
      SomethingReallyLongDetail.Column20
   from
      SomethingReallyLongDetail

OR ...

select
      SRL.Column1,
      SRL.Column7,
      SRL.Column20
   from
      SomethingReallyLongDetail SRL

В этом случае я использовал псевдоним "SRL", чтобы легче соотносить имя таблицы с аббревиатурой / сокращением по сравнению с необходимостью вводить длинное значение снова и снова, а затем иметь больше шансов набрать ошибки. Просто для удобства чтения, предоставляя ссылку "псевдоним" в запросе. Итак, я не знал вашего АКТУАЛЬНОГО имени таблицы, поэтому я составил его, но использовал ссылки "T1" и "T2", чтобы оставаться в соответствии с вашим исходным сообщением.

Далее, COALESCE (). Поскольку этот запрос выполняет LEFT-JOIN, правая таблица может (или нет) фактически иметь совпадение записей по идентификатору, поскольку, как вы знаете, не всегда может существовать. Так как я пытался извлечь столбец «Statement» из этой второй таблицы (псевдоним T1), это описание могло бы быть NULL, которое вы, вероятно, не хотели бы показывать в любом виде вывода. Чтобы предотвратить это, COALESCE () говорит, дайте мне значение из первого параметра в списке ... Если это значение равно нулю, дайте мне второе значение. В этом случае второе значение - просто пустая строка.

Параметры в запросе. Ваш исходный запрос имел ссылку на XXX и YYY, например, вы знали о конкретном значении T1.ID, которое вы хотите сузить до извлечения, но другое значение YYY как часть утверждения. Итак, место, где у вас был «XXX», я просто поместил здесь заполнитель, чтобы вы могли применить / указать любую ценность, которую вы конкретно искали. Точно так же для вашего значения "YYY", другой заполнитель для этого. Просто замените критерии, которые вы искали.

Наконец, это и часть предложения where. Это для условия LEFT-JOIN. Поскольку вы ЗНАЕТЕ, что не все записи будут иметь совпадение во вторичной таблице "T1", с помощью LEFT JOIN будет найден идентификатор и ИМЯ значение, или не будет значения и, следовательно, NULL.

Если нет подходящей записи, вы никогда не сможете сравнить какую-либо строку, int, date, что угодно со столбцом, поскольку он будет нулевым. Итак, я делаю

(T1.T1_ID IS NULL  -- as in there was no match
 OR T1.Statement = SomeOtherParameterValue )  -- there WAS a match, and I only want where the statement equals a given value.

Согласно вашим комментариям и результатам примера ваш запрос ДОЛЖЕН быть упрощен до ...

Select
      T2.ID,
      T2.T1_ID,
      T2.Requirement,
      coalesce( T1.Statement, '' ) StatementFromT1Table
   from
      T2
         LEFT JOIN T1
            on T2.Requirement = T1.T1_ID
   where
         T2.Requirement = 0
      OR T1.T1_ID IS NOT NULL

В вашем случае, окончательный ответ ... Я хочу, чтобы все записи, в которых нет требования (таким образом, = 0), ИЛИ запись имеет совпадение в таблице T1 (таким образом, T1.T1_ID НЕ НУЛЬ)

0 голосов
/ 12 января 2019

Я думаю, что вы хотите LEFT JOIN:

SELECT 1
FROM `T2` LEFT JOIN
     `T1`
     ON `T1`.`T1_ID` = `T2`.`REQUIREMENT`
WHERE (`T2`.`REQUIREMENT` <> 0) OR
      (`T1`.`STATEMENT` = YYY AND `T2`.`T1_ID` = XXX);

Возвращает строки для всех T2 значений, где REQUIREMENT != 0. Он также возвращает строки, сгенерированные JOIN. Конечно, 1 не очень наглядно, поэтому вы хотите знать, какие строки какие.

Ваш вопрос будет намного проще с примерами данных и желаемых результатов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...