22nd May 2023 Lectura de 11 minutos CTE vs. Subconsulta en SQL: ¿Cuál es la Diferencia? Jill Thornhill SQL CTE subconsulta Índice ¿Qué es una subconsulta? ¿Qué son las CTEs? ¿Cuáles son las Diferencias entre CTEs y Subconsultas? Sólo Subconsultas: Uso de Subconsultas en WHERE Sólo Subconsultas: Uso de Subconsultas en UPDATE Las CTEs hacen más legibles las consultas complejas ¿Qué son las ETC recursivas? CTE vs. Subconsulta ¿Qué son las Expresiones Comunes de Tabla (CTEs)? ¿Son lo mismo que las subconsultas? ¿Cuándo es necesario utilizar las CTE? Este artículo analiza las similitudes y diferencias entre las CTE y las subconsultas. Cuando presento a un estudiante las Expresiones Comunes de Tabla, su primera reacción es "¡Eso es sólo una subconsulta! ¿Por qué tengo que aprender eso?". Vamos a responder a esta pregunta viendo lo que se puede hacer con una subconsulta SQL y qué ventajas adicionales tiene utilizar una CTE. Si después de leer este artículo decides que te gustaría aprender a utilizar las CTE de SQL, LearnSQL.es te ofrece un completo curso de Expresiones Comunes de Tabla que cubre el tema en profundidad. Comenzando con ejemplos sencillos, trabajarás con conceptos difíciles como el procesamiento de árboles y gráficos. Cada tema cuenta con explicaciones y ejemplos paso a paso. Con 114 ejercicios interactivos, obtendrá mucha práctica. Probablemente necesitará unas 18 horas para completar el curso. ¿Qué es una subconsulta? Una subconsulta es una consulta anidada dentro de la consulta principal; esto se explica mejor viendo un ejemplo. Todos los ejemplos en este artículo utilizan SQL Server; la sintaxis puede ser ligeramente diferente en otros dialectos de SQL. Supongamos que la dirección quiere ofrecer un descuento a todos los clientes cuyas compras anuales hayan sido superiores a la media de todos los clientes. La consulta para extraer una lista de estos clientes podría tener este aspecto: SELECT account_no, name FROM customers WHERE annual_purchases > (SELECT AVG(annual_purchases) FROM customers); La consulta principal enumera los clientes y la subconsulta calcula las compras anuales medias de todos los clientes. La subconsulta no necesita un nombre (excepto cuando se trabaja en PostgreSQL). Si no estás familiarizado con las subconsultas, puedes echar un vistazo al curso SQL para principiantes de LearnSQL.es, que tiene una sección dedicada a las subconsultas. Puedes leer más sobre subconsultas en nuestra Guía para principiantes sobre la subconsulta SQL. Cómo Practicar las Subconsultas SQL te da algunas ideas sobre cómo poner en práctica estos conceptos. ¿Qué son las CTEs? Las Expresiones Comunes de Tabla son conjuntos de resultados con nombre que se definen al principio de una consulta y a los que ésta puede acceder como si fueran tablas. Supongamos que queremos comparar los salarios de los empleados con el salario medio de su función. La consulta podría tener este aspecto: WITH avg_salary AS ( SELECT role, avg(salary) AS average FROM employee GROUP BY role ) SELECT employee.role, name, salary, avg_salary FROM employee JOIN avg_salary ON avg_salary.role = employee.role ORDER BY role, name Los CTE se introducen mediante la palabra clave WITH, y los resultados se almacenan en una tabla temporal con nombre. En este ejemplo, los resultados de la CTE se almacenan en la tabla avg_salary, que es utilizada por la consulta principal para obtener el salario medio de cada función. De hecho, las CTE sencillas como ésta también podrían escribirse como subconsultas. El artículo "¿Qué es una CTE?" explica las CTE con más detalle. ¿Cuáles son las Diferencias entre CTEs y Subconsultas? Comenzaré por enumerar brevemente las principales diferencias, y luego examinaré algunas de ellas con más detalle. Las CTEs se definen al principio de la consulta, mientras que las subconsultas se definen en línea. Las CTEs siempre deben tener nombre. Sólo PostgreSQL insiste en que las subconsultas deben tener un nombre. Las CTEs pueden usarse recursivamente. Explicaré esto más adelante en el artículo. Las CTEs son mucho más legibles que las subconsultas cuando se está escribiendo un informe complejo. Una CTE puede utilizarse muchas veces dentro de una consulta, mientras que una subconsulta sólo puede utilizarse una vez. Esto puede hacer que la definición de la consulta sea mucho más corta, pero no se traducirá necesariamente en una mejora del rendimiento. Las subconsultas se pueden utilizar en una cláusula WHERE junto con las palabras clave IN o EXISTS, pero no se puede hacer esto con las CTE. Las subconsultas pueden utilizarse para recoger un único dato de una tabla con el fin de actualizar un valor de otra tabla. Algunas funcionalidades están limitadas únicamente a las subconsultas. Daré dos ejemplos en los que las subconsultas no pueden sustituirse por CTEs. En el primer ejemplo, la subconsulta forma parte de la cláusula WHERE. En el segundo, se utiliza para recoger un único valor de una tabla con el fin de actualizar otra. Como he mencionado anteriormente, SQL no permite utilizar CTEs para estas tareas. Sólo Subconsultas: Uso de Subconsultas en WHERE En el primer ejemplo, un banco guarda los detalles de todas las transacciones del día en una tabla llamada daily_trans. Los datos de esta tabla incluyen un número de cuenta, un código de transacción y un importe. La base de datos también tiene una tabla llamada transaction_typesy sus columnas incluyen el código de transacción y un indicador llamado debit_credit, que se establece en 1 para los tipos de transacción que abonan en la cuenta del cliente, y en 2 para los que cargan en la cuenta. Si el banco desea obtener una lista de todas las transacciones de crédito del día, la consulta podría tener este aspecto: SELECT account_no, tran_code, amount FROM daily_trans WHERE tran_code IN (SELECT tran_code FROM transaction_types WHERE debit_credit = 1); Este tipo de consulta sólo puede escribirse utilizando una subconsulta. Aquí no se podría sustituir la subconsulta por una CTE. Sólo Subconsultas: Uso de Subconsultas en UPDATE En el segundo ejemplo, el mismo banco tiene una tabla llamada customercuyas columnas incluyen un número de cuenta, un nombre de cliente y el número de empleado de la persona designada para la atención al cliente. El banco ha realizado una reorganización de responsabilidades y desea reasignar a la persona de soporte para algunos clientes. Para ello, ha creado una tabla llamada reassignments que contiene el número de identificación del antiguo empleado de soporte y el número de empleado de la persona de soporte que asumirá sus responsabilidades. Para llevar a cabo las reasignaciones, podríamos escribir una consulta como ésta: UPDATE customer SET support_person = (SELECT new_employee FROM reassignments WHERE old_employee = customer.support_person); Las CTEs hacen más legibles las consultas complejas Para ilustrar cómo las CTEs pueden hacer las cosas más fáciles de entender, tomemos una consulta que utiliza múltiples subconsultas y recodifiquémosla utilizando CTEs. Supongamos que tenemos una tienda que vende tres tipos de productos: libros, música y vídeos. El gerente quiere saber cuánto ha comprado cada cliente en cada categoría. El informe puede tener este aspecto: CustomerTotalBooksMusicVideos M. Mouse150604050 F. Flintstone90102060 Esta es una consulta que utiliza subconsultas para producir el informe: SELECT customer, sum(purchases) AS Total, total_books AS Books, total_music AS Music, total_videos AS Videos FROM sales JOIN (SELECT account_no, sum(purchases) AS total_books FROM sales WHERE product_type = 'Books' GROUP BY account_no) books ON books.account_no = sales.account_no JOIN (SELECT account_no, sum(purchases) AS total_music FROM sales WHERE product_type = 'Music' GROUP BY account_no) music ON music.account_no = sales.account_no JOIN (SELECT account_no, sum(purchases) AS total_videos FROM sales WHERE product_type = 'Videos' GROUP BY account_no) videos ON videos.account_no = sales.account_no GROUP BY customer ORDER BY customer Como puede ver, es bastante complicado. Y es difícil de seguir si alguien más necesita hacerle cambios más tarde. Veamos ahora qué aspecto tendría esta consulta si la reescribiéramos utilizando Expresiones Comunes de Tabla: WITH books AS ( SELECT customer, sum(purchases) AS total_books FROM sales WHERE product_type = 'Books' GROUP BY customer ), music AS ( SELECT customer, sum(purchases) AS total_music FROM sales WHERE product_type = 'Music' GROUP BY customer ), videos as ( SELECT customer, sum(purchases) AS total_videos FROM sales WHERE product_type = 'Videos' GROUP BY customer ) SELECT customer, sum(purchases) AS Total, total_books AS Books, total_music AS Music, total_videos AS Videos FROM sales JOIN books ON books.customer = sales.customer JOIN music ON music.customer = sales.customer JOIN videos ON videos.customer = sales.customer GROUP BY customer ORDER BY customer La mayoría de la gente encontrará esta segunda versión mucho más fácil de entender, aunque ambas consultas producen exactamente los mismos resultados. ¿Qué son las ETC recursivas? Antes he dicho que sólo las CTEs pueden ser recursivas. Entonces, ¿qué es una consulta recursiva? Las consultas recursivas le permiten navegar por datos jerárquicos y producir informes adecuados para datos de tipo árbol y gráfico. Algunos ejemplos de datos jerárquicos son En una organización, un empleado puede depender de un subgerente; el subgerente depende de un gerente, y el gerente depende del gerente. En la fabricación, un producto puede estar formado por varios componentes. Cada componente también puede estar formado por muchos subcomponentes, y los subcomponentes pueden estar hechos de varias materias primas. Veamos un ejemplo. Una heladería tiene varios productos en su carta. Por ejemplo, un banana split se compone de plátanos, salsa de chocolate y helado. Pero la salsa de chocolate también tiene varios ingredientes. Puede llevar cacao en polvo, azúcar y otros ingredientes. El propietario quiere una lista completa de cada plato del menú seguida de todos sus ingredientes. Parte de la lista puede tener este aspecto: ItemIngredient Menu150 Menu > Banana SplitBanana Split Menu > Banana Split > BananaBanana Menu > Banana Split > Chocolate SauceChocolate Sauce Menu > Banana Split > Chocolate Sauce > CocoaCocoa Menu > Banana Split > Chocolate Sauce > MargarineMargarine Menu > Banana Split > Chocolate Sauce > SugarSugar Menu > Banana Split > Ice cream - AmericanIce cream - American Menu > Banana Split > Ice cream - American > CreamCream Menu > Banana Split > Ice cream - American > MilkMilk Menu > Banana Split > Ice cream - American > SugarSugar Menu > Banana Split > Ice cream - American > Vanilla ExtractVanilla Extract Menu > Choc Nut SundaeChoc Nut Sundae Menu > Choc Nut Sundae > Chocolate SauceChocolate Sauce Menu > Choc Nut Sundae > Chocolate Sauce > CocoaCocoa Menu > Choc Nut Sundae > Chocolate Sauce > MargarineMargarine Menu > Choc Nut Sundae > Chocolate Sauce > SugarSugar Menu > Choc Nut Sundae > Ice cream - RichIce cream - Rich Menu > Choc Nut Sundae > Ice cream - Rich > CreamCream Menu > Choc Nut Sundae > Ice cream - Rich > EggEgg Menu > Choc Nut Sundae > Ice cream - Rich > SugarSugar Menu > Choc Nut Sundae > Ice cream - Rich > Vanilla ExtractVanilla Extract Menu > Choc Nut Sundae > Mixed NutsMixed Nuts En la base de datos tenemos dos tablas: La tabla Item contiene una lista de cada plato del menú y de cada ingrediente. La tabla Bill_of_materials contiene los enlaces entre cada artículo y sus ingredientes. La tabla Items contiene esta información: idDescriptionunitprice 15MenuNULLNULL 14EggEach0.1 13BananaEach0.2 12Banana SplitEach2 11MargarineKg4 10CocoaKg10 9Chocolate SauceLitre8 8Mixed NutsKg2 7Choc Nut SundaeEach1.5 6Ice Cream - RichLitre6 5SugarKg2 4Vanilla ExtractBottle1 3MilkLitre1.5 2CreamLitre4 1Ice Cream - AmericanLitre5 He aquí algunos ejemplos de entradas en la Bill_of_materials tabla. La columna item_id contiene un enlace al artículo principal de la tabla. Items mientras que component_id contiene un enlace a uno de sus ingredientes. Por lo tanto, la primera entrada muestra que el artículo 10: Cacao es un ingrediente del artículo 9: Salsa de chocolate. iditem_idcomponent_idquantity 19100.25 29110.25 3950.25 4120.5 A continuación se muestra la consulta recursiva utilizada para recorrer esta información. La consulta se ha escrito en SQL Server; en otros dialectos sería ligeramente diferente. WITH menu_ingredients (id, path, description, item_id) AS ( SELECT CAST (id AS bigint), CAST (description as varchar (255)), CAST ('' AS varchar(40)), CAST (id AS bigint) FROM items WHERE description = 'Menu' UNION ALL SELECT CAST (bom.component_id AS bigint), CAST (m.path + ' > ' + i.description AS varchar(255)), i.description, CAST (bom.item_id AS bigint) FROM menu_ingredients m, bill_of_materials bom JOIN items i ON i.id = bom.component_id WHERE bom.item_id = m.id ) SELECT path, description FROM menu_ingredients ORDER BY path Una explicación completa de lo que está pasando aquí está fuera del alcance de este artículo, pero voy a explicar rápidamente los conceptos básicos. En pocas palabras, cuando se añade una fila al conjunto de resultados en una consulta recursiva, ésta puede "ver" la fila anterior y utilizarla para recoger información que puede utilizarse para encontrar la siguiente fila. Esta consulta comienza por la entrada de nivel superior de la lista de materiales: el propio menú. A partir de ahí, puede recorrer todas sus filas "hijas", es decir, los ingredientes que lo componen. Y cada ingrediente puede recoger sus propias filas hijas, si las tiene. Para una explicación más detallada de la recursividad, consulte ¿Qué es una CTE recursiva en SQL? Y como mencioné anteriormente, las consultas recursivas están completamente cubiertas en LearnSQL.es's Common Table Expressions course. CTE vs. Subconsulta En resumen, elija una CTE cuando: Desea que una consulta compleja sea más legible. Necesita utilizar una consulta recursiva. Elija una subconsulta cuando: Está utilizando las palabras clave de la cláusula WHERE IN o EXISTS para recoger los criterios de selección de otra tabla. Desea seleccionar un único dato de otra tabla como nuevo valor de un campo en una sentencia UPDATE. En cualquier otra circunstancia, puede elegir la que le resulte más cómoda. Y si necesitas practicar con CTEs o subconsultas, puedes probar el sitio web Ejercicios prácticos de SQL que contiene cientos de ejercicios interactivos que te ayudarán a consolidar tus conocimientos. ¡Feliz aprendizaje! Tags: SQL CTE subconsulta