For your data, this query returns a result set ...
SELECT t.tweet_id , t.text , IFNULL(s.spam,t.spam) AS spam FROM tweets t LEFT JOIN ( SELECT tu.tweet_id, MAX(u.spam) AS spam FROM tweets_urls tu JOIN urls u ON u.url_id = tu.url_id WHERE u.spam = 1 GROUP BY tu.tweet_id ) s ON s.tweet_id = t.tweet_id
But we made some assumptions about what should be done when there are more than one line in tweets_url for several tweet_id, or when there is no corresponding URL, etc.
If you want the tweet to be marked as "spam = 1" when it is detected that the tweet matches ANY URL that is marked as "spam = 1", otherwise the tweet should be marked as "spam = 0". ..
This will set the spam column for each line in tweets based on this rule ...
UPDATE tweets t LEFT JOIN ( SELECT tu.tweet_id, MAX(u.spam) AS spam FROM tweets_urls tu JOIN urls u ON u.url_id = tu.url_id WHERE u.spam = 1 GROUP BY tu.tweet_id ) s ON s.tweet_id = t.tweet_id SET t.spam = IFNULL(s.spam,0)
If you want to leave only the spam column (leave it in accordance with the fact that it is installed), and ONLY want to update the row where the value is currently set to 0 and should be set to 1, in accordance with the "match url has spam = 1 ", you can do this:
UPDATE tweets t JOIN ( SELECT tu.tweet_id FROM tweets_urls tu JOIN urls u ON u.url_id = tu.url_id WHERE u.spam = 1 GROUP BY tu.tweet_id ) s ON s.tweet_id = t.tweet_id SET t.spam = 1 WHERE t.spam = 0
Please note that the predicate in the tweet table will ONLY update the lines with spam that is currently set to zero. Note that we do not need to refer to the value of the spam column from the URL table, we are already testing that it is 1, so we can use the literal 1 when assigning the value to the tweets.spam column. Also note that we are doing an INNER JOIN (and not a LEFT OUTER JOIN), so we will again update the rows that will be assigned the value 1.