You are on page 1of 38

Power Builder + Sql Power Builder + Sql

Consultas simples [INTO nueva_tabla]

[FROM { <origen> } [ ,...n ] ]


3.1. Introducción
[WHERE <condicion_busqueda> ]
Vamos a empezar por la instrucción que más se utiliza en SQL, la sentencia SELECT. La
sentencia SELECT es, con diferencia, la más compleja y potente de las sentencias SQL, con [GROUP BY [ ALL ] expresion_agrupacion [ ,...n ]
ella podemos recuperar datos de una o más tablas, seleccionar ciertos registros e incluso [WITH { CUBE | ROLLUP } ]
obtener resúmenes de los datos almacenados en la base de datos. Es tan compleja que la
estudiaremos a lo largo de varias unidades didácticas incorporando poco a poco nuevas ]
funcionalidades.
[HAVING < condicion_busqueda > ]
El resultado de una SELECT es una tabla lógica que alberga las filas resultantes de la
ejecución de la sentencia.
Debido a la complejidad de la sentencia (en la sintaxis anterior no se han detallado algunos
La sintaxis completa es la siguiente: elementos), la iremos viendo poco a poco, empezaremos por ver consultas básicas para luego
ir añadiendo más cláusulas.

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>

[ORDER BY {expression_columna|posicion_columna [ASC|DESC] } SELECT [ALL|DISTINCT]


[ ,...n ]] [TOP expresion [PERCENT] [WITH TIES]]
[COMPUTE <lista_seleccion>
{{AVG|COUNT|MAX|MIN|SUM} (expression)}[ ,...n ] [BY FROM <origen>
expression[ ,...n ]]
[WHERE <condicion_busqueda> ]
]
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]} [ ,...n
[<FOR clausula_for>] ]]
[OPTION (<query_hint>[ ,...n ])]

<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:
]

<especificacion_consulta> ::= <origen>::= nb_tabla | nb_vista [[ AS ] alias_tabla ]


SELECT [ALL|DISTINCT]

[TOP expresion [PERCENT] [WITH TIES] ] nb_tabla representa un nombre de tabla.


