Professional Documents
Culture Documents
SELECT sentencia::=[WITH <expresion_tabla_comun> [,...n]] Empezaremos por ver las consultas más simples, basadas en una sola tabla y nos
limitaremos a la siguiente sintaxis:
<expresion_consulta>
<expresion_consulta> ::=
3.2. Origen de datos FROM
{<especificacion_consulta> | ( < expresion_consulta > ) }
De la sintaxis anterior, el elemento <origen> indica de dónde se va a extraer la información
[ {UNION [ALL]|EXCEPT|INTERSECT} y se indica en la cláusula FROM, es la única cláusula obligatoria. En este tema veremos un
origen de datos basado en una sola tabla.
<especificacion_consulta> | (<expresion_consulta>) [...n
]
La sintaxis será la siguiente:
]
| {nombre_tabla|nombre_vista|alias_tabla}.*
Cuando no se definen esquemas, SQL-Server crea uno por defecto en cada base de datos
denominado dbo. | { [{nombre_tabla|nombre_vista|alias_tabla}.]
{nb_columna|$IDENTITY|$ROWGUID}
Opcionalmente podemos definir un nombre de alias.
|<expresion>
Un nombre de alias (alias_tabla) es un nombre alternativo que se le da a la tabla dentro de
la consulta. }[[AS] alias_columna]
| alias_columna = <expresion>
Si se define un nombre de alias, dentro de la consulta, será el nombre a utilizar para
referirnos a la tabla, el nombre original de la tabla ya no tendrá validez. } [ ,...n ]
Se utilizan los nombres de alias para simplificar los nombres de tablas a veces largos y
también cuando queremos combinar una tabla consigo misma; ya volveremos sobre los alias Separamos la definición de cada columna por una coma y las columnas del resultado
de tabla cuando veamos consultas multitabla. aparecerán en el mismo orden que en la lista de selección.
La palabra AS no añade ninguna operatividad, está más por estética. Para cada columna del resultado su tipo de datos, tamaño, precisión y escala son los
mismos que los de la expresión que da origen a esa columna.
Podemos escribir:
Podemos definir las columnas del resultado de varias formas, mediante:
SELECT ...
Una expresión simple:
FROM tabla1 Sacamos los datos de la tabla tabla1
o una referencia a una función.
SELECT ...
o una variable local
FROM tabla1 t1 Sacamos los datos de la tabla tabla1 y le
asignamos un alias de tabla: t1 o una constante
FROM tabla1 AS t1 Es equivalente a la sentencia anterior. Una subconsulta escalar, que es otra instrucción SELECT que devuelve un único valor y
se evalúa para cada fila del origen de datos (esto no lo veremos de momento).
Si la tabla o la vista están en otra base de datos del mismo equipo que está ejecutando la Una expresión compleja generada al usar operadores en una o más expresiones
instancia de SQL Server, se utiliza el nombre cualificado con el formato simples.
nbBaseDatos.nbEsquema.nbTabla.
La palabra clave *.
Si la tabla o la vista están fuera del servidor local en un servidor vinculado, se utiliza un La asignación de variables con el formato @variable_local = expresión.
nombre de cuatro partes con el formato nbservidor.catalogo.nbEsquema.nbTabla.
Volveremos más adelante sobre las conexiones remotas. La palabra clave $IDENTITY.
nombre oficina contrato El alias de columna se indica mediante la cláusula AS. Se escribe el nuevo texto tal cual sin
comillas siguiendo las reglas de los identificadores.
Antonio Viguer 12 1986-10-20
Alvaro Jaumes 21 1986-12-10 Ejemplo:
Juan Rovira 12 1987-03-01
José González 12 1987-05-19
SELECT numclie,nombre AS nombrecliente
Vicente Pantalla 13 1988-02-12
FROM clientes;
Luis Antonio 11 1988-06-14
Jorge Gutiérrez 22 1988-11-14
Ana Bustamante 21 1989-10-12 El resultado será :
María Sunta 11 1999-10-12
Juan Victor NULL 1990-01-13 Numclie nombrecliente
Hemos cualificado la columna precio aunque no es necesario en este caso. en vez de:
El resultado sería:
Lic. Vladimir Cotaquispe Gutiérrez. 5 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 6 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Numclie nombre DATEPART Devuelve un entero que corresponde a la parte de la fecha solicitada.
La palabra AS es opcional. Devuelve un valor datetime nuevo que resulta de sumar un intervalo de
DATEADD
tiempo a una fecha especificada.>
SELECT numclie,nombre nombrecliente
DATEDIFF Devuelve el nº de intervalos que hay entre dos fechas.
FROM clientes;
Función Descripción
Nota importante: Este nombre de alias se podrá utilizar en la lista de selección y en la Devuelve el valor de código ASCII del carácter situado más a la izquierda
cláusula ORDER BY pero no en la cláusula WHERE. ASCII
de una expresión de caracteres.
CHAR Devuelve el carácter ASCII del entero indicado.
3.6. Funciones NCHAR Devuelve el carácter Unicode del entero indicado.
UNICODE Devuelve el entero que se corresponde al carácter Unicode indicado.
Existen funciones que podemos utilizar en la lista de selección, e incluso en otras cláusulas
que veremos más adelante, como el WHERE. Las principales funciones son las siguientes: Devuelve el total de caracteres de una cadena, excluidos los espacios en
LEN
blanco finales.
LTRIM Devuelve una cadena tras quitarle los espacios en blanco iniciales.
Funciones de fecha:
RTRIM Devuelve una cadena tras quitarle los espacios en blanco finales.
Función Descripción LEFT Devuelve los N últimos caracteres de una cadena.
RIGHT Devuelve los N primeros caracteres de una cadena.
GETDATE Devuelve la fecha actual. SUBSTRING Devuelve parte de una expresión.
LOWER Devuelve la cadena convertida a minúsculas.
GETUTCDATE Devuelve la hora UTC. UPPER Devuelve la cadena convertida a mayúsculas.
REPLACE Reemplaza una determinada cadena.
Lic. Vladimir Cotaquispe Gutiérrez. 7 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 8 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Elimina el número de caracteres especificado e inserta otro conjunto de El resultado será:
STUFF
caracteres en el punto de inicio indicado.
Devuelve una cadena Unicode con los delimitadores agregados para ciudad region superavit
QUOTENAME convertirla en un identificador delimitado válido de Microsoft SQL Server
2005.
Valencia este 11800,00
SPACE Devuelve una cadena de espacios repetidos.
STR Devuelve una cadena de caracteres a partir de datos numéricos. Alicante este -6500,00
REPLICATE Repite una cadena N veces.
REVERSE Devuelve una cadena invertida. Castellon este 1800,00
Devuelve la posición inicial de la expresión especificada en una cadena
CHARINDEX
de caracteres.
Badajoz oeste 11100,00
Devuelve la posición inicial de la primera repetición de un patrón en la
PATINDEX expresión especificada, o ceros si el patrón no se encuentra, en todos los
tipos de datos de texto y caracteres. A Coruña oeste -11400,00
Además de las columnas que provienen directamente de la tabla origen, una consulta SQL FROM productos;
puede incluir columnas calculadas cuyos valores se evalúan a partir de una expresión.
La expresión puede contener cualquier operador válido (+, -, *, /, &…), cualquier función El resultado sería:
válida, nombres de columnas del origen de datos, nombres de parámetros o constantes y para
combinar varias operaciones se pueden utilizar los paréntesis.
Idfab idproducto descripcion valoracion
Ejemplos de columnas calculadas:
aci 41001 arandela 160,66
Listar la ciudad, región y el superávit de cada oficina. Consideraremos el superávit como el
volumen de ventas que se encuentran por encima o por debajo del objetivo de la oficina. aci 41002 bisagra 133,60
FROM oficinas;
Lic. Vladimir Cotaquispe Gutiérrez. 9 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 10 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
aci 41004 art t4 170,97 21 tiene ventas de 83600,00
22 tiene ventas de 18600,00
aci 4100x junta 9,62 23 tiene ventas de NULL
24 tiene ventas de 15000,00
aci 4100y extractor 722,00 26 tiene ventas de NULL
28 tiene ventas de 0,00
aci 4100z mont 735,00
El incluir una constante como columna en la lista de selección puede parecer inútil (se
bic 41003 manivela 19,56 repetirá el mismo valor en todas las filas) pero veremos más adelante que tiene utilidad en
ciertos casos.
bic 41089 rodamiento 175,50
También podemos utilizar la sintaxis:
alias_columna = <expresion>
Listar el nombre, mes y año del contrato de cada vendedor.
Ejemplo:
SELECT nombre, MONTH(contrato) AS [Mes de contrato], YEAR(contrato) AS
[Año de contrato]
SELECT oficina, superavit = ventas-objetivo
FROM empleados;
SELECT *
El resultado sería:
FROM oficinas;
oficina ventas
11 tiene ventas de 69300,00 Obtener todos los datos y el superávit de cada oficina.
12 tiene ventas de 73500,00
13 tiene ventas de 36800,00
Lic. Vladimir Cotaquispe Gutiérrez. 11 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 12 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
FROM oficinas;
Podemos indicar una columna o varias separadas por una coma, la columna de ordenación
se especifica mediante el nombre de columna en el origen de datos o su posición dentro de la
También podemos cualificar el * con un nombre de tabla, de vista o un alias de tabla: lista de selección. Si utilizamos el nombre de columna, no hace falta que la columna aparezca
en la lista de selección. Si utilizamos la posición es la posición de la columna dentro de la lista
de selección empezando en 1.
SELECT oficinas.*
Por defecto la filas se ordenarán en modo ascendente (ASC), de menor a mayor; si
FROM oficinas;
queremos invertir ese orden añadimos detrás de la columna la palabra DESC.
oficinas.* se interpreta como: todas las columnas de la tabla oficinas. Si la columna de ordenación es alfanumérica, las filas se ordenarán por orden alfabético.
La palabra clave $IDENTITY se interpreta como la columna de la tabla que tiene la Mostrar las ventas de cada oficina, ordenadas por orden alfabético de región y dentro de
propiedad IDENTITY (la columna de identidad que vimos en un tema anterior). cada región por ciudad.
FROM oficinas
SELECT $IDENTITY, nombre, apellidos
ORDER BY region, ciudad;
FROM usuarios;
Da como resultado:
Es equivalente a:
Oficina region ciudad ventas
SELECT codigo, nombre, apellidos 24 centro Aranjuez 15000,00
23 centro Madrid NULL
FROM usuarios;
12 este Alicante 73500,00
13 este Castellón 36800,00
La palabra clave $ROWGUID se interpreta como la columna de la tabla que tiene la 11 este Valencia 69300,00
propiedad ROWGUIDCOL y se puede utilizar de la misma forma que $IDENTITY.
28 este Valencia 0,00
26 norte Pamplona NULL
3.10. Ordenación de las filas del resultado ORDER BY 22 oeste A Coruña 18600,00
Si queremos que las filas del resultado de la consulta aparezcan ordenadas, lo podemos 21 oeste Badajoz 83600,00
indicar mediante la cláusula ORDER BY.
Listar las oficinas de manera que las oficinas de mayores ventas aparezcan en primer lugar.
Lic. Vladimir Cotaquispe Gutiérrez. 13 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 14 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
este Alicante -6500,00
SELECT ciudad, region, ventas
este Valencia -90000,00
FROM oficinas norte Pamplona NULL
ORDER BY ventas DESC; oeste Badajoz 11100,00
oeste A Coruña -11400,00
Listar las oficinas clasificadas en orden descendente de rendimiento de ventas, de modo que Listar los nº de empleado de los directores de las oficinas.
las de mayor rendimiento aparezcan las primeras.
SELECT dir
SELECT ciudad, region, ventas-objetivo
FROM oficinas;
FROM oficinas
105
SELECT region, ciudad, (ventas-objetivo) AS superavit
108
FROM oficinas
108
ORDER BY region, superavit DESC;
108
108
Resultado:
NULL
Region ciudad superavit NULL
centro Aranjuez -10000,00
centro Madrid NULL
Si un mismo empleado dirige varias oficinas (por ejemplo el 108), su código aparece repetido
este Valencia 11800,00 en el resultado. Para evitarlo modificamos la consulta:
este Castellón 1800,00
Lic. Vladimir Cotaquispe Gutiérrez. 15 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 16 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
FROM oficinas;
La cláusula TOP indica que en el resultado no deben aparecer todas las filas resultantes
sino un cierto número de registros, las n primeras. Si la consulta incluye la cláusula ORDER BY,
dir se realiza la ordenación antes de extraer los n primeros registros.
NULL
La expresión representa ese número n y debe devolver un número entero sin signo.
104
106
SELECT * FROM productos:
108
Los que se eliminan son valores duplicados de filas del resultado, por ejemplo:
FROM oficinas;
dir region
NULL este
NULL norte
Si ordenamos por ventas:
104 este
108 oeste
Ahora el 108 aparece dos veces porque las dos filas donde aparece no son iguales (porque
tienen distinta región).
NOTA: La cláusula DISTINCT hace que la consulta tarde algo más en ejecutarse debido al
proceso adicional de buscar y eliminar las repeticiones, por lo que se aconseja utilizarla
únicamente cuando sea imprescindible.
Obtenemos los 3 primeros registros: Devuelve las 10 peores oficinas en cuanto a ventas: ordenamos las oficinas por ventas de
menor a mayor y sacamos las 10 primeras.
FROM productos
La cláusula WHERE se emplea para especificar las filas que se desean recuperar del origen
de datos.
WHERE <condicion_búsqueda>
<condicion_búsqueda> ::=
{ [NOT]<predicado>
Se incluyen en el resultado todos los registros que tienen ventas iguales al último registro. |(<condicion_búsqueda>)
Otro ejemplo: }
FROM empleados
3.14. Predicados
WHERE ventas > cuota
En SQL tenemos 7 tipos de predicados, condiciones básicas de búsqueda:
Test de valor nulo (IS NULL). 103 Juan Rovira 28600,00 27500,00
Compara el valor de una expresión con el valor de otra. Para la comparación se pueden
emplear = , <> , !=, < , <= , !<, > , >= ,!> Las columnas que aparecen en el WHERE no tienen por qué aparecer en la lista de
selección, esta instrucción es igual de válida:
Sintaxis:
una constante,
SELECT numemp, nombre, contrato
una función (inclusive la función CASE),
FROM empleados
una variable,
Lic. Vladimir Cotaquispe Gutiérrez. 21 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 22 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Pertenencia a un intervalo. BETWEEN
WHERE contrato < '01/01/1988';
SELECT oficina
SELECT numemp, nombre, ventas
FROM oficinas
FROM empleados
WHERE dir = 108;
WHERE ventas >= 20000 AND ventas <=100000;
Lic. Vladimir Cotaquispe Gutiérrez. 23 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 24 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Test de pertenencia a conjunto IN
WHERE oficina = NULL;
Obtener los empleados que trabajan en las oficinas 11, 20 o 22: WHERE oficina IS NULL;
FROM empleados
Test de valor nulo IS NULL
WHERE oficina IS NOT NULL;
Lic. Vladimir Cotaquispe Gutiérrez. 25 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 26 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
108 Ana Bustamante 21 numemp nombre
Se utiliza cuando queremos comparar el valor de una columna con un patrón en el que se
utilice caracteres comodines. SELECT numemp,nombre
FROM empleados
<expression> [NOT] LIKE <patron> [ESCAPE 'car_escape']
WHERE nombre LIKE ‘%on%’;
Con expresión indicamos el valor a comparar (normalmente será el nombre de una columna)
y patrón es la cadena que se busca. El patrón es de tipo texto y tiene que escribirse entre numemp nombre
comillas simples. Dentro del patrón podemos utilizar los siguientes comodines:
101 Antonio Viguer
% representa cualquier cadena de cero o más caracteres. 104 José González
FROM empleados
Obtiene los nombres que contienen on.
WHERE nombre LIKE ‘An%’;
_ representa cualquier carácter (sólo uno).
numemp nombre
SELECT numemp,nombre
101 Antonio Viguer
FROM empleados
108 Ana Bustamante
WHERE nombre LIKE '__a%';
numemp nombre
Obtiene todos los nombres que empiecen por An. 108 Ana Bustamante
FROM empleados
Obtiene los nombres cuya tercera letra sea una a (en el patrón tenemos dos caracteres
WHERE nombre LIKE ‘%z’; subrayado).
Es equivalente a escribir:
SELECT numemp,nombre
FROM empleados
SELECT numemp,nombre
WHERE nombre LIKE '%[_]%';
FROM empleados
FROM empleados
SELECT numemp,nombre
WHERE nombre LIKE '%!_%' ESCAPE '!';
FROM empleados
WHERE nombre LIKE '[^a-d]%'; Se utiliza para buscar, coincidencias exactas o aproximadas con palabras o frases, palabras
próximas a otra dada en una cierta distancia, o coincidencias ponderadas.
Obtienen los nombres que no empiecen por a, b, c ni d. Una palabra o una frase.
Es importante tener en cuenta que dentro del patrón el espacio en blanco es considerado El prefijo de una palabra o una frase.
como un carácter más, si colocamos dos espacios en el patrón, se buscarán dos espacios en el
campo. Una palabra cerca de otra palabra.
Una palabra que sea derivada de otra (por ejemplo, las palabras controles,
Si queremos incluir en el patrón uno de los caracteres comodines y que no sea interpretado controladores, controlando y controlado son derivadas de control).
como un comodín, sino como un carácter normal, lo tenemos que encerrar entre corchetes o
utilizar un carácter de escape. Una palabra que sea un sinónimo de otra palabra usando el diccionario de sinónimos
(por ejemplo, la palabra metal puede tener sinónimos como aluminio y acero).
[ESCAPE 'car_escape']
Lic. Vladimir Cotaquispe Gutiérrez. 29 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 30 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
CONTAINS } [ ...n ]
( { nombre_columna | (lista_columnas) | * }
) ( { {
} } [ ,...n ]
< AND NOT > ::= { AND NOT | & !} Lista_columnas indica una lista de columnas separadas por comas.
< OR > ::= { OR | | }
El asterisco ( * ) especifica que todas las columnas de la tabla válidas para búsquedas de
< termino_simple > ::= texto se deben utilizar en la condición de búsqueda. Las columnas de la cláusula CONTAINS
deben proceder de una sola tabla. Si en la cláusula FROM hay más de una tabla, * se tiene que
palabra | " frase " especificar con el nombre de la tabla.
< proximo > ::= Frase es una o varias palabras con espacios entre cada una de ellas.
{ < termino_simple > | < prefijo > } Generador especifica la coincidencia de palabras cuando los términos simples incluyen
{ { NEAR | ~ } variaciones de la palabra original que se busca para buscar palabras derivadas.
THESAURUS especifica que se utiliza el diccionario de sinónimos correspondiente al idioma Idioma Es el idioma en que el usuario genera la consulta.
de texto de la columna o el idioma especificado en la consulta. El patrón o patrones más largos Condición búsqueda especifica el texto que se va a buscar y las condiciones para
de termino_simple se hacen coincidir con el diccionario de sinónimos y se generan términos
obtener coincidencias.
adicionales para expandir o reemplazar el patrón original.
Cadena_freetext es el texto que se va a buscar en nombre_columna. Se puede
Próximo especifica una coincidencia de palabras o frases que deben estar próximas entre escribir cualquier texto, incluidas palabras, frases y oraciones. Se generarán
sí. funciona de forma similar al operador AND: ambos requieren que existan varias palabras o coincidencias si se encuentra algún término o las formas de algún término en el índice
frases en la columna examinada. de texto.
NEAR | ~ indica que la palabra o frase situada a la izquierda del operador NEAR o ~ tiene Si cadena_freetext se incluye entre comillas dobles, se realiza una búsqueda de frases
que estar bastante cerca de la palabra o frase situada a la derecha del operador NEAR o ~. Se coincidentes, por lo que no se extraen las desinencias ni se utiliza el diccionario de
pueden encadenar varios términos de proximidad. sinónimos.
<valor_ponderado> especifica que las filas coincidentes (devueltas por la consulta) coinciden Las consultas de búsqueda de texto que utilizan FREETEXT son menos precisas que las
con una lista de palabras y frases a las que se asigna opcionalmente un valor ponderado. consultas de texto que utilizan CONTAINS. El motor de búsqueda de texto de SQL Server
WEIGHT(peso) especifica el valor de ponderación como un número entre 0,0 y 1,0. Cada identifica las palabras y las frases importantes. No se le da significado especial a ninguna de las
componente de < valor_ponderado > puede incluir un peso. palabras clave reservadas
Es un predicado que se utiliza para buscar en columnas que contengan tipos de datos En una cláusula WHERE podemos incluir una condición de búsqueda simple (formada por
basados en caracteres valores que coincidan con el significado y no literalmente con las un solo predicado) o compuesta (formada por la combinación de predicados unidos por los
palabras de la condición de búsqueda. Cuando se utiliza FREETEXT, el motor de consulta de operadores lógicos NOT, AND, OR).
texto realiza internamente las siguientes acciones en freetext_string, asigna a cada uno de los
términos un peso y busca las coincidencias. Cuando la condición incluye varios operadores lógicos, el orden de prioridad de estos
operadores es:
Separa la cadena en palabras individuales basándose en límites de palabras (separación de
palabras). NOT (el más alto),
Genera formas no flexionadas de las palabras (lematización). seguido de AND y OR (estos dos al mismo nivel).
Identifica una lista de expansiones o reemplazos de los términos basándose en Como siempre, se pueden utilizar paréntesis para alterar esta prioridad en una condición de
coincidencias en el diccionario de sinónimos. búsqueda.
El orden de evaluación de los operadores lógicos puede variar dependiendo de las opciones
FREETEXT ( { nombre_columna | (list_columnas) | * } elegidas por el optimizador de consultas.
Nombre_columna es la columna donde se busca. Las columnas de tipo char, varchar, Tablas de verdad de los operadores:
nchar, nvarchar, text, ntext, image, xml y varbinary(max) son válidas para la
búsqueda de texto.
Lic. Vladimir Cotaquispe Gutiérrez. 33 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 34 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
AND Combina dos condiciones y se evalúa como TRUE cuando ambas condiciones son
TRUE. FROM oficinas
Hallar los vendedores que están por debajo de su cuota y tienen ventas inferiores a 30.000.
SELECT oficina, dir
FROM oficinas
SELECT nombre
WHERE NOT dir = 108 or dir is null;
FROM empleados
SELECT oficina
Lic. Vladimir Cotaquispe Gutiérrez. 35 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 36 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Consultas multitabla [ ,...n ]]
4.1. Introducción
< consulta > representa la especificación de la consulta que nos devolverá la tabla a
combinar.
Hasta ahora hemos visto consultas que obtienen los datos de una sola tabla, en este tema Puede ser cualquier especificación de consulta con la limitación de que no admite la cláusula
veremos cómo obtener datos de diferentes tablas. En esta parte ampliaremos la cláusula FROM ORDER BY, los alias de campo se pueden definir pero sólo tienen efecto cuando se indican en
y descubriremos nuevas palabras reservadas (UNION, EXCEPT e INTERSECT) que la primera consulta ya que el resultado toma los nombres de columna de esta.
corresponden a operaciones relacionales. Para obtener datos de varias tablas tenemos que
combinar estas tablas mediante alguna operación basada en el álgebra relacional. El álgebra
relacional define una serie de operaciones cuyos operandos son tablas y cuyo resultado es Ejemplo: Suponemos que tenemos una tabla Valencia con las nuevas oficinas de Valencia y
también una tabla. otra tabla Madrid con las nuevas oficinas de Madrid y queremos obtener una tabla con las
nuevas oficinas de las dos ciudades:
Las operaciones de álgebra relacional implementadas en Transact-Sql son:
SELECT oficina as OFI, ciudad FROM Valencia
La unión UNION
UNION ALL
La diferencia EXCEPT
SELECT oficina, ciudad FROM Madrid;
La intersección INTERSECT
La unión de tablas consiste en coger dos tablas y obtener una tabla con las filas de las dos
tablas, en el resultado aparecerán las filas de una tabla y, a continuación, las filas de la otra
El resultado coge los nombres de columna de la primera consulta y aparecen primero las
tabla.
filas de la primera consulta y después las de la segunda.
Para poder realizar la operación, las dos tablas tienen que tener el mismo esquema (mismo
número de columnas y tipos compatibles) y la tabla resultante hereda los encabezados de la
primera tabla. Si queremos que el resultado aparezca ordenado podemos incluir la cláusula ORDER BY,
pero después de la última especificación de consulta, y expresion_columna será cualquier
columna válida de la primera consulta.
La sintaxis es la siguiente:
23 Madrid
4.3. La diferencia EXCEPT
28 Valencia
Aparecen en la tabla resultante las filas de la primera consulta que no aparecen en la
segunda.
Las condiciones son las mismas que las de la unión.
Ahora las filas aparecen ordenadas por el número de oficina y hemos utilizado el nombre de
columna de la primera consulta.
{<consulta>|(<consulta>)}
Cuando aparezcan en el resultado varias filas iguales, el sistema por defecto elimina las
repeticiones. EXCEPT
Si se especifica ALL, el sistema devuelve todas las filas resultante de la unión incluidas las
repetidas {<consulta>|(<consulta>)}
El empleo de ALL también hace que la consulta se ejecute más rápidamente ya que el sistema
no tiene que eliminar las repeticiones. [{EXCEPT {<consulta>|(<consulta>)}}[ ...n ] ]
SELECT oficina, ciudad FROM Valencia Por ejemplo tenemos las tablas T1 y T2.
UNION
T1 T2
SELECT oficina, ciudad FROM Madrid
UNION Cod
Codigo
SELECT oficina, ciudad FROM Pamplona; 1
2
2
Combinamos las tres tablas. 3
4
Otro ejemplo: 4
5
Obtener todos los productos cuyo precio exceda de 20 € o que se haya vendido más de 300 5
euros del producto en algún pedido. 6
1
Cod
6 2
4
Ejemplo:
5
Listar los productos que no aparezcan en ningún pedido.
Ejemplo: Obtener todos los productos que valen más de 20 euros y que además se haya
SELECT idfab, idproducto vendido en un pedido más de 300 euros de ese producto.
FROM productos
SELECT idfab, idproducto
EXCEPT
FROM productos
SELECT DISTINCT fab, producto
WHERE precio > 20
FROM pedidos;
INTERSECT
{ <consulta>|(<consulta>)}
Retomando el ejemplo anterior: La sentencia SELECT permite realizar esta composición, incluyendo dos o más tablas en la
cláusula FROM.
SELECT cod FROM T1 Es hora de ampliar la cláusula FROM que vimos en el tema anterior.
INTERSECT Empezaremos por estudiar la operación a partir de la cual están definidas las demás
operaciones de composición de tabla, el producto cartesiano.
SELECT cod FROM T2;
Lic. Vladimir Cotaquispe Gutiérrez. 41 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 42 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
4.6. El producto cartesiano CROSS JOIN
WHERE empleados.oficina=oficinas.oficina;
El producto cartesiano obtiene todas las posibles concatenaciones de filas de la primera
tabla con filas de la segunda tabla.
Aquí nos ha aparecido la necesidad de cualificar los campos ya que el nombre oficina es un
campo de empleados y de oficinas por lo que si no lo cualificamos, el sistema nos da error.
Se indica escribiendo en la cláusula FROM los nombres de las tablas separados por una Hemos utilizado en la lista de selección *, esto nos recupera todas las columnas de las dos
coma o utilizando el operador CROSS JOIN. tablas.
WHERE empleados.oficina=oficinas.oficina;
Tabla_origen puede ser un nombre de tabla o de vista o una tabla derivada (resultado de
una SELECT), en este último caso la SELECT tiene que aparecer entre paréntesis y la tabla
derivada debe llevar asociado obligatoriamente un alias de tabla. También puede ser una Recupera todas las columnas de empleados y las columnas ciudad y región de oficinas.
composición de tablas.
Se pueden utilizar hasta 256 orígenes de tabla en una instrucción, aunque el límite varía en También podemos combinar una tabla consigo misma, pero en este caso hay que definir un
función de la memoria disponible y de la complejidad del resto de las expresiones de la
alias de tabla, en al menos una, sino el sistema da error ya que no puede nombrar los campos.
consulta. También se puede especificar una variable table como un origen de tabla.
Ejemplo: SELECT *
FROM empleados, oficinas; No insistiremos más sobre el producto cartesiano porque no es la operación más utilizada,
ya que normalmente cuando queramos componer dos tablas lo haremos con una condición de
selección basada en campos de combinación y para este caso es más eficiente el JOIN que
Si ejecutamos esta consulta veremos que las filas del resultado están formadas por las veremos a continuación.
columnas de empleados y las columnas de oficinas. En las filas aparece cada empleado
combinado con la primera oficina, luego los mismos empleados combinados con la segunda
oficina y así hasta combinar todos los empleados con todas las oficinas. 4.7. La composición interna INNER JOIN
Si ejecutamos:
Una composición interna es aquella en la que los valores de las columnas que se están
combinando se comparan mediante un operador de comparación.
SELECT * Es otra forma, mejor, de expresar un producto cartesiano con una condición.
Es la operación que más emplearemos ya que lo más frecuente es querer juntar los registros de
FROM empleados CROSS JOIN oficinas; una tabla relacionada con los registros correspondientes en la tabla de referencia (añadir a
cada factura los datos de su cliente, añadir a cada línea de pedido los datos de su producto,
etc..,).
Obtenemos lo mismo.
Este tipo de operación no es la que se utiliza más a menudo, lo más frecuente sería FROM
combinar cada empleado con los datos de SU oficina. Lo podríamos obtener añadiendo a la
consulta un WHERE para filtrar los registros correctos: <tabla_origen> INNER JOIN <tabla_origen> ON <condicion_combi>
Obtiene los empleados combinados con los datos de su oficina. Para resolver este problema debemos utilizar otro tipo de composición, la composición externa.
FROM pedidos INNER JOIN productos La composición externa se escribe de manera similar al INNER JOIN indicando una
condición de combinación pero en el resultado se añaden filas que no cumplen la condición de
ON producto = idproducto AND fab = idfab; combinación.
Sintaxis
Obtiene los pedidos combinados con los productos correspondientes.
Normalmente la condición de combinación será una igualdad pero se puede utilizar cualquier FROM
operador de comparación (<>, >…).
<tabla_origen> {LEFT|RIGHT|FULL} [OUTER] JOIN <tabla_origen>
Es fácil ver la utilidad de esta instrucción y de hecho se utilizará muy a menudo, pero hay ON <condicion_combi>
algún caso que no resuelve. En las consultas anteriores, no aparecen las filas que no tienen fila
correspondiente en la otra tabla.
La palabra OUTER es opcional y no añade ninguna función.
Las palabras LEFT, RIGHT y FULL indican la tabla de la cual se van a añadir las filas sin
SELECT numemp,nombre,empleados.oficina, ciudad
correspondencia.
FROM empleados INNER JOIN oficinas
Lic. Vladimir Cotaquispe Gutiérrez. 45 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 46 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
110 Juan Victor NULL NULL numemp nombre oficina ciudad oficina
101 Antonio Viguer 12 Alicante 12
Ahora sí aparece el empleado 110 que no tiene oficina 102 Alvaro Jaumes 21 Badajoz 21
103 Juan Rovira 12 Alicante 12
Obtiene los empleados con su oficina y los empleados (tabla a la izquierda LEFT del JOIN)
que no tienen oficina aparecerán también en el resultado con los campos de la tabla oficinas 104 José González 12 Alicante 12
rellenados a NULL. 105 Vicente Pantalla 13 Castellón 13
106 Luis Antonio 11 Valencia 11
SELECT numemp,nombre,empleados.oficina, ciudad, oficinas.oficina 107 Jorge Gutiérrez 22 A Coruña 22
SELECT numemp,nombre,empleados.oficina, ciudad, oficinas.oficina Si pueden haber filas de la segunda tabla que no estén relacionadas con filas de la
primera tabla y nos interesa que salgan en el resultado, entonces cambiamos a RIGHT
FROM empleados FULL JOIN oficinas JOIN.
ON empleados.oficina=oficinas.oficina; Si necesitamos LEFT y RIGHT entonces utilizamos FULL JOIN.
Lic. Vladimir Cotaquispe Gutiérrez. 47 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 48 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Siguiendo el ejemplo anterior nos preguntaríamos: Consultas de Resumen
¿Pueden haber empleados que no tengan oficina y nos interesan?, si es que sí, necesitamos
un LEFT JOIN. 5.1. Introducción
Seguiríamos preguntando: Una de las funcionalidades de la sentencia SELECT es el permitir obtener resúmenes de los
datos contenidos en las columnas de las tablas.
¿Pueden haber oficinas que no tengan empleados y nos interesan?, si es que sí,
necesitamos un RIGHT JOIN. Para poder llevarlo a cabo la sentencia SELECT consta de una serie de cláusulas
específicas (GROUP BY, HAVING), y Transact-SQL tiene definidas unas funciones para poder
Si al final necesitamos LEFT y también RIGHT entonces utilizamos FULL JOIN. realizar estos cálculos, las funciones de agregado (también llamadas funciones de columna).
La diferencia entre una consulta de resumen y una consulta de las que hemos visto hasta
4.9. Combinar varias operaciones ahora es que en las consultas normales las filas del resultado se obtienen directamente de las
filas del origen de datos y cada dato que aparece en el resultado tiene su dato correspondiente
En las operaciones anteriores tabla_origen puede ser a su vez una composición de tablas, en el origen de la consulta mientras que las filas generadas por las consultas de resumen no
en este caso aunque sólo sea obligatorio cuando queramos cambiar el orden de ejecución de representan datos del origen sino un total calculado sobre estos datos. Esta diferencia hará que
las composiciones, es recomendable utilizar paréntesis para delimitar las composiciones. las consultas de resumen tengan algunas limitaciones que veremos a lo largo del tema.
ON empleados.oficina = oficinas.oficina)
O bien:
FROM oficinas RIGHT JOIN (empleados INNER JOIN pedidos on rep = numemp)
ON empleados.oficina = oficinas.oficina); A la izquierda tenemos una consulta simple que nos saca las oficinas con sus ventas
ordenadas por región, y a la derecha una consulta de resumen que obtiene la suma de las
ventas de las oficinas de cada región
Una función de agregado SQL acepta un grupo de datos (normalmente una columna de
datos) como argumento, y produce un único dato que resume el grupo. Por ejemplo la función
AVG() acepta una columna de datos numéricos y devuelve la media aritmética (average) de los
valores contenidos en la columna.
Lic. Vladimir Cotaquispe Gutiérrez. 49 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 50 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
El mero hecho de utilizar una función de agregado en una consulta, convierte ésta en una
consulta de resumen. SELECT COUNT(region) FROM oficinas;
La palabra ALL indica que se tiene que tomar en cuenta todos los valores de la columna. Es
l valor por defecto. Devuelve 4 porque tenemos cuatro valores distintos, no nulos, en la columna región, los
valores repetidos los considera sólo una vez. Ahora sí nos devuelve cuántas regiones tenemos
en oficinas.
La palabra DISTINCT hace que se consideren todas las repeticiones del mismo valor como
uno sólo (considera valores distintos).
Si utilizamos * en vez de expresión, devuelve el número de filas del origen que nos quedan
después de ejecutar la cláusula WHERE.
Todas las funciones de agregado se aplican a las filas del origen de datos una vez ejecutada
la cláusula WHERE (si la hubiera).
COUNT(*) no acepta parámetros y no se puede utilizar con DISTINCT. COUNT(*) no
requiere un parámetro expression porque, por definición, no utiliza información sobre ninguna
Si exceptuamos la función COUNT, todas las funciones de agregado ignoran los valores
columna específica. En el recuento se incluyen las filas que contienen valores NULL.
NULL.
Una función de agregado puede aparecer en la lista de selección en cualquier lugar en el SELECT COUNT(*) FROM empleados WHERE oficina=12;
que puede aparecer un nombre de columna. Puede, por ejemplo, formar parte de una expresión
pero no se pueden anidar funciones de agregado.
Obtiene el número de empleados asignados a la oficina 12.
Tampoco se pueden mezclar funciones de columna con nombres de columna ordinarios.
Hay excepciones a esta regla pero cuando definimos agrupaciones y subconsultas que
Si tenemos un COUNT(columna) y columna no contiene valores nulos, se obtiene el mismo
veremos más adelante.
resultado que COUNT(*) pero el COUNT(*) es más rápido por lo que en este caso hay que
utilizarlo en vez de COUNT(columna).
5.3. La función COUNT
Por ejemplo:
Expresion puede ser de cualquier tipo excepto text, image o ntext. No se permite utilizar
funciones de agregado ni subconsultas. El tipo de dato devuelto es int. Es mejor que:
Si el número de valores devueltos por expresion es superior a 231-1, COUNT genera un error,
en ese caso hay que utilizar la función COUNT_BIG.
SELECT COUNT(oficina) FROM empleados WHERE oficina IS NOT NULL;
La función cuenta los valores distintos de NULL que hay en la columna. La palabra ALL
indica que se tienen que tomar todos los valores de la columna, mientras que DISTINCT hace
que se consideren todas las repeticiones del mismo valor como uno solo. Estos parámetros son Las dos nos devuelven el número de empleados que tienen una oficina asignada pero la
opcionales, por defecto se considera ALL. primera es mejor porque se calcula más rápidamente.
Por ejemplo:
Lic. Vladimir Cotaquispe Gutiérrez. 51 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 52 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
5.4. La función COUNT_BIG 5.7. La función SUM
Funciona igual que la función COUNT. La única diferencia entre ambas funciones está en los
SUM ([ALL|DISTINCT] expresion )
valores devueltos, COUNT_BIG siempre devuelve un valor de tipo bigint y por lo tanto admite
más valores de entrada, no está limitado a 231-1 valores de entrada como COUNT.
Devuelve la suma de los valores devueltos por la expresión.
5.5. La función MAX
Sólo puede utilizarse con columnas numéricas.
MAX ([ALL|DISTINCT] expression)
El resultado será del mismo tipo aunque puede tener una precisión mayor.
Utilizar DISTINCT no tiene ningún sentido con MAX (el valor máximo será el mismo si
consideramos las repeticiones o no) y sólo se incluye para la compatibilidad con SQL-92. SELECT SUM(ventas) AS VentasTotales, MAX(objetivo) AS MayorObjetivo
SELECT SUM(ventas) AS VentasTotales, MAX(objetivo) AS MayorObjetivo Devuelve la suma de las ventas de todas las oficinas y de los objetivos de todas las oficinas,
el de mayor importe.
FROM oficinas;
Devuelve el promedio de los valores de un grupo, para calcular el promedio se omiten los
5.6. La función MIN valores nulos.
La función se aplica también a campos numéricos, y en este caso el tipo de dato del
Devuelve el valor mínimo de la expresión sin considerar los nulos.
resultado puede cambiar según las necesidades del sistema para representar el valor del
resultado.
MIN se puede usar con columnas numéricas, de caracteres y de datetime, pero no con
columnas de bit. No se permiten funciones de agregado ni subconsultas.
5.9. La función VAR
Utilizar DISTINCT no tiene ningún sentido con MIN (el valor mínimo será el mismo si
consideramos las repeticiones o no) y sólo se incluye para la compatibilidad con SQL-92.
VAR ([ALL|DISTINCT] expresion )
Lic. Vladimir Cotaquispe Gutiérrez. 53 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 54 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Devuelve la varianza estadística de todos los valores de la expresión especificada. 5.14. Agrupamiento de filas (cláusula GROUP BY).
VAR sólo se puede utilizar con columnas numéricas. Los valores NULL se pasan por alto.
Hasta ahora las consultas sumarias que hemos visto obtienen totales de todas las filas del
5.10. La función VARP origen y producen una única fila de resultado.
Muchas veces cuando calculamos resúmenes nos interesan totales parciales, por ejemplo
VARP ([ALL|DISTINCT] expresion ) saber de cada empleado cuánto ha vendido, y cuál ha sido su pedido máximo, de cada cliente
cuándo fue la última vez que nos compró, etc.
Devuelve la varianza estadística de la población para todos los valores de la expresión En todos estos casos en vez de obtener una fila única de resultados necesitamos una fila
especificada. por cada empleado, cliente, etc.
Sólo se puede utilizar con columnas numéricas. Los valores NULL se pasan por alto.
Podemos obtener estos subtotales con la cláusula GROUP BY.
5.11. La función STDEV
GROUP BY [ ALL ] expresion_agrupacion [ ,...n ]
STDEV ([ALL|DISTINCT] expresion )
[ WITH { CUBE | ROLLUP } ]
expresion_agrupacion puede ser una columna o una expresión no agregada que haga
Devuelve la desviación estadística estándar para la población de todos los valores de la referencia a una columna devuelta por la cláusula FROM. Un alias de columna que esté
expresión especificada. definido en la lista de selección no puede utilizarse para especificar una columna de
Sólo se puede utilizar con columnas numéricas. Los valores NULL se pasan por alto. agrupamiento.
No se pueden utilizar columnas de tipo text, ntext e image en expresion_agrupacion.
5.13. La función GROUPING
En las cláusulas GROUP BY que no contengan CUBE o ROLLUP, el número de columnas
de agrupación está limitado por los tamaños de columna de GROUP BY, las columnas de
GROUPING (nb_columna) agregado y los valores de agregado que participan en la consulta. Este límite procede del límite
de 8.060 bytes de la tabla de trabajo intermedia que se necesita para contener los resultados
intermedios de la consulta. Se permite un máximo de 10 expresiones de agrupamiento cuando
Es una función de agregado que genera como salida una columna adicional con el valor 1 si se especifica CUBE o ROLLUP.
la fila se agrega mediante el operador CUBE o ROLLUP, o el valor 0 cuando la fila no es el
resultado de CUBE o ROLLUP. Si en la columna de agrupación existen valores nulos, se generará una fila de resumen para
este “valor”, en este caso se considera el valor nulo como otro valor cualquiera.
Nb_columna tiene que ser una de las columnas de agrupación y la cláusula GROUP BY
debe contener el operador CUBE o ROLLUP. Ejemplo:
En el siguiente punto, cuando veamos las cláusulas CUBE y ROLLUP quedará más claro.
SELECT oficina, count(numemp) AS [Número de empleados]
FROM empleados
Lic. Vladimir Cotaquispe Gutiérrez. 55 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 56 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
103 2111 2 21,00
GROUP BY oficina;
105 2103 4 275,00
22 1
De cada representante obtenemos el número de pedidos y el importe máximo vendido a
cada cliente, de las ventas de 1997. La cláusula ORDER BY se ha incluido para que las filas
Hay empleados sin oficinas (con oficina a nulo), estos forman un grupo con el valor NULL en aparezcan ordenadas y quede más claro.
oficina, en este caso hay dos empleados así.
Hemos dicho que los resúmenes se calculan sobre todas las filas del origen después de
Podemos indicar varias columnas de agrupación. haber ejecutado el WHERE, pues ALL permite obtener un resumen de las filas que no cumplen
el WHERE.
Ejemplo:
ALL Incluye todos los grupos y conjuntos de resultados, incluso aquellos en los que no hay
filas que cumplan la condición de búsqueda especificada en la cláusula WHERE. Cuando se
SELECT rep, clie, count(numpedido) AS [Número de pedidos], MAX(importe) especifica ALL, se devuelven valores NULL para las columnas de resumen de los grupos que
AS [Importe máximo] no cumplen la condición de búsqueda. No se puede especificar ALL con los operadores CUBE
y ROLLUP.
FROM pedidos
GROUP BY ALL no se admite en consultas que tienen acceso a tablas remotas si también
WHERE YEAR(fechapedido) = 1997
hay una cláusula WHERE en la consulta.
GROUP BY rep, clie
Por ejemplo, vamos a modificar la consulta anterior:
ORDER BY rep, clie;
FROM pedidos
rep clie Número Importe
de pedidos máximo WHERE YEAR(fechapedido) = 1997
101 2113 1 225,00
GROUP BY ALL rep, clie
102 2106 2 21,30
ORDER BY rep, clie;
102 2120 1 37,50
Resultado:
Lic. Vladimir Cotaquispe Gutiérrez. 57 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 58 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Número Importe Número Importe
rep clie rep clie
de pedidos máximo de pedidos máximo
101 2102 0 NULL 101 2113 1 225,00
101 2108 0 NULL 101 NULL 1 225,00
101 2113 1 225,00 102 2106 1 21,30
102 2106 2 21,30 102 2120 1 37,50
102 2120 1 37,50 102 NULL 3 37,50
103 2111 2 21,00 103 2111 2 21,00
105 2103 4 275,00 103 NULL 2 21,00
105 2111 1 37,45 105 2103 4 275,00
106 2101 1 14,58 105 2111 1 37,45
106 2117 0 NULL 105 NULL 5 275,00
107 2109 1 313,50 106 2101 1 14,28
107 2124 2 24,30 106 NULL 1 14,28
108 2112 1 29,25 107 2109 1 313,50
108 2114 1 71,00 107 2124 2 24,30
108 2118 3 14,20 107 NULL 3 313,50
108 2112 1 29,25
Cuál ha sido el efecto de añadir ALL? Se han añadido filas para las filas del origen que no 108 2114 1 71,00
cumplen la condición del WHERE pero sin que intervengan en el cálculo de las funciones de
agregado. 108 2118 3 14,20
Por ejemplo el representante 101 tiene pedidos con el cliente 2102 pero estos pedidos no son 108 NULL 5 71,00
del año 1997, por eso aparece la primera fila (no estaba en el resultado de la otra consulta) ... ... ... ...
pero con 0 y NULL como resultados de las funciones de agregado.
NULL NULL 23 450,00
ROLLUP especifica que, además de las filas que normalmente proporciona GROUP BY, se
incluyen filas de resumen en el conjunto de resultados. Los grupos se resumen en un orden Efecto: Se han añadido automáticamente subtotales por cada nivel de agrupamiento y una
jerárquico, desde el nivel inferior del grupo hasta el superior. La jerarquía del grupo se línea de totales generales al final. En este caso no hemos incluido ORDER BY porque las filas
determina por el orden en que se especifican las columnas de agrupamiento. Cambiar el orden salen ya ordenadas.
de las columnas de agrupamiento puede afectar al número de filas generadas en el conjunto de
resultados.
CUBE especifica que, además de las filas que normalmente proporciona GROUP BY, deben
Por ejemplo:
incluirse filas de resumen en el conjunto de resultados. Se devuelve una fila de resumen
GROUP BY por cada posible combinación de grupo y subgrupo del conjunto de resultados. En
el resultado se muestra una fila de resumen GROUP BY como NULL, pero se utiliza para
SELECT rep, clie, count(numpedido) AS [Número de pedidos], MAX(importe) indicar todos los valores.
AS [Importe máximo]
FROM pedidos
Resultado:
WHERE YEAR(fechapedido) = 1997
Lic. Vladimir Cotaquispe Gutiérrez. 59 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 60 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
NULL 2118 3 14,20
GROUP BY rep, clie WITH CUBE;
NULL 2120 1 37,50
NULL 2124 2 24,30
Resultado:
Efecto: Obtenemos además de los resultados obtenidos con ROLLUP (los totales por cada
Número Importe representante), los totales por el otro criterio (los totales por cada cliente).
rep clie
de pedidos máximo El número de filas de resumen del conjunto de resultados se determina mediante el número de
101 2113 1 225,00 columnas que contiene la cláusula GROUP BY. Cada operando (columna) de la cláusula
GROUP BY se enlaza según el agrupamiento NULL y se aplica el agrupamiento al resto de los
101 NULL 1 225,00 operandos (columnas). CUBE devuelve todas las combinaciones posibles de grupo y subgrupo.
102 2106 1 21,30
102 2120 1 37,50 Tanto si utilizamos CUBE como ROLLUP, nos será útil la función de agregado GROUPING.
Lic. Vladimir Cotaquispe Gutiérrez. 61 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 62 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
5.15. Selección sobre grupos de filas, la cláusula HAVING
HAVING SUM(ventas)=10000
Cuando queremos incluir una cláusula de selección sobre las filas del origen, utilizamos la
cláusula WHERE, pero cuando estamos definiendo una consulta de resumen, no podemos
utilizar esta cláusula para seleccionar filas del resultado ya que cada una de éstas representa Las Sub consultas
un grupo de filas de la tabla original. Para seleccionar filas del resumen tenemos la cláusula
HAVING.
6.1. Introducción
HAVING condición de búsqueda
Una subconsulta es una consulta que aparece dentro de otra consulta o subconsultas, en la
lista de selección o en la cláusula WHERE o HAVING, originalmente no se podían incluir en la
lista de selección.
HAVING funciona igual que la cláusula WHERE pero en vez de actuar sobre las filas del Una subconsulta se denomina también consulta o selección interna, mientras que la instrucción
origen de datos, actúa sobre las filas del resultado, selecciona grupos de filas por lo que la que contiene la subconsulta es conocida como consulta o selección externa.
condición de búsqueda sufrirá alguna limitación, la misma que para la lista de selección:
Ejemplo:
Aparece siempre encerrada entre paréntesis y tiene la misma sintaxis que una sentencia
SELECT normal con alguna limitación:
No puede incluir una cláusula COMPUTE o FOR BROWSE y sólo puede incluir una cláusula
SELECT oficina, count(numemp) AS [Número de empleados] ORDER BY cuando se especifica también una cláusula TOP.
FROM empleados
Una subconsulta puede anidarse en la cláusula WHERE o HAVING de una instrucción
GROUP BY oficina externa SELECT, INSERT, UPDATE o DELETE, o bien en otra subconsulta. Se puede disponer
de hasta 32 niveles de anidamiento, aunque el límite varía dependiendo de la memoria
HAVING COUNT(numemp)<2; disponible y de la complejidad del resto de las expresiones de la consulta. Hay que tener en
cuenta que para cada fila de la consulta externa, se calcula la subconsulta, si anidamos varias
consultas, el número de veces que se ejecutarán las subconsultas ¡puede dispararse!
Resultado:
Cuando la subconsulta aparece en la lista de selección de otra consulta, deberá devolver un
oficina Número de empleados solo valor, de lo contrario provocará un error.
13 1 Ejemplo de subconsulta: Listar los empleados cuya cuota no supere el importe vendido por
el empleado.
22 1
SELECT nombre
Esta SELECT es la misma que la del primer ejemplo del apartado sobre la cláusula GROUP
FROM empleados
BY, la diferencia es que le hemos añadido la cláusula HAVING, que hace que del resultado sólo
se visualicen los grupos que cumplan la condición. Es decir sólo aparecen las oficinas que WHERE cuota <= (SELECT SUM(importe)
tienen menos de 2 empleados.
Siempre que en una condición de selección haya una función de columna, la condición deberá FROM pedidos
incluirse en la cláusula HAVING, además, como HAVING filtra filas del resultado, sólo puede
contener expresiones (nombres de columnas, expresiones, funciones…) que también pueden WHERE rep = numemp);
aparecer en la lista de selección, por lo que también se aplica la misma regla a no olvidar:
EN LA CLÁUSULA HAVING UN NOMBRE DE COLUMNA NO PUEDE APARECER Por cada fila de la tabla de empleados (de la consulta externa) se calcula la subconsulta y se
FUERA DE UNA FUNCIÓN DE AGREGADO SI NO ES UNA COLUMNA DE AGRUPACIÓN. evalúa la condición, por lo que utilizar una subconsulta puede en algunos casos ‘ralentizar’ la
consulta, en contrapartida se necesita menos memoria que una composición de tablas.
Las expresiones que pongamos en HAVING no tienen porqué aparecer en la lista de
selección, por ejemplo en la SELECT anterior se podía haber escrito: Muchas de las instrucciones Transact-SQL que incluyen subconsultas se pueden formular
también utilizando composiciones de tablas. Otras preguntas se pueden formular sólo con
subconsultas.
Lic. Vladimir Cotaquispe Gutiérrez. 63 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 64 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
En Transact-SQL, normalmente no hay una regla fija en cuanto a diferencias de rendimiento
entre una instrucción que incluya una subconsulta y una versión semánticamente equivalente SELECT oficina, ciudad
que no la incluya.
FROM oficinas
Podremos utilizar una subconsulta siempre y cuando no se quiera que aparezcan en el WHERE objetivo > (SELECT SUM(ventas)
resultado columnas de la subconsulta ya que si una tabla aparece en la subconsulta y no en la
consulta externa, las columnas de esa tabla no se pueden incluir en la salida (la lista de FROM empleados
selección de la consulta externa).
WHERE oficina = oficina);
Tenemos tres tipos de subconsultas:
La columna oficina se encuentra en los dos orígenes (oficinas y empleados) pero esta
Las que devuelven un solo valor, aparecen en la lista de selección de la consulta externa consulta no dará error (no se nos pedirá cualificar los nombres como pasaría en una
o con un operador de comparación sin modificar. composición de tablas), dentro de la subconsulta se considera oficina el campo de la tabla
empleados. Con lo que compararía la oficina del empleado con la misma oficina del empleado y
Las que generan una columna de valores, aparecen con el operador IN o con eso no es lo que queremos, queremos comparar la oficina del empleado con la oficina de
un operador de comparación modificado con ANY, SOME o ALL. oficinas, lo escribiremos pues así para forzar a que busque la columna en la tabla oficinas.
Las que pueden generar cualquier número de columnas y filas, son utilizadas en pruebas
de existencia especificadas con EXISTS.
SELECT oficina, ciudad
A lo largo del tema las estudiaremos todas. FROM oficinas
Antes de terminar con la introducción queda comentar el concepto de referencia externa muy WHERE objetivo > (SELECT SUM(ventas)
útil en las subconsultas.
FROM empleados
A menudo, es necesario, dentro del cuerpo de una subconsulta, hacer referencia al valor de WHERE oficina = oficinas.oficina);
una columna en la fila actual de la consulta externa, el nombre de columna de la consulta
externa dentro de la subconsulta recibe el nombre de referencia externa, ya que hace referencia
a una columna externa.
En el ejemplo anterior numemp es una referencia externa, no es una columna del origen de
datos de la subconsulta (pedidos), es una columna del origen de la consulta externa 6.2. Subconsultas de resultado único
(empleados).
Existen subconsultas que deben obligatoriamente devolver un único valor, son las que
Hay que tener en cuenta de cómo se ejecuta la consulta; por cada fila de la consulta externa aparecen en la lista de selección de la consulta externa o las que aparecen en WHERE o
se calcula el resultado de la subconsulta y se evalúa la comparación. HAVING combinadas con un operador de comparación sin modificar.
En el ejemplo, se coge el primer empleado (numemp= 101, por ejemplo) y se calcula la Los operadores de comparación sin modificar son los operadores de comparación que vimos
subconsulta sustituyendo numemp por el valor 101, se calcula la suma de los pedidos del rep = con la cláusula WHERE.
101, y el resultado se compara con la cuota de ese empleado, y así se repite el proceso con
todas las filas de empleados. Sintaxis:
En este caso la segunda expresión será una subconsulta, con una sola columna en la lista
de selección y deberá devolver una única fila como mucho.
Por ejemplo:
Ese valor único será el que se compare con el resultado de la primera expresión.
Lic. Vladimir Cotaquispe Gutiérrez. 65 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 66 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Si la subconsulta no devuelve ninguna fila, la comparación opera como si la segunda
expresión fuese nula. WHERE region = 'Este');
Estas consultas aparecen en las cláusulas WHERE o HAVING combinadas con el operador WHERE oficina IN (SELECT oficina
IN o con comparaciones modificadas. FROM oficinas
<expresion> IN subconsulta La lista generada está vacía por lo que la condición IN devuelve FALSE y en este caso no
sale ningún empleado.
IN examina si el valor de expresion es uno de los valores incluidos en la lista de valores Muchas veces la misma pregunta se puede resolver mediante una composición de tablas.
generados por la subconsulta.
La subconsulta tiene que generar valores de un tipo compatible con la expresión. SELECT empleados.*
FROM empleados Esta sentencia es equivalente. En el resultado no queremos ver ninguna columna de la tabla
WHERE oficina IN (SELECT oficina oficinas, el JOIN lo tenemos sólo para la pregunta, en este caso pues se puede sustituir por una
subconsulta.
FROM oficinas
Lic. Vladimir Cotaquispe Gutiérrez. 67 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 68 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
SELECT *
Si combinamos el operador IN con NOT obtenemos el operador NOT IN.
FROM Oficinas
FROM empleados
Devuelve los empleados cuya oficina no esté en la lista generada por la subconsulta, es
decir empleados que trabajan en oficinas que no son del Este. WHERE oficina IS NOT NULL);
Lic. Vladimir Cotaquispe Gutiérrez. 69 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 70 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
En este caso, como un empleado puede tener varios pedidos hay que añadir DISTINCT para ANY significa que, para que una fila de la consulta externa satisfaga la condición
eliminar las repeticiones de empleados (si un empleado tiene varios pedidos de ACI aparecería especificada, la comparación se debe cumplir para al menos un valor de los devueltos por la
varias veces). subconsulta.
Sin embargo esta sentencia con NOT IN, queremos los empleados que no tienen pedidos de Por cada fila de la consulta externa se evalúa la comparación con cada uno de los valores
ACI: devueltos por la subconsulta y si la comparación es True para alguno de los valores ANY es
verdadero, si la comparación no se cumple con ninguno de los valores de la consulta, ANY da
False a no ser que todos los valores devueltos por la subconsulta sean nulos en tal caso ANY
dará NULL.
Si la subconsulta no devuelve filas ANY da False incluso si expresion es nula.
SELECT numemp AS [NOT IN]
Ejemplo:
FROM empleados
FROM Empleados INNER JOIN pedidos ON numemp = rep Obtenemos los empleados que tienen una cuota superior a la cuota de alguno de sus
compañeros de oficina, es decir los empleados que no tengan la menor cuota de su oficina.
WHERE fab <> 'ACI';
En este caso hemos tenido un alias de tabla en la subconsulta (empleados2) para poder
utilizar una referencia externa.
Esta consulta devuelve los empleados que tienen pedidos que no son de ACI, pero un
empleado puede tener pedidos de ACI y otros de otros fabricantes y por estos otros saldría en
el resultado cuando sí tiene pedidos de ACI y no debería salir. El test ALL
Hay que tener mucho cuidado con este tipo de preguntas.
<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} ALL subconsulta
6.5. La comparación modificada (ANY, ALL)
Los operadores de comparación que presentan una subconsulta se pueden modificar Con el modificador ALL, para que se cumpla la condición, la comparación se debe cumplir
mediante las palabras clave ALL, ANY o SOME. SOME es un equivalente del estándar de SQL- con cada uno de los valores devueltos por la subconsulta.
92 de ANY.
Si la subconsulta no devuelve ninguna fila ALL da True.
Se utiliza este tipo de comparación cuando queremos comparar el resultado de la expresión
con una lista de valores y actuar en función del modificador empleado.
El test ANY
SELECT *
FROM empleados
<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} {ANY|SOME} subconsulta
WHERE cuota > ALL (SELECT cuota
Ejemplo:
En el ejemplo anterior obtenemos los empleados que tengan una cuota superior a todas las
cuotas de la oficina del empleado. Podríamos pensar que obtenemos el empleado de mayor
cuota de su oficina pero no lo es, aquí tenemos un problema, la cuota del empleado aparece en SELECT *
el resultado de subconsulta por lo tanto > no se cumplirá para todos los valores y sólo saldrán
los empleados que no tengan oficina (para los que la subconsulta no devuelve filas). FROM empleados
Para salvar el problema tendríamos que quitar del resultado de la subconsulta la cuota del WHERE EXISTS (SELECT *
empleado modificando el WHERE: FROM pedidos
Otra cosa a tener en cuenta es que la lista de selección de una subconsulta que se
especifica con EXISTS casi siempre consta de un asterisco (*). No hay razón para enumerar los
6.6. Subconsultas con cualquier número de columnas (EXISTS) nombres de las columnas porque no se van a utilizar y supone un trabajo extra para el sistema.
Existe otro operador de subconsulta con el que la subconsulta puede devolver más de una Si utilizamos NOT EXISTS el resultado será el contrario.
columna, el operador EXISTS.
En este caso la sintaxis es algo diferente:
SELECT *
WHERE [NOT] EXISTS subconsulta FROM empleados
Lic. Vladimir Cotaquispe Gutiérrez. 73 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 74 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql
FROM pedidos