MySQL - Выберите данные с помощью JOIN, но с предложениями WHERE, применяемыми к сложным и различным периметрам - PullRequest
0 голосов
/ 19 сентября 2019

У меня есть база данных MySQL 5.6, и я не могу сделать сложный запрос, который (я думаю) включает в себя несколько объединений.

Первая таблица (T1) - Hobby_ideas_articles, а записи выглядят так:

hobby_idea_article_id= 1,
hobby_id = 6
url= 'http://exo.example.com',
author = 'john@example.com'

hobby_idea_article_id= 2,
hobby_id = 3
url= 'http://exo.example2.com',
author = 'john@example.com'

hobby_idea_article_id= 3,
hobby_id = 6
url= 'http://exo.example3.com',
author = 'eric@example.com'

hobby_idea_article_id= 4,
hobby_id = 7
url= 'http://exo.example4.com',
author = 'john@example.com'

hobby_idea_article_id= 5,
hobby_id = 6
url= 'http://exo.example5.com',
author = 'nestor@example.com'

hobby_idea_article_id= 7,
hobby_id = 6
url= 'http://exo.example6.com',
author = 'ginger@example.com'

hobby_idea_article_id= 8,
hobby_id = 6
url= 'http://exo.example8.com',
author = 'derek@example.com'

hobby_idea_article_id= 9,
hobby_id = 6
url= 'http://exo.example9.com',
author = 'derek@example.com'

Во второй таблице (T2) с именем Past_Customer_sent_messages перечислены ВСЕ сообщения из прошлого, в частности, с информацией о том, кто ее отправил (customer_id ->, указывая на другую таблицу с именем Customers, которая не нужна).в этом текущем вопросе) и кому (recipient) и записи выглядят так:

past_customer_sent_message_id = 5
hobby_id = 7,
customer_id = 4,
recipient = "john@example.com",
sent_at= "2019-09-10 00:00:00"

past_customer_sent_message_id = 6
hobby_id = 999,
customer_id = 4,
recipient = "eric@example.com",
sent_at= "2019-09-18 00:00:00"

past_customer_sent_message_id = 7
hobby_id = 999,
customer_id = 4,
recipient = "nestor@example.com",
sent_at= "2019-07-18 00:00:00"

Даже если в настоящее время между T1 и T2 нет внешнего ключа, одна важная информация состоит в том, что T1 'author' это 'recipient", который появится на Т2, если клиент отправит ему сообщение.

Я не уверен, имеет ли это значение для данного вопроса, но есть таблица Customer (past_customer_sent_messages принадлежит customer, customer имеет несколько past_customer_sent_messages) иHobbies таблица (a Hobby_ideas_article принадлежит hobby, но hobby может иметь несколько Hobby_ideas_articles).

В моем файле javascript перед написанием оператора SQL я у меня есть 2 входа с уже заданными значениями, которые мне понадобятся в какой-то момент в SQL-выражении :

  • hobby_id = HOBBY_ID_INPUT_I_HAVE, например 6

  • customer_id = CUSTOMER_ID_INPUT_I_HAVE, например 4

Мне нужно извлечь ВСЕ записи из таблицы Hobby_ideas_articles (T1), гдеhobby_id = HOBBY_ID_INPUT_I_HAVE с 2 условиями / ограничениями :

  • условие 1: получатель (например: 'john@example.com '), независимо от того, ЧТО (то есть независимо от того, чтоhobby_id-S = plural, к которому он подключен через 'author' столбец на T1, и независимо от того, customer_id-S = plural к которому он подключен через 'recipient' на T2), ему никогда не отправлялось сообщение (sent_at coluна T2) в за последние 3 часа. Опять же, это относится ко всем прошлым сообщениям к этому 'recipient' (очень важно, что это означает не только для «авторов» T1, которые будут соответствовать hobby_id = HOBBY_ID_INPUT_I_HAVE = 6).

  • условие 2: автору не было сообщено в течение последних 30 дней клиентом, у которого customer_id = CUSTOMER_ID_INPUT_I_HAVE.Здесь это относится к этому конкретному клиенту (но через любое хобби!).

Часть, которую я нахожу особенно сложной в интеллектуальном плане, поскольку я хотел бы назвать ее ГДЕ hobby_id = HOBBY_ID_INPUT_I_HAVE (см. Ниже), но это неправильно, потому что тогда, как мне выполнить условие1который применяется ко ВСЕМ сообщениям и не должен применяться только к тем, у кого hobby_id = HOBBY_ID_INPUT_I_HAVE ... hard!Такая же сложность для условия 2