<lista_seleccion>
nb_vista un nombre de vista.
Lic. Vladimir Cotaquispe Gutiérrez. 1 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 2 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Tanto para las tablas como para las vistas, podemos hacer referencia a tablas que están en En la lista de selección <lista_seleccion> indicamos las columnas que se tienen que
otras bases de datos (siempre que tengamos los permisos adecuados), en este caso tenemos visualizar en el resultado de la consulta.
que cualificar el nombre de la tabla, indicando delante el nombre de la base de datos (Lógica) y
el nombre del esquema al que pertenece la tabla dentro de la base de datos.
<lista_seleccion> ::=
Por ejemplo: MiBase.dbo.MiTabla se refiere a la tabla MiTabla que se encuentra en el
esquema dbo de la base de datos MiBase. { *

| {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

SELECT ... o una columna del origen de datos,

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.

La palabra clave $ROWGUID.


3.3. La lista de selección
Lic. Vladimir Cotaquispe Gutiérrez. 3 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 4 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
3.4. Columnas del origen de datos Idfab idproducto descripcion precio
aci 41001 arandela 0,58
Cuando queremos indicar en la lista de selección una columna del origen de datos, la
especificamos mediante su nombre simple o nombre cualificado. El nombre cualificado consiste aci 41002 bisagra 0,80
en el nombre de la columna precedido del nombre de la tabla donde se encuentra la columna. aci 41003 art t3 1,12
aci 41004 art t4 1,23
Si en el origen de datos hemos utilizado una vista o un nombre de alias, deberemos utilizar
ese nombre. Es obligatorio utilizar el nombre cualificado cuando el nombre de la columna aci 4100x junta 0,26
aparece en más de una tabla del origen de datos. aci 4100y extractor 28,88
aci 4100z mont 26,25
Ejemplos de consulta simple.
bic 41003 manivela 6,52
bic 41089 rodamiento 2,25
Listar nombres, oficinas, y fechas de contrato de todos los empleados:

SELECT nombre, oficina, contrato


3.5. Alias de columna
FROM empleados;
Por defecto, en el encabezado de cada columna del resultado, aparece el nombre de la
columna origen, pero esto se puede cambiar definiendo un alias de columna, el alias de
El resultado sería: columna es un nombre alternativo que se le da a esa columna.

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

2101 Luis García Antón


Listar una tarifa de productos:

2102 Alvaro Rodríguez


SELECT idfab, idproducto, descripcion, productos.precio

FROM productos; 2103 Jaime Llorens

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.

2101 Luis García Antón DAY Devuelve el día de la fecha indicada.

2102 Alvaro Rodríguez MONTH Devuelve el mes de la fecha indicada.

2103 Jaime Llorens YEAR Devuelve el año de la fecha indicada.

Devuelve una cadena de caracteres que representa el valor de la


DATENAME
unidad especificada de una fecha especificada.

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;

@@DATEFIRST Devuelve el primer día de la semana establecido con SET DATEFIRST.


Sería equivalente a la consulta anterior
SET
Si queremos incluir espacios en blanco en el nombre lo debemos encerrar entre corchetes. Establece el primer día de la semana en un número del 1 al 7.
DATEFIRST

SELECT numclie,nombre AS [nombre cliente]


Funciones de cadena:
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

Madrid centro NULL


Otras funciones:

Madrid centro -10000,00


Función Descripción
ROUND Redondea un valor a la longitud y precisión indicadas.
Pamplona norte NULL
CAST y
Convierten de un tipo de datos a otro de forma explícita.
CONVERT
Valencia este -90000,00
CASE Evalúa una lista de condiciones.
ISNULL Reemplaza el valor NULL por otro especificado.
Devuelve la primera expresión distinta de NULL entre sus
COALESCE De cada producto queremos saber el id de fabricante, id de producto, su descripción y el
argumentos.
valor de sus existencias.

3.7. Columnas calculadas SELECT idfab,idproducto,descripcion,(existencias*precio) AS valoracion

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

SELECT ciudad, region, (ventas-objetivo) AS superavit aci 41003 art t3 231,84

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;

Esto tiene el mismo efecto que


El resultado será:

Nombre Mes de contrato Año de contrato SELECT oficina, ventas-objetivo AS superavit


Antonio Viguer 10 1986
Alvaro Jaumes 12 1986
Juan Rovira 3 1987
3.8. Utilización del asterisco *
Listar las ventas en cada oficina con el formato: 22 tiene ventas de 186,042.00 €
Si queremos visualizar todas las columnas del origen de datos, en lugar de indicar todas las
columnas una a una se puede utilizar el carácter de sustitución *.
SELECT oficina, 'tiene ventas de ' AS [ ], ventas
Mostrar todos los datos de la tabla oficinas.
FROM oficinas;

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

SELECT *, (ventas-objetivo) AS superavit ORDER BY {expression_columna|posicion_columna [ASC|DESC]}[ ,...n ]

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.

Si la columna de ordenación es numérica, las filas se ordenarán de menor a mayor.


Esta forma se utiliza normalmente cuando el origen está basado en varias tablas y queremos
indicar todas las columnas no del origen completo sino de una tabla concreta. Si la columna de ordenación es de tipo fecha, las filas se ordenarán de más antigua a
más reciente o futura.
3.9. Las palabras clave $IDENTITY y $ROWGUID
Ejemplos:

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.

Por ejemplo, si en la columna codigo de la tabla usuarios (BD Biblio) se ha definido la


propiedad IDENTITY. SELECT oficina, region, ciudad, ventas

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

ciudad region ventas


En este caso hemos utilizado el alias de columna para hacer referencia a la columna
Badajoz oeste 83600,00
calculada y también se puede observar que las filas aparecen ordenadas por región ascendente
Alicante este 73500,00 (no hemos incluido nada después del nombre de la columna) y dentro de cada región por
Valencia este 69300,00 superávit y descendente.

Castellon este 36800,00


A Coruña oeste 18600,00 3.11. Eliminar filas duplicadas DISTINCT/ALL
Aranjuez centro 15000,00
SQL no elimina las filas duplicadas en el resultado de la consulta, si nosotros no queremos
Valencia este 0,00 que se repitan las filas, tenemos la cláusula DISTINCT.
Pamplona norte NULL Al incluir la cláusula DISTINCT en la SELECT, se eliminará del resultado las repeticiones de
filas de resultado. Si por el contrario queremos que aparezcan todas las filas seleccionadas
Madrid centro NULL podemos incluir la cláusula ALL o nada, ya que ALL es el valor por defecto.

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

ORDER BY 3 DESC; dir


106
Lo mismo que el anterior pero agrupadas por región. 104

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

SELECT DISTINCT dir [TOP <expresión> [PERCENT] [WITH TIES]]

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

105 Por ejemplo tenemos la siguiente tabla:

106
SELECT * FROM productos:
108

Han desaparecido los valores duplicados.

Los que se eliminan son valores duplicados de filas del resultado, por ejemplo:

SELECT DISTINCT dir, region

FROM oficinas;

dir region
NULL este

NULL norte
Si ordenamos por ventas:
104 este

105 este SELECT * FROM productos


106 este ORDER BY ventas;
108 centro

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.

3.12. La cláusula TOP


Obtenemos el siguiente resultado:
Lic. Vladimir Cotaquispe Gutiérrez. 17 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 18 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Si añadimos la cláusula TOP:
SELECT TOP 10 oficina, ciudad, ventas

SELECT TOP 3 * FROM productos FROM oficinas

ORDER BY ventas ORDER BY ventas;

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.

Si incluimos la palabra PERCENT, entonces n no indica el número de registros a recuperar


sino el porcentaje de registros a recuperar del total de filas recuperadas después de ejecutar la
cláusula WHERE.

SELECT TOP 50 PERCENT *


Si existen más registros con las mismas ventas que el último valor de la lista, éstos no FROM productos
saldrán en el resultado de la consulta.
ORDER BY ventas
En el ejemplo el registro con cod = 2 no sale en el resultado y tiene las mismas ventas que
cod = 3.
Devuelve:
Si queremos que salgan añadimos la cláusula WITH TIES. La cláusula WITH TIES sólo se
puede emplear si la SELECT incluye un ORDER BY, de lo contrario dará error.

Si añadimos la cláusula WITH TIES:

SELECT TOP 3 WITH TIES *

FROM productos

ORDER BY ventas Si el porcentaje no da exacto, siempre redondea al alza.

Obtenemos: 3.13. Selección de filas WHERE

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: }

[{AND|OR} [NOT] {<predicado>|(<condicion_búsqueda>)}]


Lic. Vladimir Cotaquispe Gutiérrez. 19 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 20 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
una subconsulta escalar o
[ ...n ]
cualquier combinación de nombres de columna, constantes y funciones conectados
mediante uno o varios operadores o una subconsulta.
En el resultado de la consulta sólo aparecerán las filas que cumplan que la condición de
búsqueda sea TRUE, los valores NULL no se incluyen, por lo tanto, en las filas del resultado. La Ejemplo:
condición de búsqueda puede ser una condición simple o una condición compuesta por varias
condiciones (predicados) unidas por operadores AND y OR, no hay límite en cuanto al número Listar los "buenos" vendedores (los que han rebasado su cuota).
de predicados que se pueden incluir. En las condiciones compuestas se pueden utilizar
paréntesis para delimitar predicados y se aconseja su uso cuando se incluyen operadores AND
y OR en la misma condición de búsqueda. SELECT numemp, nombre, ventas, cuota

FROM empleados
3.14. Predicados
WHERE ventas > cuota
En SQL tenemos 7 tipos de predicados, condiciones básicas de búsqueda:

numemp nombre ventas cuota


Comparación estándar
101 Antonio Viguer 30500,00 30000,00
Pertenencia a un intervalo (BETWEEN)

Pertenencia a un conjunto (IN) 102 Alvaro Jaumes 47400,00 35000,00

Test de valor nulo (IS NULL). 103 Juan Rovira 28600,00 27500,00

Coincidencia con patrón (LIKE) 105 Vicente Pantalla 36800,00 35000,00

Si contiene (CONTAINS) 106 Luis Antonio 29900,00 27500,00


FREETEXT
108 Ana Bustamante 36100,00 35000,00

Comparación estándar. 109 María Sunta 39200,00 3000,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:

SELECT numemp, nombre


<expresion> {=|<>|!=|>|>=|!>|<|<=|!<} <expresion>
FROM empleados

WHERE ventas > cuota;


<expresion> Puede ser:

Un nombre de columna, Hallar vendedores contratados antes de 1988.

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';

<expresion> [NOT] BETWEEN <expresion2> AND <expresion3>


numemp nombre contrato

101 Antonio Viguer 1986-10-20


Examina si el valor de la expresión de test está en el rango delimitado por los valores
resultantes de expresion1 y expresion2, estos valores no tienen porqué estar ordenados en
102 Alvaro Jaumes 1986-12-10 ANSI/ISO; expresion1 debe ser menor o igual a expresion2.
103 Juan Rovira 1987-03-01
Hallar vendedores cuyas ventas estén entre 20.000 euros y 50.000.
104 José González 1987-05-19
SELECT numemp, nombre, ventas
También podemos utilizar funciones, ésta es equivalente a la anterior: FROM empleados

WHERE ventas BETWEEN 20000 AND 100000;


SELECT numemp, nombre

FROM empleados numemp nombre ventas


WHERE YEAR(contrato) < 1988; 101 Antonio Viguer 30500,00

102 Alvaro Jaumes 47400,00


La función YEAR(fecha) devuelve el año de una fecha.
103 Juan Rovira 28600,00
Hallar oficinas cuyas ventas estén por debajo del 80% de su objetivo:
105 Vicente Pantalla 36800,00

SELECT oficina 106 Luis Antonio 29900,00

FROM oficinas 108 Ana Bustamante 36100,00


WHERE ventas < (.8 * objetivo);
109 María Sunta 39200,00

Hallar las oficinas dirigidas por el empleado 108:


La instrucción anterior es equivalente a:

SELECT oficina
SELECT numemp, nombre, ventas
FROM oficinas
FROM empleados
WHERE dir = 108;
WHERE ventas >= 20000 AND ventas <=100000;

Parece que con BETWEEN se lee mejor.

Observa que no hemos utilizado separadores de millares (100.000), porque se habría


interpretado por una coma decimal.

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;

<expresion> IN ( <exp_valor> [ ,...n ] )


Esta instrucción no da error pero no obtiene lo que en principio parece que quiere obtener.
No obtenemos los empleados cuya oficina sea un valor nulo (es decir los empleados que no
Examina si el valor de la expresion es uno de los valores incluidos en la lista de valores tienen oficina), no obtenemos nada, en cambio los obtendremos utilizando el test de valor nulo:
indicados entre paréntesis. Se pueden expresar los valores mediante cualquier expresión, la
única condición es que todas las exp_valor devuelvan el mismo tipo de datos.
SELECT numemp,nombre, oficina
Ejemplo: FROM empleados

Obtener los empleados que trabajan en las oficinas 11, 20 o 22: WHERE oficina IS NULL;

SELECT oficina, numemp, nombre Resultado:


FROM empleados
numemp nombre oficina
WHERE oficina IN (11,20,22);
110 Juan Victor NULL

oficina numemp nombre


Juan Victor es el único empleado que no tiene oficina asignada.
11 106 Luis Antonio
Listar los vendedores asignados a alguna oficina.
22 107 Jorge Gutiérrez

11 109 María Sunta SELECT numemp, nombre, oficina

FROM empleados
Test de valor nulo IS NULL
WHERE oficina IS NOT NULL;

<expression> IS [NOT] NULL


numemp nombre oficina

101 Antonio Viguer 12


Una condición de búsqueda puede ser TRUE, FALSE o NULL/UNKNOW, este último caso
se produce cuando algún campo que interviene en la condición tiene valor NULL.
102 Alvaro Jaumes 21
A veces es útil comprobar explícitamente los valores NULL en una condición de búsqueda ya
que estas filas puede que queramos darles un tratamiento especial, para ello tenemos el
predicado IS NULL. 103 Juan Rovira 12

104 José González 12


Este test produce un valor TRUE o FALSE, por lo que se podrá combinar con otras
condiciones. El valor NULL no es en sí un valor por eso no lo podemos utilizar en una igualdad.
105 Vicente Pantalla 13

106 Luis Antonio 11


SELECT numemp,nombre

FROM empleados 107 Jorge Gutiérrez 22

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

109 María Sunta 11 104 José González

107 José González

Test de correspondencia con patrón LIKE


Obtiene los nombres que acaban en z.

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

106 Luis Antonio


SELECT numemp,nombre

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

103 Juan Rovira

Obtiene todos los nombres que empiecen por An. 108 Ana Bustamante

110 Juan Victor


SELECT numemp,nombre

FROM empleados
Obtiene los nombres cuya tercera letra sea una a (en el patrón tenemos dos caracteres
WHERE nombre LIKE ‘%z’; subrayado).

[ ] sirve para indicar un carácter cualquiera perteneciente al conjunto indicando.


El conjunto se indica enumerando los caracteres o indicando un intervalo.
Lic. Vladimir Cotaquispe Gutiérrez. 27 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 28 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
La cláusula ESCAPE es opcional y permite definir un carácter de escape.
SELECT numemp,nombre
Un carácter de escape es un carácter que se coloca delante de un carácter comodín para
FROM empleados
indicar que el comodín no debe interpretarse como tal, sino como un carácter normal.
WHERE nombre LIKE '[a-d]%';
Por ejemplo queremos buscar los nombres compuestos que incluyen un subrayado. En este
caso tenemos que poner el carácter _ como un carácter normal no como un comodín, así que lo
Obtiene los nombres que empiezan por cualquier letra de la a a la d. escribiremos así:

Es equivalente a escribir:
SELECT numemp,nombre

FROM empleados
SELECT numemp,nombre
WHERE nombre LIKE '%[_]%';
FROM empleados

WHERE nombre LIKE '[abcd]%';


O bien,

[^] significa cualquier carácter individual que no se encuentre en el conjunto.


SELECT numemp,nombre

FROM empleados
SELECT numemp,nombre
WHERE nombre LIKE '%!_%' ESCAPE '!';
FROM empleados

WHERE nombre LIKE '[^abcd]%';


Existen dos predicados más para evaluar expresiones: CONTAINS y FREETEXT. Puedes
ver más información sobre ellas en este avanzado .
Y
Los predicados CONTAINS y FREETEXT (I)
SELECT numemp,nombre
CONTAINS
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.

CONTAINS puede buscar:

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) | * }

