Skillnaden är att när du använder exists - frågan inuti beror vanligtvis på huvudfrågan (genomsnittet använder kolumner från den och kan därför inte köras separat) och därför kontrollerar den för varje rad i huvudfrågan om någon data som hämtas av underfrågan finns eller inte.
Problemet med din första fråga är att underfrågan inuti existerande block inte i vilket fall som helst beror på huvudfrågekolumnerna, det är en separat fråga som alltid returnerar en rad med 1 , så resultatet av exists för vilken rad som helst i huvudfrågan kommer alltid att vara true . Så din första fråga motsvarar bara
SELECT distinct(company_id)
FROM user
WHERE user.user_id = 123
AND user.company_id IS NOT NULL
Se även fiol