Um SELF JOIN não é, de forma alguma, uma palavra-chave SQL, mas apenas um termo comum para a situação em que uma tabela é unida a si mesma. Na prática, isso é feito com tipos normais de JOIN, mais frequentemente INNER JOIN ou LEFT JOIN, dependendo da lógica necessária. Isso é útil para consultar dados hierárquicos ou comparar linhas dentro da mesma tabela.
Para realizar um self-join, você deve tratar uma tabela como se fossem duas tabelas separadas. Para fazer isso, você deve usar aliases de tabela para dar a cada instância da tabela um nome exclusivo. Sem aliases, o banco de dados não saberá qual coluna pertence a qual instância da tabela.
Visualização (Hierarquia de Funcionários):
Imagine uma tabela employee onde cada linha tem um manager_id que aponta para o employee_id de seu supervisor.
Tabela A (Funcionários) Tabela B (Gerentes)
+----+-------+---------+ +----+-------+
| id | nome | mgr_id | | id | nome |
+----+-------+---------+ +----+-------+
| 1 | Alice | NULL | | 1 | Alice |
| 2 | Bob | 1 | <-> | 1 | Alice | (O gerente de Bob é Alice)
| 3 | Carol | 1 | <-> | 1 | Alice | (A gerente de Carol é Alice)
+----+-------+---------+ +----+-------+
SELECT
e.name AS nome_funcionario,
m.name AS nome_gerente
FROM
funcionario AS e
LEFT JOIN
funcionario AS m ON e.manager_id = m.id;
funcionario AS e: A primeira instância (representando os funcionários).funcionario AS m: A segunda instância (representando os gerentes).ON e.manager_id = m.id: A condição que os vincula.Suponha que queiramos encontrar pares de filmes que tenham exatamente a mesma duração (length). Podemos unir a tabela film a si mesma.
SELECT
f1.title AS filme_1,
f2.title AS filme_2,
f1.length
FROM
film AS f1
INNER JOIN
film AS f2 ON f1.length = f2.length
WHERE
f1.film_id <> f2.film_id -- Garante que não combinemos um filme com ele mesmo
LIMIT 10;
A condição f1.film_id <> f2.film_id é crítica. Sem ela, cada filme corresponderia a si mesmo (pois tem a mesma duração que si mesmo).
Se quisermos ver quais clientes moram no mesmo endereço (com base no address_id neste exemplo simplificado):
SELECT
c1.first_name AS nome_1,
c1.last_name AS sobrenome_1,
c2.first_name AS nome_2,
c2.last_name AS sobrenome_2,
c1.address_id
FROM
customer AS c1
INNER JOIN
customer AS c2 ON c1.address_id = c2.address_id
WHERE
c1.customer_id < c2.customer_id; -- Use '<' em vez de '<>' para evitar pares duplicados (A-B e B-A)
JOIN, como INNER JOIN ou LEFT JOIN.ON para definir o relacionamento entre as linhas (ex: hierarquia ou atributos compartilhados).id1 <> id2 ou id1 < id2 para evitar combinar uma linha consigo mesma ou retornar pares redundantes. No caso de LEFT JOIN, parte dessa lógica pode ficar não apenas em WHERE, mas também na condição ON.