, '< condicion_busqueda >' < valor_ponderado > ::=

[ , LANGUAGE idioma ] ISABOUT

) ( { {

< condicion_busqueda > ::= < termino_simple >

{ < termino_simple > | < prefijo >

| < prefijo > | < generador >

| < generador > | < proximo >

| < proximo > }

| < valor_ponderado > [ WEIGHT ( peso ) ]

} } [ ,...n ]

| { ( < condicion_busqueda > ) )

[ { < AND > | < AND NOT > | < OR > } ]

< condicion_busqueda > [ ...n ]

} Nombre_columna es la columna donde se busca. Las columnas de tipo char, varchar,


nchar, nvarchar, text, ntext, image, xml y varbinary(max) son válidas para la búsqueda de
< AND > ::= { AND | & } texto.

< 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.

< prefijo > ::=


Idioma Es el idioma en que el usuario genera la consulta.
{ "palabra * " | "frase *" }
Condición búsqueda especifica el texto que se va a buscar y las condiciones para obtener
< generador > ::= coincidencias.
FORMSOF ( { INFLECTIONAL | THESAURUS } , < termino_simple > [
Palabra es una cadena de caracteres sin espacios ni signos de puntuación.
,...n ] )

< 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.

{ < termino_simple > | < prefijo > }