Может быть, я мог бы / должен добавить новый столбец с именем hobby_idea_id, который я бы поместил в T2, который будет внешним ключом между двумя таблицами, так как Past_Customer_sent_message в некотором родедля Hobby_ideas_article и Hobby_ideas_article имеет много Past_Customer_sent_messages?

Сегодня у меня есть это, но я даже не знаю, на что поместить предложение ON для объединения ... и не могу установить правильное утверждение.

SELECT             
          hia.query_result_id,
          hia.url,
          hia.title,
          hia.article_publication_day,
          hia.media_name,
          hia.author_full_name,
          hia.author_first_name,
          hia.author_last_name,
          hia.author_email,
          ces.sent_at
FROM
          Hobby_ideas_articles hia
LEFT JOIN
          Past_Customer_sent_messages ces
ON
          # WHAT CLAUSE ???
WHERE
          hia.hobby_id = HOBBY_ID_INPUT_I_HAVE AND         
          hia.author IS NOT NULL
          # more conditions but how to assert them ??

Как этого добиться?

Желаемый результат будет:

hobby_idea_article_id= 5,
hobby_id = 6
url= 'http://exo.example5.com',
author = 'nestor@example.com'
last_email_sent_at = "2019-07-18 00:00:00"

hobby_idea_article_id= 7,
hobby_id = 6
url= 'http://exo.example6.com',
author = 'ginger@example.com'
last_email_sent_at = null

hobby_idea_article_id= 8,
hobby_id = 6
url= 'http://exo.example8.com',
author = 'derek@example.com'
last_email_sent_at = null

Как вы можете видеть с моими входными значениями, приведенными в качестве примеров (hobby_id =6, customer_id = 4),

  • 'john@example.com 'и любые hobby_ideas, связанные с ним, не являются частью вывода, потому что Джон был сообщен customer_id = 4 в прошломУже 30 дней

  • 'Эрик' и связанные с ним hobby_ideas могли быть частью вывода, потому что Эрик был сообщен customer_id = 6 8 дней назад (а не customer_id = 4, которыйстоимостьмы нацелены), НО, к сожалению, это было исключено / отфильтровано из-за условия 1: в какой-то момент 2 часа назад он получил сообщение от другого клиента, поэтому он тоже отсутствует.

  • Нестор иСвязанные с ним hobby_idea находятся внутри вывода, потому что оба они не затронуты, потому что он действительно связан с hobby_id = 6, но его единственное письмо было отправлено несколько месяцев назад.

  • имбирь и связанный с ней hobby_idea находятся внутри вывода, потому что условия 1 и 2 нормальные, учитывая, что имбирь никогда никому не писал по электронной почте: там вообще нет сообщений, где она является получателем

  • Также обратите внимание, что если автор будет в выходных данных, но имеет несколько связанных с ним hobby_ideas, то я хочу только один, поэтому Дерек появляется только один раз, скажем, FIRST hobby_idea, но второй, который он один, удаляется из вывода

Отказ от ответственности : Я родом из Rails, где раньше у меня была ORM (Active Record), делающая все цепочки / объединения / проще больше automagic и я немного растерялся с настоящим оператором SQL, который я должен написать внутри своего лямбда-файла javascript aws.

1 Ответ

1 голос
/ 19 сентября 2019

Используйте recipient NOT IN (SELECT ...) и author NOT IN (SELECT ...), чтобы исключить участников, которые соответствуют вашим условиям 1 и 2.

SELECT             
          hia.query_result_id,
          hia.url,
          hia.title,
          hia.article_publication_day,
          hia.media_name,
          hia.author_full_name,
          hia.author_first_name,
          hia.author_last_name,
          hia.author_email,
          ces.sent_at
FROM
          Hobby_ideas_articles hia
LEFT JOIN
          Past_Customer_sent_messages ces
ON
          hia.author = ces.recipient 
            AND ces.recipient NOT IN (
                SELECT recipient
                FROM Past_Customer_sent_messages
                WHERE sent_at > DATE_SUB(NOW(), INTERVAL 3 HOUR)
            )
WHERE
          hia.hobby_id = HOBBY_ID_INPUT_I_HAVE AND         
          hia.author IS NOT NULL
          AND hia.author NOT IN (
            SELECT recipient
            FROM Past_Customer_sent_messages
            WHERE customer_id = CUSTOMER_ID_INPUT_I_HAVE
            AND sent_at > DATE_SUB(NOW(), INTERVAL 30 DAY)
          )

Условие ces должно быть в предложении ON, чтобы выВы получите sent_at = NULL для статей, у которых нет подходящих строк.

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