【SQL】一个经典挑战,左连接时字段为null
下面这个查询,claims 表中 uuid 都有值,但是查询结果中 u.uuid 有时候有值,有时候是null。
SELECT q.id, u.uuid, q.created_at, q.name, q.phone_number, q.province_city, q.address, q.base64, u.role, u.avatar_base64 FROM "claims" q
LEFT JOIN "msm_users" u ON q.msm_user_uuid = u.uuid
WHERE q.status < 3
解释如下:
This is a classic behavior of a LEFT JOIN (or LEFT OUTER JOIN).
Here’s why you’re seeing NULL values for u.uuid (and all other columns from the msm_users table) sometimes:
LEFT JOINExplained:- A
LEFT JOINreturns all rows from the “left” table (which is"claims"aliased asqin your query). - It then tries to find matching rows in the “right” table (which is
"msm_users"aliased asu) based on theONcondition (q.msm_user_uuid = u.uuid). - If a match is found: The columns from
msm_users(likeu.uuid,u.role,u.avatar_base64) will contain the data from the matching user. - If NO match is found: The
LEFT JOINstill includes the row from theclaimstable, but for all columns that come from themsm_userstable, it will putNULLvalues.
- A
Why a match might not be found:
q.msm_user_uuidisNULL: If themsm_user_uuidcolumn in a specificclaimsrecord isNULL, thenq.msm_user_uuid = u.uuidcan never be true (asNULLdoesn’t equal anything, not even anotherNULLin standard SQL comparison), so no user will match.q.msm_user_uuidhas a value, but it doesn’t exist inmsm_users.uuid: This indicates a data integrity issue.- Perhaps a user was deleted from
msm_users, but theiruuidstill remains in someclaimsrecords. - Perhaps there was a typo or data entry error when populating
q.msm_user_uuid. - Perhaps
q.msm_user_uuidis a foreign key, but it’s not enforced, allowing “orphan”claimsrecords.
- Perhaps a user was deleted from
In summary: When u.uuid is NULL, it means that for that particular claims record, there was no corresponding msm_users record where msm_users.uuid matched claims.msm_user_uuid.
What you can do to investigate:
Check for
NULLforeign keys:SELECT COUNT(*) FROM "claims" WHERE msm_user_uuid IS NULL;If this count is greater than 0, these are the claims that will definitely result in
NULLforu.uuid.Check for non-existent foreign keys:
SELECT DISTINCT q.msm_user_uuid FROM "claims" q LEFT JOIN "msm_users" u ON q.msm_user_uuid = u.uuid WHERE u.uuid IS NULL AND q.msm_user_uuid IS NOT NULL;This query will show you
msm_user_uuidvalues from theclaimstable that are notNULL, but still don’t have a matching user in themsm_userstable. These are your “orphan” foreign keys.
If you always expect a user to exist and want to exclude claims without a user:
You should use an INNER JOIN instead of a LEFT JOIN:
SELECT q.id, u.uuid, q.created_at, q.name, q.phone_number, q.province_city, q.address, q.base64, u.role, u.avatar_base64
FROM "claims" q
INNER JOIN "msm_users" u ON q.msm_user_uuid = u.uuid
WHERE q.status < 3;
This query will only return rows where there is a successful match between claims.msm_user_uuid and msm_users.uuid. Claims that don’t have a matching user will be excluded from the result entirely.

浙公网安备 33010602011771号