Lic. Vladimir Cotaquispe Gutiérrez. 31 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 32 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
INFLECTIONAL especifica que se va a utilizar el analizador lingüístico dependiente del Lista_columnas indica una lista de columnas separadas por comas.
idioma en el término simple especificado. El comportamiento del analizador lingüístico se define
en función de las reglas de análisis lingüístico de cada idioma concreto. El idioma neutro no El asterisco ( * ) especifica que todas las columnas de la tabla válidas para búsquedas
tiene ningún analizador lingüístico asociado. El idioma de las columnas que se van a consultar de texto se deben utilizar en la condición de búsqueda. Las columnas de la cláusula
se utiliza para hacer referencia al analizador lingüístico deseado. Si se especifica idioma, se CONTAINS deben proceder de una sola tabla. Si en la cláusula FROM hay más de una
utiliza el analizador lingüístico correspondiente a dicho idioma. tabla, * se tiene que especificar con el nombre de la tabla.

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

FREETEXT 3.15. Condiciones de búsqueda compuestas

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.

, 'cadena_freetext' [ , LANGUAGE idioma ] )


Los operadores lógicos pueden devolver tres valores distintos: TRUE, FALSE, NULL
(UNKNOWN).

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

WHERE NOT dir = 108;


AND TRUE FALSE NULL
TRUE TRUE FALSE NULL
O
FALSE FALSE FALSE FALSE
NULL NULL FALSE NULL
SELECT oficina
OR Combina dos condiciones y se evalúa como TRUE cuando alguna de las condiciones es FROM oficinas
TRUE.
WHERE dir <> 108;
OR TRUE FALSE NULL
TRUE TRUE TRUE TRUE Devuelven:
FALSE TRUE FALSE NULL
NULL TRUE NULL NULL oficina
11
NOT Niega la expresión booleana que especifica el predicado 12
13
NOT TRUE FALSE NULL
FALSE TRUE NULL Las oficinas sin director no aparecen, para que aparezcan deben añadir otro predicado:

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

