MySQL - Select 具有 JOIN 但 WHERE 子句适用于复杂且不同的边界的数据
MySQL - Select data with a JOIN but with WHERE clauses applying to complex and distinct perimeters
我有一个 MySQL 5.6 数据库,无法进行复杂查询,(我认为)涉及多个连接。
第一个 table (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'
第二个 table (T2) 称为 Past_Customer_sent_messages
列出了过去的所有消息,特别是发送者的信息(customer_id
-> 指向另一个 table 称为 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"
如果客户向他发送消息,它将出现在 T2 上。
我不确定它对现在的问题是否重要,但是有一个 Customer
table(一个 past_customer_sent_messages
属于一个 customer
,一个 customer
有多个 past_customer_sent_messages
) 和一个 Hobbies
table (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
table (T1) 中检索所有记录,其中 hobby_id = HOBBY_ID_INPUT_I_HAVE
和 2 conditions/restrictions:
条件 1: 收件人(例如:'john@example.com
'),无论是什么(即无论 hobby_id-S = plural
是否已连接通过 T1 上的 'author'
列,无论它是通过 T2 上的 'recipient'
连接到的 customer_id-S = plural
,从未发送过消息(T2 上的 sent_at
列) 过去 3 小时。 同样,这适用于此 'recipient'
的所有过去消息(非常重要,这意味着不仅在 T1 'authors' 上匹配 hobby_id = HOBBY_ID_INPUT_I_HAVE = 6
).
条件 2: 作者在 过去 30 天 内没有收到 customer_id = CUSTOMER_ID_INPUT_I_HAVE
。在这里它适用于这个特定的客户(但适用于任何爱好!)。
我觉得这部分在智力上特别具有挑战性,因为我很想把它作为 WHERE hobby_id = HOBBY_ID_INPUT_I_HAVE
(见下文)但感觉不对,因为那样的话,我该如何实现适用于所有的条件 1消息,并且不应仅应用于那些 hobby_id = HOBBY_ID_INPUT_I_HAVE
...hard! condition2 难度相同
也许我 could/should 添加一个名为 hobby_idea_id
的新列,我将把它放在 T2 上,它将作为 2 table 之间的外键作为 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 都不是输出的一部分,因为 john 在过去 30 天内收到了 customer_id = 4 的消息已经
'Eric' 和与他相关的 hobby_ideas 可能是输出的一部分,因为 Eric 在 8 天前收到 customer_id=6 的消息(并且不是 customer_id=4,这是我们的目标值),但不幸的是 excluded/filtered 因为条件 1:他在 2 小时前的某个时间点收到另一位客户的消息,所以他也出去了。
nestor 和与他相关的 hobby_idea 在输出中,因为他不受两者影响,因为他确实与 hobby_id= 6 相关,但他唯一的邮件是几个月前发送。
ginger 和与她相关的 hobby_idea 在输出中,因为条件 1 和 2 都可以,因为 ginger 从未给任何人发过电子邮件:她是收件人的地方根本没有消息
另请注意,如果作者会出现在输出中但有多个 hobby_ideas 与他相关,那么我只想要一个,这就是为什么 derek 只出现一次的原因让我们说FIRST hobby_idea 但第二个他是一个从输出中删除
免责声明:我来自 Rails 背景,我曾经有 ORM(活动记录)使所有 chains/joins/ 更容易 automagic 并且现在的 SQL 声明有点迷失,我必须在我的 javascript aws lambda 文件中写入。
使用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
。
我有一个 MySQL 5.6 数据库,无法进行复杂查询,(我认为)涉及多个连接。
第一个 table (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'
第二个 table (T2) 称为 Past_Customer_sent_messages
列出了过去的所有消息,特别是发送者的信息(customer_id
-> 指向另一个 table 称为 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"
如果客户向他发送消息,它将出现在 T2 上。
我不确定它对现在的问题是否重要,但是有一个 Customer
table(一个 past_customer_sent_messages
属于一个 customer
,一个 customer
有多个 past_customer_sent_messages
) 和一个 Hobbies
table (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
table (T1) 中检索所有记录,其中 hobby_id = HOBBY_ID_INPUT_I_HAVE
和 2 conditions/restrictions:
条件 1: 收件人(例如:
'john@example.com
'),无论是什么(即无论hobby_id-S = plural
是否已连接通过 T1 上的'author'
列,无论它是通过 T2 上的'recipient'
连接到的customer_id-S = plural
,从未发送过消息(T2 上的sent_at
列) 过去 3 小时。 同样,这适用于此'recipient'
的所有过去消息(非常重要,这意味着不仅在 T1 'authors' 上匹配hobby_id = HOBBY_ID_INPUT_I_HAVE = 6
).条件 2: 作者在 过去 30 天 内没有收到
customer_id = CUSTOMER_ID_INPUT_I_HAVE
。在这里它适用于这个特定的客户(但适用于任何爱好!)。
我觉得这部分在智力上特别具有挑战性,因为我很想把它作为 WHERE hobby_id = HOBBY_ID_INPUT_I_HAVE
(见下文)但感觉不对,因为那样的话,我该如何实现适用于所有的条件 1消息,并且不应仅应用于那些 hobby_id = HOBBY_ID_INPUT_I_HAVE
...hard! condition2 难度相同
也许我 could/should 添加一个名为 hobby_idea_id
的新列,我将把它放在 T2 上,它将作为 2 table 之间的外键作为 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 都不是输出的一部分,因为 john 在过去 30 天内收到了 customer_id = 4 的消息已经
'Eric' 和与他相关的 hobby_ideas 可能是输出的一部分,因为 Eric 在 8 天前收到 customer_id=6 的消息(并且不是 customer_id=4,这是我们的目标值),但不幸的是 excluded/filtered 因为条件 1:他在 2 小时前的某个时间点收到另一位客户的消息,所以他也出去了。
nestor 和与他相关的 hobby_idea 在输出中,因为他不受两者影响,因为他确实与 hobby_id= 6 相关,但他唯一的邮件是几个月前发送。
ginger 和与她相关的 hobby_idea 在输出中,因为条件 1 和 2 都可以,因为 ginger 从未给任何人发过电子邮件:她是收件人的地方根本没有消息
另请注意,如果作者会出现在输出中但有多个 hobby_ideas 与他相关,那么我只想要一个,这就是为什么 derek 只出现一次的原因让我们说FIRST hobby_idea 但第二个他是一个从输出中删除
免责声明:我来自 Rails 背景,我曾经有 ORM(活动记录)使所有 chains/joins/ 更容易 automagic 并且现在的 SQL 声明有点迷失,我必须在我的 javascript aws lambda 文件中写入。
使用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
。