martes, 2 de abril de 2013

Programación en SQL Server - parte 3



En la entrada anterior vimos cómo funciona el INNER JOIN para cruzar la información de dos o más tablas, en esta entrada abordaremos el LEFT JOIN.

Supongamos que tenemos el siguiente query:

SELECT T1.Col1, T1.Col2
FROM Table1 T1
LEFT JOIN Table2 T2
ON T1.Col1 = T2.Col1

A la tabla Table1 se le considera tabla izquierda y a la tabla Table2 se le considera la tabla derecha, es importante tener esto en mente para poder identificar qué datos vamos a obtener del query.

LEFT JOIN devolverá todas las filas de la tabla izquierda y de la tabla derecha devolverá valores para sus columnas cuando se haya encontrado una correspondencia en el predicado ON, para aquellas filas de la tabla izquierda que no encuentren correspondencia en la tabla derecha, las columnas de la tabla derecha tendrán el valor NULL.

Por ejemplo, supongamos que tenemos las siguientes tablas:

CREATE TABLE Categories(
    Id TINYINT IDENTITY(1, 1),
    Name VARCHAR(10) NOT NULL,
    CONSTRAINT pkCategories PRIMARY KEY (Id)
)
GO
CREATE TABLE Products(
    Id TINYINT IDENTITY(1, 1),
    Id_Category TINYINT NOT NULL,
    Name VARCHAR(10) NOT NULL,
    CONSTRAINT pkProducts PRIMARY KEY (Id),
    CONSTRAINT fkProducts_Categories FOREIGN KEY (Id_Category) REFERENCES Categories (Id)
)
GO
INSERT INTO Categories (Name)
VALUES ('Category 1'), ('Category 2'), ('Category 3')
GO
INSERT INTO Products (Id_Category, Name)
VALUES (1, 'Product 1'), (1, 'Product 2'), (3, 'Product 3')


Podemos ver que la categoría "Category 2" no tiene productos, ¿qué pasa si nos pidieran un reporte donde mostremos la cantidad de productos que tiene cada categoría?, intentemos con el INNER JOIN y veamos el resultado:

SELECT C.Name, COUNT(*) AS ProductsCount
FROM Categories C
INNER JOIN Products P
ON C.Id = P.Id_Category
GROUP BY C.Name


El resultado es el siguiente:


Podemos ver que la categoría "Category 2" no aparece en el resultado, esto es debido a que INNER JOIN sólo mostrará aquellas filas que encontraron correspondencia directa y como no se encontró el Id de la categoría "Category 2" en la tabla Products, entonces no se toma en cuenta.

Cambiemos el query por un LEFT JOIN y veamos que ahora sí muestra el resultado tal como lo queremos:

SELECT C.Name, COUNT(*) AS ProductsCount
FROM Categories C
LEFT JOIN Products P
ON C.Id = P.Id_Category
GROUP BY C.Name


Veamos el resultado:


¿Qué pasó? ¡se supone que no hay productos en la categoría "Category 2"!, el problema radica en que COUNT(*) cuenta la fila, y como "Category 2" forma parte del resultado por ser tabla izquierda en un LEFT JOIN, entonces la cuenta, veamos el query sin el COUNT(*) y verifiquemos que en efecto hay una fila que tiene "Category 2":

SELECT C.Name AS Category, P.Name AS Product
FROM Categories C
LEFT JOIN Products P
ON C.Id = P.Id_Category


Veamos el resultado:


Aún cuando no tenemos un valor en la columna de la tabla derecha (Products) la función de agregación COUNT(*) devuelve 1 porque existe una fila que tiene "Category 2".    Vamos a cambiar nuestro query para que cuente los valores de la tabla derecha y así descarte los nulos:

SELECT C.Name, COUNT(P.Name) AS ProductsCount
FROM Categories C
LEFT JOIN Products P
ON C.Id = P.Id_Category
GROUP BY C.Name


El resultado será el siguiente:


¡Ahora sí!, este es justamente el resultado que estábamos buscando, la categoría "Category 2" no tiene productos y por lo tanto debe mostrar el número cero.

Espero te resulte de ayuda esta entrada y haya quedado claro cómo utilizar el LEFT JOIN, en la siguiente entrada veré una instrucción súper interesante llamada MERGE.

No hay comentarios.:

Publicar un comentario