WHERE ventas < cuota AND ventas < 30000;


oficina dir
11 106
Hallar los vendedores que están debajo de su cuota, pero cuyas ventas no sean inferiores a 12 104
150.000.
13 105
26 NULL
SELECT nombre
28 NULL
FROM empleados

WHERE ventas < cuota AND ventas < 150000;

Hallar las oficinas no dirigidas por el empleado 108

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

El producto cartesiano CROSS JOIN El resultado sería:


La composición interna INNER JOIN
OFI ciudad
La composición externa LEFT JOIN, RIGHT JOIN Y FULL JOIN
11 Valencia
En todo el tema cuando hablemos de tablas nos referiremos tanto a las tablas que
físicamente están almacenadas en la base de datos como a las tablas temporales y a las
resultantes de una consulta o vista. 28 Valencia

4.2. La unión de tablas UNION 23 Madrid

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:

SELECT oficina as OFI, ciudad FROM Valencia


{< consulta >|(< consulta >)}
UNION
UNION [ALL]
SELECT oficina, ciudad FROM Madrid
{< consulta >|(< consulta >)}
ORDER BY ofi;
[{UNION [ALL] {< consulta >|(< consulta >)}}[ ...n ] ]

[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}


Lic. Vladimir Cotaquispe Gutiérrez. 37 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 38 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
OFI ciudad
WHERE importe > 300;
11 Valencia

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 ] ]

