Indice
1.
Introducción
2. ¿Qué es
sql?
3. La sentencia select y la
cláusula from
4. Programación SQL desde el
control data
5. Eliminación Dinámica De
Registros
6. Contar Registros
7. Grupos De
Registros
8. Combinación De
Datos
Visual Basic es un lenguaje de
programación de propósito general, con una gran
potencia en toda
su estructura. Su
implementación en el sistema operativo
Windows y sus
herramientas
visuales, han hecho de este lenguaje un
líder
indiscutible en lo que a desarrollo de
aplicaciones se refiere. Con la versión 3.0. se
implementó la gestión
de bases de datos a
muy alto nivel, pudiendo gestionar bases de datos de tipo
Access, Paradox,
dBASE, FoxPro,
etc.
Este paso de gigante ha hecho de Visual Basic uno
de los lenguajes favoritos por los desarrolladores de
aplicaciones de bases de datos,
en especial el hecho de que Visual Basic
implemente el lenguaje
SQL, uno de
los más potentes y sencillos lenguajes de bases de
datos.
SQL (Structured Query Language ó Lenguaje
Estructurado de Consulta), es un lenguaje bastante sencillo,
principalmente orientado a bases de datos y, sobre todo, al
manejo de consultas. Visual Basic
incorpora esta extensión junto a nuestras bases de datos,
obteniendo potentes resultados. De hecho, las consultas que se
realizan en Access,
están desarrolladas o basadas en este lenguaje, por lo que
su implementación en Visual Basic no
es complicada.
El objetivo
principal de SQL es la realización de consultas y
cálculos con los datos de una o varias tablas.
Consejos Para Escribir Mandatos En SQL
He aquí una serie de consejos (a veces normas), que hay
que tener en cuenta a la hora de escribir mandatos SQL en
nuestras aplicaciones en Visual Basic:
1. Un mandato en SQL se expresa en una cadena de caracteres o
String.
2. Dicho mandato se puede escribir en la propiedad
RecordSource de un control Data
(más adelante, podremos prescindir del control Data para
realizar nuestras consultas), con el fin de crear una consulta en
la interfaz.
3. Los nombres de los campos especificados (y de las tablas), que
contengan más de una palabra, han de encerrarse entre
corchetes ([nombre]). Como norma general, se suelen escribir
siempre entre corchetes.
4. Para especificar un determinado campo de una determinada
tabla, se ha de escribir primero el nombre de la tabla, un punto
y, a continuación, el nombre del campo
(nombre_tabla.nombre_campo).
5. Al especificar una expresión de búsqueda, si
ésta se refiere a una expresión de caracteres,
éstos han de encerrarse entre comillas simples
('expresión_a_buscar').
6. Para especificar una fecha en una búsqueda, ésta
debe encerrarse entre signos numeral
(#fecha#) en Access, Dbase X,
etc., y entre comillas simples ('fecha') para bases Sql Server,
Informix, etc.
7. Si se utiliza la propiedad
RecordSource del control Data, para crear nuestras consultas en
SQL, tras introducir el mandato SQL (siempre como una
expresión de cadena) es necesario refrescar el control
Data (control_data.Refresh).
Mandato Sql Estándar
El lenguaje
SQL está compuesto por una serie de sentencias y de
cláusulas muy reducidas en número, pero muy
potentes en efectividad. De entre todas las palabras, existen
cuatro que son las más utilizadas, estando compuestas por
una sentencia y por tres cláusulas:
SELECT lista_campos FROM lista_tablas [WHERE criterios [ORDER BY
lista_campos]]
3. La sentencia select y
la cláusula from
La sentencia SELECT "selecciona" los campos que
conformarán la consulta, es decir, que establece los
campos que se visualizarán o compondrán la
consulta. El parámetro 'lista_campo' está compuesto
por uno o más nombres de campos, separados por comas,
pudiéndose especificar también el nombre de la
tabla a la cual pertenecen, seguido de un punto y del nombre del
campo correspondiente. Si el nombre del campo o de la tabla
está compuesto de más de una palabra, este nombre
ha de escribirse entre corchetes ([nombre]). Si se desea
seleccionar todos los campos de una tabla, se puede utilizar el
asterisco (*) para indicarlo.
Una sentencia SELECT no puede escribirse sin la
cláusula FROM. Una cláusula es una extensión
de un mandato que complementa a una sentencia o
instrucción, pudiendo complementar también a otras
sentencias. Es, por decirlo así, un accesorio
imprescindible en una determinada máquina, que puede
también acoplarse a otras máquinas.
En este caso, la cláusula FROM permite indicar en
qué tablas o en qué consultas (queries) se
encuentran los campos especificados en la sentencias SELECT.
Estas tablas o consultas se separan por medio de comas (,), y, si
sus nombres están compuestos por más de una
palabra, éstos se escriben entre corchetes
([nombre]).
He aquí algunos ejemplos de mandatos SQL en la
estructura
SELECT…FROM…:
SELECT nombre,apellidos FROM clientes;
Selecciona los campos 'nombre' y 'apellidos' de la tabla
'clientes'.
SELECT clientes.nombre, producto FROM
clientes, productos;
Selecciona el campo 'nombre' de la tabla 'clientes', y el campo
'producto' de
la tabla productos.
Hay que tener en cuenta que si dos tablas poseen el mismo nombre
de campo (un 'nombre' de cliente y un
'nombre' de producto, hay que especificar también la tabla
a la cual pertenece dicho campo, ya, que de lo contrario,
seleccionaría ambos nombres).
SELECT pedidos.* FROM pedidos;
Selecciona todos los campos de la tabla 'pedidos'.
SELECT * FROM pedidos;
Selecciona todos los campos de la tabla 'pedidos'.
SELECT nombre, apellidos, telefono FROM clientes;
Selecciona los campos 'nombre', 'apellidos' y 'telefono' de la
tabla 'clientes'. De esta manera obtenemos una agenda
telefónica de nuestros clientes.
SELECT [codigo postal]
FROM [tabla morosos];
Selecciona el campo 'codigo postal'
de la tabla 'tabla morosos'.
Claúsula Where
La claúsula WHERE es opcional, y permite
seleccionar qué registros
aparecerán en la consulta (si no se especifica
aparecerán todos los registros). Para
indicar este conjunto de registros se hace uso de criterios o
condiciones, que no es más que una comparación del
contenido de un campo con un determinado valor (este
valor puede
ser constante (valor predeterminado), el contenido de un campo,
una variable, un control, etc.).
He aquí algunos ejemplos que ilustran el uso de
esta cláusula:
SELECT * FROM clientes WHERE nombre='ALFREDO';
Selecciona todos los campos de la tabla 'clientes', pero los
registros de todos aquellos clientes que se llamen 'ALFREDO'.
SELECT * FROM abonados WHERE provincia='MADRID' OR
provincia='VALENCIA OR provincia='BARCELONA';
Selecciona todos los campos de la tabla 'abonados', pero los
registros de todos los abonados de las provincias de 'MADRID',
'VALENCIA' o 'BARCELONA'.
SELECT nombre, apellidos FROM abonados WHERE edad>=18;
Selecciona los campos 'nombre' y 'apellidos' de la tabla
abonados, escogiendo a aquellos abonados que sean mayor de edad
(a partir de 18 años).
SELECT * FROM abonados WHERE edad>=18 AND edad<=45;
Selecciona todos los abonados con edades comprendidas entre los
18 y los 45 años.
SELECT * FROM abonados WHERE edad BETWEEN 18 AND 45;
Selecciona todos los abonados con edades comprendidas entre los
18 y los 45 años.
SELECT * FROM diario WHERE fecha=#7/1/97#;
Selecciona los apuntes de 'diario' realizados el 1 de Julio de
1.997 (la fecha ha de indicarse en inglés
(mes/día/año)).
SELECT * FROM diario WHERE fecha<=#12/31/96#;
Selecciona los apuntes de 'diario' realizados antes del 1 de
Enero de 1.997.
SELECT * FROM diario WHERE fecha BETWEEN #7/1/97# AND
#7/31/97#;
Selecciona los apuntes de 'diario' realizados en Julio de
1.997.
SELECT * FROM clientes WHERE nombre LIKE 'AL*';
Selecciona los clientes cuyo nombre comience con los caracteres
'AL'.
SELECT * FROM clientes WHERE apellidos LIKE '*EZ';
Selecciona los clientes cuyos apellidos terminen con los
caracteres 'EZ'.
SELECT * FROM clientes WHERE apellidos LIKE '*ZAMO*'
Selecciona los clientes cuyos apellidos contengan, en cualquier
posición, los caracteres 'ZAMO'.
SELECT * FROM clientes WHERE provincia IN ('MADRID',
'BARCELONA',
'VALENCIA','TOLEDO', 'AVILA');
Selecciona todos los clientes de las provincias de MADRID,
BARCELONA, VALENCIA,
TOLEDO o AVILA.
Cláusula Order By
La cláusula ORDER BY suele escribirse al final de
un mandato en SQL. Dicha cláusula establece un criterio de
ordenación de los datos de la consulta, por los campos que
se especifican en dicha cláusula. La potencia de
ordenación de dicha cláusula radica en la
especificación de los campos por los que se ordena, ya que
el programador puede indicar cuál será el primer
criterio de ordenación, el segundo, etc., así como
el tipo de ordenación por ese criterio: ascendiente o
descendiente.
(…) ORDER BY campo1 [ASC/DESC][,campo2 [ASC/DESC]…]
La palabra reservada ASC es opcional e indica que el orden del
campo será de tipo ascendiente (0-9 A-Z), mientras que, si
se especifica la palabra reservada DESC, se indica que el orden
del campo es descendiente (9-0 Z-A). Si no se especifica ninguna
de estas palabras reservadas, la cláusula ORDER BY toma,
por defecto, el tipo ascendiente [ASC].
He aquí algunos ejemplos:
SELECT nombre, apellidos, telefono FROM clientes ORDER BY
apellidos, nombre;
Crea una agenda telefónica de 'clientes' ordenada por
'apellidos' y 'nombre'.
SELECT * FROM pedidos ORDER BY fecha DESC;
Relación de 'pedidos' ordenados desde el más
antiguo hasta el más moderno.
SELECT * FROM abonados ORDER BY apellidos, nombre,
fecha_nacimiento DESC;
Relación de 'abonados' por 'apellidos' y 'nombre'
ascendiente, y por 'fecha_nacimiento' en orden descendiente (del
más viejo al más joven).
4. Programación SQL desde el control
data
Gracias al control 'Data' podremos hacer nuestros
primeros pinitos en SQL. Lo primero que hay que tener en cuenta
es que la consulta realizada en SQL posea los mismos campos que
la interfaz diseñada, y que los controles encargados de
mostrar o modificar la base de datos,
estén perfectamente vinculados al control Data. Por
ejemplo: realizamos una ficha de 'clientes', por lo que
diseñamos una interfaz con diversas Text Box vinculadas a
un control Data que contendrá los datos. Estas Text Box se
vinculan gracias a las propiedades 'DataSource' y 'DataField'. La
propiedad 'DataSource' corresponde a la fuente de los datos, en
este caso, el nombre del control 'Data'. En la propiedad
'DataField' se especifica el nombre del campo a tratar por cada
Text Box ('nombre', 'direccion', 'nif', 'telefono', etc.). Por
otro lado, en la propiedad 'DatabaseName' del control 'Data', se
ha de especificar la ruta completa de la base de datos
(fichero .MDB), y la propiedad 'RecordSource' se reservará
para indicar, en una cadena o String, el mandato en SQL
correspondiente cuando sea necesario.
Siguiendo con este ejemplo, esta ficha se
reservará para consultas determinadas, y la Form
será mostrada desde una Form anterior, desde la que se
establece las condiciones de la consulta ('que sean de Madrid',
'que hayan nacido antes de 1960', 'que habiten en
Peñaranda de Bracamonte', etc.). Se podría crear
una variable de tipo String en un módulo, e insertar el
mandato en SQL correspondiente antes de llamar a la ficha. Al
llamar a la ficha, la Form correspondiente tendrá un
evento Load, donde se insertará un código
parecido a éste:
control_data.RecordSource = variable_SQL
control_data.Refresh
Obviamente, dependiendo del caso, la programación se hará diferente. Pero
la norma común es crear una interfaz en concreto, con
unos campos concretos y, cuando sea necesario, establecer como
valor de la propiedad 'RecordSource' el mandato en SQL, y
refrescar el control Data correspondiente. De esta manera, el
control Data contendrá el resultado de la
consulta.
5. Eliminación
Dinámica De Registros
¿Quién no ha sentido la necesidad de
eliminar de un golpe un grupo de
registros en común, en lugar de hacerlo uno por uno?. Esta
operación puede ser mucho más habitual de lo que
parece en un principio y, por ello, el lenguaje SQL nos
permitirá eliminar registros que cumplan las condiciones o
criterios que nosotros le indiquemos a través de la
sentencia DELETE, cuya sintaxis es la siguiente:
DELETE FROM tablas WHERE criterios
Donde el parámetro 'tablas' indica el nombre de las tablas
de las cuales se desea eliminar los registros, y, el
parámetro 'criterios', representa las comparaciones o
criterios que deben cumplir los registros a eliminar, respetando
a aquellos registros que no los cumplan. Si – por ejemplo –
quisiéramos eliminar todos los pedidos realizados por el
cliente cuyo
código
sea 4 en el día de hoy, utilizaríamos la siguiente
sentencia:
DELETE FROM pedidos WHERE [codigo cliente]=4 AND
fecha=Now();
Aritmética Con Sql
¿Quién no ha echado en falta el saber el total de
ingresos o de
gastos de esta
fecha a esta otra?.
¿Quién no ha deseado saber la media de ventas de los
comerciales en este mes?. ¡Tranquilos!: el lenguaje SQL nos
permitirá resolver estas y otras cuestiones de forma muy
sencilla, ya que posee una serie de funciones de
carácter aritmético:
Sumas O Totales
Para sumar las cantidades numéticas contenidas en un
determinado campo, hemos de utilizar la función
SUM, cuya sintaxis es la siguiente:
SUM(expresión)
Donde 'expresión' puede representar un campo o una
operación con algún campo.
La función
SUM retorna el resultado de la suma de la expresión
indicada en todos los registros que son afectados por la
consulta. Veamos algunos ejemplos:
SELECT SUM(unidades) FROM pedidos;
Retorna el total de unidades pedidas (la suma de todos los valores
almacenados en el campo 'unidades' de la tabla 'pedidos'). Este
resultado se toma como un nuevo campo en el RecordSet.
SELECT SUM(ingresos-gastos) AS saldo
FROM diario;
Retorna el saldo final de una tabla llamada 'diario'. Este
resultado se toma como un nuevo campo en el RecordSet y se le
llama 'saldo'.
SELECT SUM(unidades) AS total FROM pedidos WHERE fecha=Now();
Retorna el total de unidades pedidas hoy. Este resultado se toma
como un nuevo campo en el RecordSet y se le llama
'total'.
Promedios O Medias Aritméticas
Para averiguar el promedio de unas cantidades utilizaremos la
función AVG, cuya sintaxis es la siguiente:
AVG(expresión)
La función AVG retorna el promedio o media
aritmética de la expresión especificada, en todos
los registros afectados por la consulta. Esto es lo mismo que
realizar una suma (SUM) y, después, dividir el resultado
entre el número de registros implicados.
He aquí algunos ejemplos:
SELECT AVG(unidades) FROM PEDIDOS;
Retorna el promedio de unidades pedidas (la media de todos los
valores
almacenados en el campo 'unidades' de la tabla 'pedidos'). Este
resultado se toma como un nuevo campo en el RecordSet.
SELECT AVG(ingresos-gastos) AS saldo_medio FROM diario;
Retorna el saldo medio de una tabla llamada 'diario'. Este
resultado se toma como un nuevo campo en el RecordSet y se le
llama 'saldo_medio'.
SELECT AVG(unidades) AS media FROM pedidos WHERE fecha=Now();
Retorna el promedio de unidades pedidas hoy. Este resultado se
toma como un nuevo campo en el RecordSet y se le llama
'media'.
Valores Mínimos Y Máximos
También es posible conocer el valor mínimo o
máximo de un campo, mediante las funciones MIN y
MAX, cuyas sintaxis son las siguientes:
MIN(expresión)
MAX(expresión)
He aquí algunos ejemplos:
SELECT MIN(unidades) AS minimo FROM pedidos;
Retorna el pedido más pequeño y lo refleja en el
campo 'minimo'.
SELECT MAX(unidades) AS maximo FROM pedidos WHERE
fecha=Now();
Retorna el pedido más grande de hoy y lo refleja en el
campo 'maximo'.
SELECT MAX(gastos) AS maximo FROM diario;
Retorna el gasto más costoso reflejado en el diario
contable, y lo representa en el campo 'maximo'.
Otra operación muy común es realizar un
recuento de registros. Aunque a primera vista pueda parecer poco
práctico, la realidad es bien distinta. ¿Q
quién no le gustaría conocer cuántos pedidos
se han realizado hoy?. ¿O comprobar cuántos pagos
se han realizado por una determinada cantidad?. ¿O saber
cuántos clientes cumplen hoy años, se jubilan, son
menores o mayores de edad, tienen alguna deuda, viven en esta
ciudad o en tal otra, tienen teléfono móvil, están casados
o solteros, etc.?. Para conocer cuántos registros hay
utilizaremos la función COUNT, cuya sintaxis es la
siguiente:
COUNT(expresión)
La función COUNT retorna el número de registros
indicados en la expresión.
He aquí algunos ejemplos:
SELECT COUNT(*) AS num_pedidos FROM pedidos WHERE
fecha=Now();
Retorna el número de pedidos realizados hoy. Este
resultado se toma como un nuevo campo en el RecordSet y se le
llama 'num_pedidos'.
SELECT COUNT(*) AS casados FROM clientes WHERE casado=True;
Retorna el número de clientes casados. Este resultado se
toma como un nuevo campo y se le llama 'casados'.
SELECT COUNT(*) AS num_pagos FROM diario WHERE gastos=25594;
Retorna el número de pagos por un importe equivalente a
25594. Este resultado se toma como un nuevo campo en el
RecordSet, y se le llama 'num_pagos'.
SELECT SUM(unidades) AS total, AVG(unidades) AS media, COUNT(*)
AS registros, MAX(unidades) AS maximo, MIN(unidades) AS minimo
FROM pedidos WHERE fecha BETWEEN #1/1/97# AND #6/30/97#;
Retorna el total, la media, el máximo y el mínimo
de unidades pedidas, y el número de pedidos realizados,
durante el primer semestre de 1.997.
Omisión De Registros Duplicados
En una consulta podría ser útil omitir registros
que estén duplicados. Por ejemplo, en nuestros pedidos hay
duplicación, puesto que un cliente realiza varios pedidos
en el mismo día. Quizá necesitemos una historia para conocer los
días y los clientes que realizaron algún pedido,
pero no necesitaremos toda la lista, si no que nos diga,
únicamente, mediante una línea, qué cliente
realizó algún pedido y en qué día.
Para ello, utilizaremos el predicado DISTINCT, cuya sintaxis es
la siguiente:
SELECT DISTINCT lista_campos …
El predicado DISTINCT omite aquellos registros duplicados en los
campos especificados. En el problema expuesto, utilizaremos la
siguiente sentencia:
SELECT DISTINCT [codigo cliente],fecha FROM pedidos;
Si deseamos que la consulta sea más completa y nos
visualice también el nombre y los apellidos
correspondientes del cliente en cuestión (estos datos
están en la tabla 'clientes' y no en 'pedidos'),
escribiríamos este mandato:
SELECT DISTINCT pedidos.fecha, pedidos.[codigo cliente],
clientes.nombre, clientes.apellidos
FROM pedidos, clientes WHERE clientes.[codigo cliente] =
pedidos.[codigo cliente];
Reemplazar Datos
Imaginemos por un momento que el precio de los
productos ha subido un 10%, y que tenemos que actualizar nuestra
tabla de productos con el nuevo importe. La solución
más primitiva sería acceder a la tabla y, el
precio de cada
producto multiplicarlo por 1.1 y reemplazarlo a mano. Con diez
productos, la inversión de tiempo
podría llegar al cuarto de hora, y no estaremos exentos de
fallos al tipear el importe o al realizar el cálculo en
la calculadora. Si la tabla de productos superase la cantidad de
100 productos (algo muy probable y fácil de cumplir), la
cosa ya no es una pequeña molestia y un poco de tiempo
perdido.
El lenguaje SQL nos permite solucionar este problema en
cuestión de pocos segundos, ya que posee una sentencia
llamada Update, que se ocupa de los cálculos y reemplazos.
Su sintaxis es la siguiente:
UPDATE lista_tablas SET campo=nuevo_valor [,campo=nuevo_valor]
[WHERE…]
Donde lista_tablas representa el nombre de las tablas donde se
realizarán las sustituciones o reemplazos. El
parámetro campo indica el campo que se va a modificar, y
el parámetro nuevo_valor representa una expresión
(constante, valor directo, un cálculo,
etc.) cuyo resultado o valor será el nuevo valor del
campo.
En el problema expuesto anteriormente
escribiríamos la siguiente sentencia:
UPDATE productos SET pvc=pvc*1.1;
Si este incremento de precio de costo debe
afectar al precio de venta al
público un 30% de beneficio, podríamos escribir la
siguiente línea para ahorrar trabajo y tiempo:
UPDATE productos SET pvc=pvc*1.1, pvp=pvp*1.3;
La sentencia UPDATE es muy versátil y potente, por lo que
podemos realizar reemplazos condicionantes, ya que permite la
cláusula WHERE. De ello se deduce que – por ejemplo -, si
se desea bajar un 10% el importe del seguro a aquellos
asegurados que cumplan más de dos años de carnet de
conducir, y que tengan más de 22 años de edad,
tendríamos que escribir la siguiente sentencia:
UPDATE asegurados SET importe=importe/1.1 WHERE edad>22 AND
YEAR(Now)-YEAR(expedicion)>2;
Pero ahí no queda la cosa, porque es posible utilizar
varias tablas y sustituir el valor de un campo de una de las
tablas con el valor del campo de otra tabla, o bien reemplazar el
valor de unos campos de alguna tabla si el valor de los campos de
otras tablas cumple una serie de requisitos. Estos casos no son
tan frecuentes, pero en el caso de haberlos se agradecerá
un buen planteamiento en el diseño
inicial de la base de datos.
A veces, puede ser necesario mostrar un resumen de los
datos que tenemos, especificando el total – por ejemplo -, de los
ingresos y de los gastos de cada día, en lugar de
visualizar todos los ingresos y gastos realizados al detalle.
Para llevar a cabo esta tarea hemos de tener en cuenta, en primer
lugar, bajo qué campo se van a agrupar los datos (en lo
expuesto, sería el campo fecha), y, a continuación,
realizar la consulta mediante la cláusula GROUP BY, cuya
sintaxis es la siguiente:
SELECT … FROM … [WHERE …] GROUP BY lista_campos
Básicamente, la cláusula GROUP BY agrupa o combina
registros con idéntico valor en los campos especificados,
en un único registro. Esto
significa que en un sólo registro se
mostrará la información común a muchos
registros, como si dijésemos, al terminar las cuentas: "hoy se
ha ingresado tanto y se ha gastado tanto, con lo que hay un
beneficio de tanto", sin necesidad de especificar cada movimiento
(cada ingreso, cada cobro, cada pago, cada factura, cada
transferencia bancaria, etc.).
Imaginemos que queremos hacer un resumen de nuestros
pedidos, y queremos saber cuántos pedidos y unidades han
realizado cada uno de nuestros clientes. Para ello, se
escribiría una sentencia como ésta:
SELECT codigo_cliente, count(codigo_cliente) AS num_pedidos,
SUM(unidades) AS cantidad FROM pedidos GROUP BY
codigo_cliente;
Para saber cuántos pedidos se realizaron cada
día, escribiríamos esta línea:
SELECT fecha, count(fecha) AS num_pedidos FROM pedidos GROUP BY
fecha;
Para conocer cuántas unidades se pidieron cada día,
tipearíamos esta sentencia:
SELECT fecha, SUM(unidades) AS cantidad FROM pedidos GROUP BY
fecha;
En la siguiente sentencia se muestra para cada
cliente aquellos días en que se realizó un pedido,
resumiéndose el número de pedidos realizados
así como el total de unidades pedidas:
SELECT fecha, codigo_cliente, COUNT(codigo_cliente) AS
num_pedidos, SUM(unidades) AS cantidad FROM pedidos GROUP BY
fecha, codigo_cliente HAVING fecha<#1/6/97#;
Como se puede apreciar, se ha especificado una condición a
través de la cláusula HAVING, que indica los
criterios o condiciones a cumplir por los registros a visualizar
en un agrupamiento. En esta ocasión, la condición
era de aquellos pedidos realizados antes del seis de Enero de
1.997.
Para conocer una estadítica de pedidos diaria,
utilizaremos la siguiente sentencia:
SELECT fecha, COUNT(fecha) AS pedidos, SUM(unidades) AS subtotal,
MIN(unidades) AS minimo, MAX(unidades) AS maximo, AVG(unidades)
AS promedio FROM pedidos GROUP BY fecha;
Un resultado de ejemplo sería el siguiente:
FECHA PEDIDOS UNIDADES MINIMO MAXIMO PROMEDIO
—– ——- ——– —— —— ——–
2/01/97 9 1599 2 1500 177,6
3/01/97 5 113 1 100 22,6
4/01/97 3 33 3 25 11,0
6/01/97 6 90 5 50 15,0
7/01/97 1 1 1 1 1,0
8. Combinación De Datos
Las consultas realizadas hasta ahora requerían de
una dosis de habilidad para conseguir crear un conjunto de datos
que tuviese información combinada de dos tablas. Pero,
podemos combinar datos de una manera mucho más sencilla y
eficaz: mediante las operaciones JOIN,
las cuales permiten combinar datos de dos tablas. La
operación JOIN más común es INNER JOIN, cuya
sintaxis es:
tabla1 INNER JOIN tabla2 ON
tabla1.campo_común=tabla2.campo_común
Donde tabla1 y tabla2 representan el nombre de las tablas a
combinar. Ambas tablas han de tener un campo común o igual
para poder realizar
correctamente la combinación de los datos. Pero veamos un
ejemplo para entenderlo mejor:
SELECT * FROM pedidos INNER JOIN clientes ON
pedidos.codigo_cliente =clientes.codigo_cliente;
El resultado será un conjunto de registros con los datos
de las dos tablas. Este conjunto poseerá el nombre de
todos los campos de la tabla pedidos y de todos los campos de la
tabla clientes. En cada registro aparecerán los datos
relacionados, es decir, que en un pedido aparecerán los
datos del mismo y los datos personales del cliente que
realizó el pedido.
La operación INNER JOIN combina los datos de las dos
tablas siempre que haya valores
coincidentes en los campos comunes o enlazados.
Existen también otras dos formas de combinar:
LEFT JOIN y RIGHT JOIN. Ambas tienen la misma sintaxis que INNER
JOIN, pero estas operaciones
incluyen todos los registros de una tabla y aquellos registros de
la otra en que los campos comunes sean iguales. En la
operación LEFT JOIN, incluye todos los registros de la
primera tabla (parámetro tabla1) y aquellos registros de
la segunda tabla (parámetro tabla2) en que los campos
comunes sean iguales. En la operación RIGHT JOIN ocurre lo
contrario: incluye todos los registros de la segunda tabla y
aquellos registros de la primera tabla en que los campos comunes
sean iguales.
Aunque la diferencia entre las tres operaciones parezca
inexistente, en realidad sí existe. La operación
INNER JOIN realiza una combinación con todos aquellos
registros de las dos tablas en que el campo común de ambas
tenga el mismo valor, mientras que las operaciones LEFT JOIN y
RIGHT JOIN realizan la combinación de todos los registros
de la tabla que combinan (ya sea la primera para LEFT JOIN o la
segunda para RIGHT JOIN), aunque en la otra tabla, en el campo
común no haya coincidencia. La prueba se ve
rápidamente si se introduce un código de cliente en
el campo campo_cliente de la tabla pedidos que no exista:
SELECT * FROM pedidos INNER JOIN clientes ON
pedidos.codigo_cliente =clientes.codigo_cliente;
El registro que contiene el pedido del cliente que no existe no
aparece, puesto que no hay coincidencia. Si escribimos:
SELECT * FROM pedidos LEFT JOIN clientes ON
pedidos.codigo_cliente =clientes.codigo_cliente;
Observaremos que aparecen todos los registros de la tabla
pedidos, incluido aquel donde indicamos que el pedido fue
solicitado por el cliente inexistente, pero en los campos
relacionados (campos de la tabla clientes) no habrá
ningún dato relacionado o combinado. Si ahora escribimos
lo siguiente:
SELECT * FROM pedidos LEFT JOIN clientes ON
pedidos.codigo_cliente =clientes.codigo_cliente; obtendremos el
mismo resultado que con la operación INNER JOIN, puesto
que se visualizan todos aquellos registros que existen en
clientes y aquellos que coincidan con el campo clave en la tabla
pedidos. Como el código inexistente no existe en la tabla
clientes, este registro no aparece. Para comprobar el efecto
aún mejor, modificar el código inexistente en el
registro de la tabla pedidos por uno que sí exista. Tras
ello, volver a introducir las sentencias SQL para comprobar la
diferencia.
Lo más normal es utilizar la operación
INNER JOIN para omitir aquellos registros no coincidentes, aunque
las operaciones LEFT JOIN y RIGHT JOIN nos pueden servir para
descubrir entradas erróneas en códigos.
Veamos algunos ejemplos más:
SELECT fecha, codigo_producto, unidades, apellidos, nombre FROM
pedidos INNER JOIN clientes ON pedidos.codigo_cliente =
clientes.codigo_cliente WHERE fecha<#1/6/97#;
Combina pedidos y clientes, visualizando aquellos pedidos
realizados antes del 6 de Enero de 1997 por los campos fecha,
codigo_producto, unidades, apellidos y nombre.
SELECT fecha, unidades, productos.* FROM pedidos INNER JOIN
productos ON pedidos.codigo_producto =
productos.codigo_producto;
Combina pedidos y productos, visualizando los pedidos por los
campos fecha y unidades, y por todos los campos de la tabla
productos.
SELECT fecha, unidades, productos.* FROM pedidos INNER JOIN
productos ON pedidos.codigo_producto = productos.codigo_producto
ORDER BY fecha, producto;
El resultado será el mismo que con el anterior
ejemplo, salvo que la presentación de los registros se
realizará ordenada por la fecha y el nombre del
producto.
Autor:
Ing. Antonini Sergio