Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
CAPTULO 31
ndice de contenido
COMPLIQUEMOS UN POCO LAS CONSULTAS DE SELECCIN..............................................2
VAMOS ALL................................................................................................................................2
CREACIN DE LITERALES.....................................................................................................2
UTILIZACIN DE ALIAS.........................................................................................................3
ALIAS DIRECTO COMO CAMPO..........................................................................................3
ALIAS DIRECTO COMO TABLA............................................................................................4
ALIAS INDIRECTO: USO DE FUNCIONES AGREGADAS.................................................5
OPERACIONES MATEMTICAS Y OTRAS POSIBILIDADES..................................6
FUNCIONES DE VALORES SIMPLES...............................................................................7
ABS().................................................................................................................................8
SQR().................................................................................................................................8
MOD()...............................................................................................................................8
ROUND()..........................................................................................................................8
FUNCIONES DE GRUPOS DE VALORES (FUNCIONES DE AGREGADO)..................8
COUNT()...........................................................................................................................8
SUM()................................................................................................................................9
AVG()................................................................................................................................9
STDEV() / STDEVP().......................................................................................................9
FIRST() / LAST()............................................................................................................10
MAX() / MIN()................................................................................................................10
CONSULTAS ANIDADAS, O SUBCONSULTAS...........................................................................10
UTILIZANDO IN......................................................................................................................10
UTILIZANDO ANY/SOME..................................................................................................12
UTILIZANDO EXISTS.............................................................................................................12
COMBINACIN DE ELEMENTOS EN SQL..................................................................................13
COMBINACIN EXTERNA (O LLMAME... OUTER JOINS)...........................................13
CORRESPONDENCIA CON LAS CONSULTAS-OBJETO EN ACCESS. TIPOS DE
COMBINACIN......................................................................................................................15
COMBINACIN INTERNA (O LLMAME... INNER JOIN)...............................................16
CONSULTA UNION / UNION ALL.....................................................................................17
CONSULTA TRANSFORM......................................................................................................19
AUTOCOMBINACIN................................................................................................................21
SELF JOIN....................................................................................................................................22
CLUSULA HAVING...................................................................................................................24
PARA FINALIZAR ESTE CAPTULO.............................................................................................25
1
Vistame en http://siliconproject.com.ar/neckkito/
CREACIN DE LITERALES
Puede interesarnos, en un momento dado, mostrar una informacin puntual a travs de una
consulta, e identificar claramente qu informacin estamos obteniendo.
Para estos casos podemos hacer uso de literales.
Un literal no es ms que una cadena de texto que nos mostrar el valor literal que hayamos
escrito en cada registro de la consulta.
La estructura para un literal podra ser la siguiente:
SELECT nomTabla.nomCampo1, 'Literal', nomTabla.nomCampo2
FROM nomTabla
Supongamos que queremos ver las ventas, pero con impuestos incluidos, y que nuestro
impuesto es el 18%. Para no perder de vista que estamos trabajando con valores impuesto
incluido podramos querer que en cada registro se mostrara dicha informacin.
Nuestro cdigo con la SQL pertinente sera el siguiente:
Vistame en http://siliconproject.com.ar/neckkito/
Fijaos que, aunque no sea una solucin muy elegante, para una consulta puntual nos puede
sacar del apuro.
Tambin cabe destacar que podemos realizar operaciones matemticas con los valores de los
registros directamente sobre la SQL. En nuestro caso hemos multiplicado por 1,18:
TVentas.ImpVta*1.18
UTILIZACIN DE ALIAS
En ocasiones puede interesarnos crear un campo que no existe inicialmente en la tabla. Esta
creacin puede ser realizada de dos maneras:
De manera directa
De manera indirecta, porque aplicamos alguna funcin.
Y qu es un alias? Para que nos entendamos, es el nombre que nos inventamos para poder
hacer referencia a ese campo que no existe, inicialmente.
Supongo que, hasta ahora, la cosa est clara (o no?). La verdad es que sin ver un ejemplo
este concepto puede parecer un poco difuso. Vamos pues a plantear una hiptesis de trabajo
para la creacin de un alias de manera directa.
Vistame en http://siliconproject.com.ar/neckkito/
Private Sub cmdAliasPunteado_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CAliasPunteado"
Call eliminaConsulta(nomQuery)
miSql = "SELECT TVentas.IdCliVta, TVentas.ImpVta, NULL AS Punteado" _
& " FROM TVentas" _
& " WHERE TVentas.FechVta>#12-31-2011#"
Call creaConsulta(nomQuery, miSql)
DoCmd.OpenQuery nomQuery
End Sub
El campo que hace de filtro NO tiene porqu mostrarse en los resultado (filtramos por
fecha de venta pero no se ve en la consulta)
Vistame en http://siliconproject.com.ar/neckkito/
Para comodidad de lectura de cdigo podemos utilizar AS, aunque en el caso de tablas
podemos poner el alias directamente, sin necesidad de utilizar el AS.
Por ejemplo, el siguiente cdigo utiliza un alias sobre la
tabla:
Si nos fijamos hemos definido el alias sobre la tabla tras la clusula FROM, a travs de ( FROM
TVentas AS TV), y todas las referencias a nomTabla han sido hechas con TV.
Si hubiramos escrito nuestra SQL as (fijaos lo escrito tras el FROM) nuestra SQL funcionara
igualmente bien:
miSql = "SELECT TV.IdCliVta, TV.ImpVta, 'NO' AS Punteado" _
& " FROM TVentas TV" _
& " WHERE TV.FechVta<=#12-31-2011# AND TV.ImpVta>8000"
Vistame en http://siliconproject.com.ar/neckkito/
'-----Esta otra SQL tambin conseguira lo mismo----------------------------------------' miSql = "SELECT TVentas.IdCliVta, TVentas.ImpVta," _
'
& " TVentas.ImpVta*0.18 AS Impuesto, TVentas.ImpVta*1.18 AS ImpConImpto" _
'
& " FROM TVentas"
'---------------------------------------------------------------------------------------Call creaConsulta(nomQuery, miSql)
DoCmd.OpenQuery nomQuery
End Sub
Importante: recordad que para operar con exponentes debemos utilizar el smbolo (^),
Vistame en http://siliconproject.com.ar/neckkito/
Vistame en http://siliconproject.com.ar/neckkito/
negrita.
As, en los siguientes epgrafes slo os mostrar lo que debera ser
la SQL.
ABS()
Devuelve el VALOR ABSOLUTO de un nmero. En la tabla de
ejemplo no se van a producir variaciones en el resultado
porque no hay valores negativos, pero, si los hubiera,
quedaran convertidos en valores positivos.
miSql = "SELECT Abs(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
SQR()
Devuelve la RAZ CUADRADA de un valor.
miSql = "SELECT Sqr(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
MOD()
Devuelve el RESTO DE LA DIVISIN de un valor entre otro valor.
La SQL muestra el resto de dividir el importe de las ventas entre cinco
miSql = "SELECT (TVentas.ImpVta MOD 5) As Resultado" _
& " FROM TVentas"
ROUND()
La funcin Round() REDONDEA LOS DECIMALES DE UN VALOR AL NMERO DE DECIMALES
QUE INDICAMOS, siguiendo la estructura:
Round(<valor>,<n de decimales>)
La siguiente SQL redondea los decimales del importe de ventas a un solo decimal.
miSql = "SELECT Round(TVentas.ImpVta,1) As Resultado" _
& " FROM TVentas"
COUNT()
Esta funcin devuelve la CUENTA de los registros.
Si queremos saber cuntos registros cumplen la condicin de que las ventas sean superiores a
8
Vistame en http://siliconproject.com.ar/neckkito/
SUM()
Devuelve la SUMA de los valores seleccionados.
Si queremos saber el total de ventas realizadas tendramos:
miSql = "SELECT Sum(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
AVG()
Devuelve el PROMEDIO de los valores seleccionados.
As, el promedio de todas las ventas sera:
miSql = "SELECT Avg(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
VAR() / VARP()
La funcin Var() devuelve la VARIANZA DE UNA MUESTRA DE POBLACIN; la funcin Varp()
devuelve la VARIANZA DE UNA POBLACIN.
La SQL sera (ejemplo con Var(); con Varp() la estructura sera la misma):
miSql = "SELECT Var(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
STDEV() / STDEVP()
La funcin Stdev() devuelve la DESVIACIN ESTNDAR DE UNA MUESTRA DE POBLACIN; la
funcin Stdevp() devuelve la DESVIACIN ESTNDAR DE UNA POBLACIN.
La SQL sera (ejemplo con StDev(); con StDevp() la estructura sera la misma):
miSql = "SELECT Stdev(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
Vistame en http://siliconproject.com.ar/neckkito/
FIRST() / LAST()
First() devuelve el valor DEL PRIMER REGISTRO; Last() devuelve el valor DEL LTIMO
REGISTRO.
MAX() / MIN()
Max() devuelve el valor MXIMO de un grupo de registros; Min() devuelve el valor MNIMO de
un grupo de registros.
La siguiente SQL nos muestra la venta mayor de las que se han realizado:
miSql = "SELECT Max(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
y la siguiente nos muestra la venta ms pequea que se ha conseguido:
miSql = "SELECT Min(TVentas.ImpVta) As Resultado" _
& " FROM TVentas"
UTILIZANDO IN
Planteemos el problema: queremos saber el detalle del importe de las ventas realizadas por los
clientes (hasta aqu ya deberamos saber hacerlo), pero slo de los clientes que estn en las
poblaciones de Badajoz y Cdiz.
Bueno, bueno... primer problema que tenemos: las ventas estn en una tabla y las poblaciones
10
Vistame en http://siliconproject.com.ar/neckkito/
estn en otra.
Si operramos con la consulta como objeto de Access con
toda probabilidad sabramos cmo hacerlo: aadiramos
ambas tablas, las relacionaramos por su identificador y
filtraramos por los valores que queremos.
La anterior operacin la podramos realizar utilizando la
operacin INNER JOIN (que veremos ms adelante). Pero
en este apartado vamos a realizar una subconsulta para
conseguir el mismo efecto.
Vayamos por partes, empezando por detrs:
Si quisiramos realizar una SQL que nos filtrara los clientes de Badajoz y Cdiz, cogiendo su
identificador de cliente, escribiramos:
miSql = "SELECT TClientes.IdCli FROM TClientes" _
& " WHERE TClientes.PoblCli IN ('Badajoz','Cdiz')"
Y esto ya lo sabemos hacer.
La anterior consulta nos devuelve los valores {2,5,10}
Para construir la SQL principal podramos pues escribir:
miSql = "SELECT TVentas.IdCliVta, TVentas.ImpVta FROM TVentas" _
& " WHERE TVentas.IdCliVta IN (2,5,10)
Estamos de acuerdo?
Pues bsicamente se trata de sustituir los valores por la consulta que nos proporciona esos
valores.
Es decir, que nuestro cdigo nos quedara as:
Slo llamar la atencin sobre el hecho de que no debemos olvidarnos el parntesis de cierre
del IN () de la consulta principal.
11
Vistame en http://siliconproject.com.ar/neckkito/
UTILIZANDO ANY/SOME
Los predicados ANY o SOME son sinnimos, por lo que
podemos emplear tanto uno como otro. Se utilizan como
comparadores de los resultados que devuelve la
subconsulta.
Por ejemplo, imaginemos que queremos ver una lista con
todos los datos de los clientes que han realizado compras
durante el ao 2011. Nuestra SQL podra quedar de la
siguiente manera:
UTILIZANDO EXISTS
Con el predicado EXISTS lo que obtenemos es un TRUE o FALSE; es decir, comprobamos si la
subconsulta nos dice S o No.
Por ejemplo, queremos saber qu clientes NO han realizado ninguna compra durante el ao
2011. Ser nuestra subconsulta la que nos dir si s han realizado compra o no, y la consulta
principal nos mostrar los resultados:
Vistame en http://siliconproject.com.ar/neckkito/
Fijaos en que:
Para saber si el cliente existe hemos tenido que indicar la
correspondencia del identificador de cliente, necesario para
que la SQL funcione
(& " Tclientes.IdCli=TVentas.IdCliVta))")
13
Vistame en http://siliconproject.com.ar/neckkito/
Private Sub cmdOuterJoins_Click()
Dim miSql As String, nomQuery As String
nomQuery = "COuterJoins"
Call eliminaConsulta(nomQuery)
miSql
&"
&"
&"
Vistame en http://siliconproject.com.ar/neckkito/
15
Vistame en http://siliconproject.com.ar/neckkito/
.- Nos situamos sobre la lnea de relacin y, con mucho pulso, hacemos click con el botn de la
derecha. Nos saldr un men contextual con dos opciones:
16
Vistame en http://siliconproject.com.ar/neckkito/
Rbanos
Buenitos
porque
no
tiene
Vistame en http://siliconproject.com.ar/neckkito/
nomQuery = "CUnion"
Call eliminaConsulta(nomQuery)
miSql
&"
&"
&"
&"
Como vemos he tenido que crear un campo que me uniera el nombre del trabajador y su
apellido porque el nombre de la empresa corresponde slo a un campo, no a dos; en definitiva,
lo que os comentaba de conseguir una estructura consistente.
Para saciar vuestra segura curiosidad, aqu tenis capturado un fragmento de lo que devolvera
la anterior consulta:
18
Vistame en http://siliconproject.com.ar/neckkito/
Os copio aqu algunas indicaciones que da la propia ayuda de Access sobre este tipo de
consultas que creo que pueden seros tiles:
<<De forma predeterminada, no se devuelven registros duplicados cuando se usa la operacin UNION; sin embargo,
puede incluir el predicado ALL para asegurarse de que se devuelven todos los registros. Adems, de esta manera, la
consulta se ejecuta ms rpidamente.
Todas las consultas de una operacin UNION deben solicitar el mismo nmero de campos; sin embargo, no es
necesario que los campos sean del mismo tamao o tipo de datos.
Use alias slo en la primera instruccin SELECT, ya que en las dems se omiten. En la clusula ORDER BY, haga
referencia a los campos por el nombre que se utilice en la primera instruccin SELECT.>>
Y, para acabar, tened en cuenta que las consultas de unin NO ADMITEN el uso de campos tipo
hipervnculo, objeto OLE o Datos Adjuntos. Si los intentis utilizar el campo os saldr con
#ERROR
CONSULTA TRANSFORM
Una SQL con la instruccin TRANSFORM es lo que en Access conocemos como consulta de
referencias cruzadas
La estructura en general de una SQL con TRANSFORM sera:
TRANSFORM
<funcin de agregado>
SELECT FROM
GROUP BY
PIVOT
Vamos a ver cmo aplicamos lo anterior para construirnos una SQL. Lo haremos razonndolo
porque este tipo de consulta, para quienes la ven por primera vez, puede parecer muy
complicada, aunque no tiene por qu serlo.
Imaginemos que queremos ver la suma por clientes y por meses, correspondientes al ao
2012. Quedmonos con este enunciado, pues ser el hilo conductor para realizar la SQL.
Hemos dicho que queremos ver la suma de las ventas. Esto ya nos da el primer elemento de
la SQL. Y como contiene una funcin de agregado (suma) ser lo primero que escribiremos en
la SQL. As:
TRANSFORM
Sum(TVentas.ImpVta) As Ventas
19
Vistame en http://siliconproject.com.ar/neckkito/
Sigamos:
Cul es el criterio de la vista que queremos obtener? Pues el criterio es por clientes y por
meses.
Vamos a por el primer criterio. Necesitamos los clientes...
pues vamos a seleccionarlos:
SELECT TVentas.IdCliVta FROM TVentas
pero vamos a necesitar un filtro, porque slo queremos
incluir las ventas del ao 2012. Pues sigamos como si
construyramos una SQL filtrada:
WHERE TVentas.FechVta>=#01-01-12#
Recordamos qu ocurra cuando utilizbamos una funcin de agregado? Pues lo
comentbamos en el apartado anterior Combinacin externa, con el error 3122. As que... a
agrupar
GROUP BY TVentas.IdCliVta
Y vamos a por el segundo criterio. Queremos la informacin por meses. Y para sacar el mes de
una fecha utilizamos la funcin Datepart() -eso deberamos saberlo de VB, pero si no lo
sabemos lo aprendemos aqu... sin problemas-. Y la funcin Datepart(), para que nos devuelva
el mes, tiene la siguiente sintaxis: Datepart('m',<campo con la fecha>).
Si seguimos la estructura indicada en el comienzo de este apartado escribiramos pues:
PIVOT Datepart('m',TVentas.FechVta)
A que no es tan difcil? (Espero que respondis con un S unnime...!).
Nuestro cdigo quedara as:
20
Vistame en http://siliconproject.com.ar/neckkito/
AUTOCOMBINACIN
Supongamos que queremos obtener una informacin que pase por combinar elementos que
tenemos dentro de la propia tabla y que, de alguna manera, dependen los unos de los otros.
Para realizar la autocombinacion vamos a servirnos de la misma tabla pero, gracias a un alias,
vamos a tratarlas cmo si fueran dos tablas distintas.
Por ejemplo, vamos a ver una consulta que nos devolver el empleado con su cargo junto con
el nombre del empleado del que depende, tambin con su puesto.
A la tabla de empleados (que saldr de TTrabLaboral) le pondremos el alias Empl, y a la tabla
de superiores (que tambin saldr de TTrabLaboral) le pondremos el alias Sup.
Nuestro cdigo quedara as:
Fijmonos cmo:
Hemos utilizado dos alias sobre la misma tabla, de manera que parece que
manejamos dos tablas diferentes (TTrabLaboral AS Empl, TTrabLaboral AS Sup)
Hemos seleccionado los campos que nos interesaban seleccionndolos como si fueran
campos de esas dos tablas diferentes (SELECT Empl.IdTrab, Empl.Cargo,
Sup.IdTrab, Sup.Cargo)
Para obtener la relacin hemos utilizado datos que tenemos en la misma tabla, y que
provienen
de
los
campos
[IdTrab]
y
[DependeDe]
(WHERE
Empl.DependeDe=Sup.IdTrab)
21
Vistame en http://siliconproject.com.ar/neckkito/
SELF JOIN
Para conseguir un producto cartesiano de una tabla consigo misma podemos utilizar una
estructura SELF JOIN. Un producto cartesiano establece una relacin de cada uno de los
elementos de la tabla por s mismo y por el resto de elementos de la tabla.
Para poder poner un ejemplo de SELF JOIN vamos a tener que crearnos una nueva tabla, que
llamaremos TRepresentantes. Esta tabla nos recoger los clientes y los responsables dentro del
departamento de ventas que se encargan de ellos (tranquilos: haremos el ejemplo con pocos
registros).
La estructura de la tabla ser la siguiente:
Teniendo en cuenta que en el campo [IdCliRepr] el tipo de datos viene dado por el asistente
para bsquedas, donde hemos seleccionado la tabla TClientes y como campo visible [NomCli[,
y que para el campo [IdTrabRepr] el tipo de datos se ha creado utilizando el asistente para
bsquedas, donde hemos seleccionado de la tabla TTrabPersonal y como campos visibles
[ApellTrab] y [NomTrabl] (por este orden).
Rellenamos la tabla con unos pocos datos. Yo la he rellenado as:
Es decir, que nuestra empresa siempre asigna dos representantes para cada cliente, para
poderse cubrir las vacaciones (porque en nuestra empresa S damos vacaciones )
Vamos a realizar la misma operacin que en el apartado anterior; es decir, vamos a dividir
nuestra tabla en dos utilizando un alias.
El cdigo para una combinacin SELF JOIN sobre esta tabla podra ser:
22
Vistame en http://siliconproject.com.ar/neckkito/
Private Sub cmdSelfJoin_Click()
Dim miSql As String, nomQuery As String
nomQuery = "CSelfJoin"
Call eliminaConsulta(nomQuery)
miSql
&"
&"
&"
Y obtenemos:
Como podemos ver, a una hipottica tabla la hemos llamado Uno, y a la otra Dos, y las
hemos relacionado a travs de (Uno.IdCliRepr = Dos.IdCliRepr). Si nos hubiramos
quedado aqu (sin aadir el AND) tendramos una SELF JOIN en toda regla. Es decir, que nos
saldra el producto cartesiano puro y duro. Para los incrdulos...
En nuestro ejemplo no tena mucho sentido la informacin Filemn-Filemn, o SecretoSecreto, o Secreto-Zape/Zape-Secreto. Para eliminar estos duplicados hemos aadido el
AND, que los elimina.
23
Vistame en http://siliconproject.com.ar/neckkito/
CLUSULA HAVING
La clusula HAVING tiene un comportamiento muy parecido
al WHERE, pero trabaja con grupos de registros (WHERE no
puede trabajar con grupos de registros). Hablando para que
nos entendamos, WHERE nos muestra un conjunto de filas
que cumplen un criterio como campos individuales, y
HAVING nos muestra grupos de registros que cumplen un
criterio como grupo de registros.
Y, como hablamos de grupos, no podemos olvidarnos de utilizar el GROUP BY con HAVING.
Vamos a desgranar un ejemplo con lo anterior.
Imaginemos que queremos obtener una consulta de los totales de ventas, pero que nos
muestre slo aquellos totales que sean mayores que un lmite que hemos establecido como
objetivo de ventas, que ser de 8.500 euros.
Debemos crear pues una primera agrupacin, que ser la que nos calcular la suma de las
ventas agrupadas por cliente.
SELECT TVentas.IdCliVta, Sum(TVentas.ImpVta) AS VentasTotales FROM TVentas
GROUP BY TVentas.IdCliVta
Con esta primera agrupacin ya tenemos los totales de todas las ventas, pero ahora queremos
realizar un filtrado sobre ese grupo, de manera que slo nos muestre aquellos registros (que,
recordemos, estn formados por la agrupacin por suma de registros individuales) que
cumplen nuestra condicin.
Para ello deberamos agregar dicho filtro sobre grupo, es decir, HAVING
HAVING Sum(TVentas.ImpVta)>=8500
Si combinamos todo lo anterior en una SQL obtendramos:
Como curiosidad, para rematar este apartado, os dir que, segn Microsoft, una clusula
HAVING puede contener hasta 40 expresiones vinculadas por operadores lgicos, como AND y
OR.
24
Vistame en http://siliconproject.com.ar/neckkito/
25
Vistame en http://siliconproject.com.ar/neckkito/