[ORDER BY {expression_columna|posicion_columna [ASC|DESC]}


Se pueden combinar varias tablas con el operador UNION. Por ejemplo supongamos que
tenemos otra tabla Pamplona con las oficinas nuevas de Pamplona: [ ,...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

SELECT idfab, idproducto


SELECT cod FROM T1
FROM productos
EXCEPT
WHERE precio > 20
SELECT codigo FROM T2;
UNION

SELECT fab, producto Devuelve:


FROM pedidos
Lic. Vladimir Cotaquispe Gutiérrez. 39 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 40 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
Cod Devuelve:

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

SELECT fab, producto


4.4. La intersección INTERSECT
FROM pedidos
Tiene una sintaxis parecida a las anteriores pero en el resultado de la intersección aparecen
las filas que están simultáneamente en las dos consultas. WHERE importe > 300;
Las condiciones son las mismas que las de la unión.

{ <consulta>|(<consulta>)}

INTERSECT 4.5. La composición de tablas


{<especificacion_consulta>|(<especificacion_consulta>)} Hasta ahora hemos operado con tablas que tenían el mismo esquema, pero muchas veces
lo que necesitamos es obtener una tabla que tenga en una misma fila datos de varias tablas,
[{INTERSECT {<consulta>|(<consulta>)}} [ ...n ] ] por ejemplo, obtener las facturas y que en la misma fila de factura aparezca el nombre y
[ORDER BY {expression_columna|posicion_columna [ASC|DESC]} dirección del cliente. Pues en lo que queda del tema estudiaremos este tipo de consultas
basadas en la composición de tablas. La composición de tablas consiste en obtener a partir de
[ ,...n ]] dos tablas cualesquiera una nueva tabla fusionando las filas de una con las filas de la otra,
concatenando los esquemas de ambas tablas. Consiste en formar parejas de filas.

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.

FROM {<tabla_origen>} [ ,...n ] SELECT empleados.*,ciudad, region


|<tabla_origen> CROSS JOIN <tabla_origen> FROM empleados, oficinas

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 oficinas, oficinas as ofi2;


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>

SELECT * tabla_origen tiene el mismo significado que en el producto cartesiano.


condicion_combi es cualquier condición que permite seleccionar las parejas de filas que
FROM empleados, oficinas aparecen en el resultado. Normalmente será una condición de igualdad.
Lic. Vladimir Cotaquispe Gutiérrez. 43 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 44 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
109 María Sunta 11 Valencia
SELECT *

FROM empleados INNER JOIN oficinas


No aparecen los empleados que no tienen oficina, ni las oficinas que no tienen empleados,
ON empleados.oficina=oficinas.oficina; porque para que salga la fila, debe de existir una fila de la otra tabla que cumpla la condición.

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.

4.8. La Composición externa LEFT, RIGHT y FULL OUTER JOIN


SELECT *

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

ON empleados.oficina=oficinas.oficina; SELECT numemp,nombre,empleados.oficina, ciudad

FROM empleados LEFT JOIN oficinas


numemp nombre oficina ciudad ON empleados.oficina=oficinas.oficina;
101 Antonio Viguer 12 Alicante

102 Alvaro Jaumes 21 Badajoz numemp nombre oficina ciudad


101 Antonio Viguer 12 Alicante
103 Juan Rovira 12 Alicante 102 Alvaro Jaumes 21 Badajoz
104 José González 12 Alicante 103 Juan Rovira 12 Alicante
104 José González 12 Alicante
105 Vicente Pantalla 13 Castellón 105 Vicente Pantalla 13 Castellón
106 Luis Antonio 11 Valencia 106 Luis Antonio 11 Valencia
107 Jorge Gutiérrez 22 A Coruña
107 Jorge Gutiérrez 22 A Coruña
108 Ana Bustamante 21 Badajoz
108 Ana Bustamante 21 Badajoz 109 María Sunta 11 Valencia

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

FROM empleados RIGHT JOIN oficinas 108 Ana Bustamante 21 Badajoz 21


109 María Sunta 11 Valencia 11
ON empleados.oficina=oficinas.oficina;
110 Juan Victor NULL NULL NULL
NULL NULL NULL Madrid 23
numemp nombre oficina ciudad oficina NULL NULL NULL Aranjuez 24
106 Luis Antonio 11 Valencia 11 NULL NULL NULL Pamplona 26
109 María Sunta 11 Valencia 11 NULL NULL NULL Valencia 28
101 Antonio Viguer 12 Alicante 12
103 Juan Rovira 12 Alicante 12 Aparecen tanto los empleados sin oficina como las oficinas sin empleados.
104 José González 12 Alicante 12
105 Vicente Pantalla 13 Castellón 13 SELECT numemp,nombre,empleados.oficina, ciudad, oficinas.oficina
102 Alvaro Jaumes 21 Badajoz 21
FROM empleados FULL OUTER JOIN oficinas
108 Ana Bustamante 21 Badajoz 21
107 Jorge Gutiérrez 22 A Coruña 22 ON empleados.oficina=oficinas.oficina;
NULL NULL NULL Madrid 23
NULL NULL NULL Aranjuez 24 Es equivalente, la palabra OUTER como hemos dicho no añade ninguna funcionalidad y se
NULL NULL NULL Pamplona 26 utiliza si se quiere por cuestiones de estilo.
NULL NULL NULL Valencia 28
NOTA: Cuando necesitamos obtener filas con datos de dos tablas con una condición de
combinación utilizaremos un JOIN, os aconsejo empezar por escribir el JOIN con la condición
Las oficinas 23,24,26 y 28 no tienen empleados. que sea necesaria para combinar las filas, y luego plantearos si la composición debe de ser
interna o externa. Para este segundo paso ésta sería la norma a seguir:
Obtiene los empleados con su oficina y las oficinas (tabla a la derecha RIGHT del JOIN) que
no tienen empleados aparecerán también en el resultado con los campos de la tabla empleados Empezamos con INNER JOIN.
rellenados a NULL.
Si pueden haber filas de la primera tabla que no estén relacionadas con filas de la
segunda tabla y nos interesa que salgan en el resultado, entonces cambiamos a LEFT
JOIN.

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.

Por ejemplo: Un ejemplo sería:

SELECT numemp, nombre, empleados.oficina, ciudad, oficinas.oficina,


pedidos.*

FROM (oficinas RIGHT JOIN empleados

ON empleados.oficina = oficinas.oficina)

INNER JOIN pedidos on rep=numemp;

O bien:

SELECT numemp, nombre, empleados.oficina, ciudad, oficinas.oficina,


pedidos.*

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

5.2. Las funciones de agregado

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;

Todas las funciones de agregado tienen una estructura muy parecida:


Devuelve 9 porque tenemos nueve valores no nulos en la columna region. A la hora de
interpretar un COUNT es conveniente no olvidar que cuenta valores no nulos, por ejemplo si
Función ([ALL|DISTINCT] expression) interpretáramos la sentencia tal cual se lee, “cuántas regiones tenemos en oficinas” sería
erróneo, realmente estamos obteniendo cuántas oficinas tienen una región asignada.

El grupo de valores sobre el que actúa la función lo determina el resultado de la expresión


que será un nombre de columna o una expresión basada en una columna o varias del origen de
datos. En la expresión nunca puede aparecer una función de agregado ni una subconsulta. SELECT COUNT(DISTINCT 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:

COUNT ({[ALL|DISTINCT] expresion | * } )


SELECT COUNT(*) FROM empleados WHERE oficina IS NOT NULL;

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.

Devuelve el valor máximo de la expresión sin considerar los nulos.


SELECT SUM(importe) FROM pedidos;
MAX 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.
Obtiene el importe total vendido en todos los pedidos.

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

Por ejemplo: FROM oficinas;

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;

5.8. La función AVG


Devuelve 9 porque tenemos nueve valores no nulos en la columna region. A la hora de
interpretar un COUNT es conveniente no olvidar que cuenta valores no nulos, por ejemplo si
interpretáramos la sentencia tal cual se lee, “cuántas regiones tenemos en oficinas” sería AVG ([ALL|DISTINCT] expresion )
erróneo, realmente estamos obteniendo cuántas oficinas tienen una región asignada.

Devuelve el promedio de los valores de un grupo, para calcular el promedio se omiten los
5.6. La función MIN valores nulos.

El grupo de valores lo determina el resultado de la expresión que será un nombre de


MIN ([ALL|DISTINCT] expression)
columna o una expresión basada en una columna o varias del origen de datos.

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 } ]

Devuelve la desviación típica estadística de todos los valores de la expresión especificada.


Sólo se puede utilizar con columnas numéricas. Los valores NULL se pasan por alto. Una consulta con una cláusula GROUP BY agrupa los datos de la tabla origen y produce
una única fila resultado por cada grupo formado. Las columnas indicadas en el GROUP BY se
llaman columnas de agrupación o agrupamiento .
5.12. La función STDEVP
Cuando queremos realizar una agrupación múltiple, por varias columnas, éstas se indican en
la cláusula GROUP BY en el orden de mayor a menor agrupación igual que con la cláusula
STDEVP ([ALL|DISTINCT] expresion ) ORDER BY.

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

Resultado: 105 2111 1 37,45

oficina Número de empleados 106 2101 1 14,58

NULL 2 107 2109 1 313,50

11 2 107 2124 2 24,30

12 3 108 2112 1 29,25

13 1 108 2114 1 71,00

21 2 108 2118 3 14,20

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;

SELECT rep, clie, count(numpedido) AS [Número de pedidos], MAX(importe)


Resultado: AS [Importe máximo]

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 Por ejemplo:

WHERE YEAR(fechapedido) = 1997


SELECT rep, clie, count(numpedido) AS [Número de pedidos], MAX(importe)
GROUP BY rep, clie WITH ROLLUP; 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.

102 NULL 3 37,50


Si cogemos por ejemplo la primera fila remarcada (101 NULL …) el valor NULL, no sabemos
103 2111 2 21,00 si se refiere a una fila de subtotal o a que el representante 101 ha realizado un pedido sin
103 NULL 2 21,00 número de cliente. Para poder salvar este problema se utiliza la función de agregado
GROUPING.
105 2103 4 275,00
105 2111 1 37,45
SELECT rep, clie, count(numpedido) AS [Número de pedidos], MAX(importe)
105 NULL 5 275,00
AS [Importe máximo], GROUPING(clie) AS [Fila resumen]
106 2101 1 14,28
FROM pedidos
106 NULL 1 14,28
107 2109 1 313,50 WHERE YEAR(fechapedido) = 1997
107 2124 2 24,30 GROUP BY rep, clie WITH ROLLUP;
107 NULL 3 313,50
108 2112 1 29,25
Número Importe Fila
108 2114 1 71,00 rep clie
de pedidos máximo Resumen
108 2118 3 14,20 101 2113 1 225,00 0
108 NULL 5 71,00 101 NULL 1 225,00 1
... ... ... ... 102 2106 2 21,30 0
NULL NULL 23 450,00 102 2120 1 37,50 0
NULL 2101 1 14,58 102 NULL 3 37,50 1
NULL 2103 4 275,00 103 2111 2 21,00 0
NULL 2106 2 21,30
NULL 2107 1 6,32 Las filas que corresponden a subtotales aparecen con un 1 y las normales con un cero.
NULL 2108 1 56,25
Ahora que estamos más familiarizados con las columnas de agrupamiento debemos
NULL 2109 1 313,50 comentar una regla a no olvidar:
NULL 2111 3 37,45
NULL 2112 2 450,00 EN LA LISTA DE SELECCIÓN DE UNA CONSULTA DE RESUMEN UN NOMBRE DE
COLUMNA NO PUEDE APARECER FUERA DE UNA FUNCIÓN DE AGREGADO SI NO ES
NULL 2113 1 225,00 UNA COLUMNA DE AGRUPACIÓN.
NULL 2114 1 71,00

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:

El nombre de una columna dentro de la subconsulta se presupone del origen de datos de la


subconsulta y, sólo si no se encuentra en ese origen, la considera como columna externa y la <expresion> {=|<>|!=|>|>=|!>|<|<=|!<} <subconsulta>
busca en el origen de la consulta externa.

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');

Si la subconsulta devuelve más de una fila o más de una columna, da error.


Por cada empleado se calcula la lista de las oficinas del Este (nº de oficina) y se evalúa si la
Ejemplo: oficina del empleado está en esta lista. Obtenemos pues los empleados de oficinas del Este.

numemp nombre edad oficina titulo contrato jefe cuota ventas


SELECT nombre
101 Antonio 45 12 representante 1986- 104 30000,00 30500,00
FROM empleados Viguer 10-20
103 Juan 29 23 representante 1987- 104 27500,00 28600,00
WHERE cuota <= (SELECT SUM(importe)
Rovira 03-01
FROM pedidos 104 José 33 23 dir ventas 1987- 106 20000,00 14300,00
González 05-19
WHERE rep = numemp); 105 Vicente 37 13 representante 1988- 104 35000,00 36800,00
Pantalla 02-12
106 Luis 52 11 dir general 1988- NULL 27500,00 29900,00
La subconsulta devuelve una sola columna y como mucho una fila ya que es una consulta Antonio 06-14
de resumen sin cláusula GROUP BY.
Si la subconsulta no devuelve ninguna fila:
6.3. Subconsultas de lista de valores
SELECT *
Otro tipo de subconsultas son las que devuelven una lista de valores en forma de una
columna y cero, una o varias filas. FROM empleados

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

WHERE region = 'Otro');


6.4. El operador IN con subconsulta

<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 INNER JOIN oficinas ON empleados.oficina =


Ejemplo: oficinas.oficina

WHERE region = 'Este';


SELECT *

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

WHERE oficina NOT IN (SELECT oficina


<expresion> NOT IN subconsulta
FROM empleados);

Devuelve TRUE si el valor de la expresión no está en la lista de valores devueltos por la


subconsulta. Esta consulta no devuelve ninguna fila cuando sí debería ya que hay oficinas que nos están
asignadas a ningún empleado. El problema está en que la columna oficina de la tabla
empleados admite nulos por lo que la subconsulta devuelve valores nulos en todos los
SELECT * empleados que no están asignados a ninguna oficina. Estos valores nulos hacen que no se
cumpla el NOT IN. La solución pasa por eliminar estos valores molestos:
FROM empleados

WHERE oficina NOT IN (SELECT oficina SELECT *


FROM oficinas FROM Oficinas
WHERE region = 'Este'); WHERE oficina NOT IN (SELECT oficina

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);

OJO con NOT IN.


En el primer ejemplo no tenemos ese problema porque la columna oficina en oficinas no
admite nulos.
Hay que tener especial cuidado con los valores nulos cuando utilizamos el operador NOT IN
porque el resultado obtenido no siempre será el deseado por ejemplo:
A diferencia de IN, NOT IN no siempre puede resolverse con una composición:
* En la consulta anterior no salen los empleados que no tienen oficina ya que para esos
empleados la columna oficina contiene NULL por lo que no se cumple el NOT IN.
SELECT numemp AS [IN]
* Si la subconsulta no devuelve ninguna fila, la condición se cumplirá para todas las filas de FROM empleados
la consulta externa, en este caso todos los empleados.
WHERE numemp IN (SELECT rep
* Si la subconsulta devuelve algún valor NULL, la condición NOT IN es NULL lo que nos
puede ocasionar algún problema. FROM pedidos

WHERE fab = 'ACI');


Por ejemplo, queremos obtener las oficinas que no están asignadas a ningún empleado.

Se puede resolver con una composición:

SELECT DISTINCT empleados.numemp AS [=]

FROM Empleados INNER JOIN pedidos ON numemp = rep

WHERE fab = 'ACI';

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

WHERE numemp NOT IN (SELECT rep SELECT *


FROM pedidos FROM empleados
WHERE fab = 'ACI'); WHERE cuota > ANY (SELECT cuota

FROM empleados empleados2


No se puede resolver con una composición:
WHERE empleados.oficina =
empleados2.oficina);
SELECT DISTINCT empleados.numemp AS [<>]

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

FROM empleados empleados2


Lic. Vladimir Cotaquispe Gutiérrez. 71 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA Lic. Vladimir Cotaquispe Gutiérrez. 72 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA
Power Builder + Sql Power Builder + Sql
No se realiza ninguna comparación con los valores devueltos por la subconsulta,
WHERE empleados.oficina = simplemente se evalúa si la subconsulta devuelve alguna fila, en este caso EXISTS será True y
empleados2.oficina); si la subconsulta no devuelve ninguna fila, EXISTS será False.

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

WHERE numemp = rep and fab ='ACI');


WHERE empleados.oficina = empleados2.oficina

AND empleados.numemp <> empleados2.numemp);


Obtenemos los empleados que tengan un pedido del fabricante ACI. Por cada empleado, se
calcula la subconsulta (obteniendo los pedidos de ese empleado y con fabricante ACI), si existe
alguna fila, el empleado sale en el resultado, si no, no sale.
De esta forma saldrían los empleados que tienen una cuota mayor que cualquier otro
empleado de su misma oficina.
Cuando se utiliza el operador EXISTS es muy importante añadir una referencia externa, no
es obligatorio pero en la mayoría de los casos será necesario. Veámoslo con ese mismo
O bien ejemplo, si quitamos la referencia externa:

WHERE empleados.oficina = empleados2.oficina SELECT *


AND empleados.cuota <> empleados2.cuota); FROM empleados

WHERE EXISTS (SELECT *


Para no considerar los empleados que tengan la misma cuota que el empleado. En este
caso saldrían los empleados con la mayor cuota de sus oficina, pero si dos empleados tienen la FROM pedidos
misma cuota superior, saldrían, hecho que no sucedería con la otra versión.
WHERE fab ='ACI');
Cuando la comparación es una igualdad, = ANY es equivalente a IN y <> ALL es equivalente
a NOT IN (con los mismos problemas).
Sea el empleado que sea, la subconsulta siempre devolverá filas (si existe algún pedido
cuyo fabricante sea ACI) o nunca, indistintamente del empleado que sea, por lo que se
obtendrán todos los empleados o ninguno para que el resultado varíe según las filas de la
consulta externa habrá que incluir una referencia externa.

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

WHERE NOT EXISTS (SELECT *

FROM pedidos

WHERE fab ='ACI' AND rep=numemp);

Devuelve los empleados que no tienen ningún pedido de ACI.

Lic. Vladimir Cotaquispe Gutiérrez. 75 E.P. DE INGENIERIA DE SISTEMA E INFORMATICA

You might also like