jueves, 1 de noviembre de 2018

ACCESS II: Vista Diseño de Login


ACCESS II: Código del Formulario Login

Option Compare Database
Option Explicit

' Variable privada que controla los intentos de login fallidos
Private bytErrLogin As Byte

'Procedure:  Comprueba_Intentos
' Purpose   : Comprueba los intentos de inicio de sesión fallidos y actúa
'             en consecuencia.
'-------------------------------------------------------------------------
'
Private Sub Comprueba_Intentos(bytErrLogin As Byte, _
                                intUsuario As Integer)

    If bytErrLogin = Get_ErrMaxLogin Then

        ' Mostramos el mensaje "Se ha superado el número máximo de intentos
        ' de inicio de sesión"
        MsgBox "Se ha superado el número máximo de intentos de " & _
                "inicio de sesión." & _
                vbCrLf & vbCrLf & _
                "Usuario : """ & Me.cbo_Usuario.Column(1) & """." & _
                vbCrLf & vbCrLf & _
                "El usuario ha sido bloqueado.", _
                vbExclamation, "Inicio de sesión"
           
        ' Bloqueamos al usuario
        Call Block_Usuario(intUsuario)
           
        ' Hacemos log del bloqueo del usuario
        Call Log_Sesion(intUsuario, "El usuario ha sido bloqueado.")
       
        With Me
       
            ' Actualizamos el combobox cbo_Usuario
            .cbo_Usuario.Requery
               
            ' Borramos la contraseña
            .txt_Contraseña = ""
               
            ' Ocultamos la etiqueta
            .lbl_Mensaje.Visible = False
     
        End With
     
    End If
           
End Sub

Private Sub cmd_Login_Click()
Dim intUsuario As Integer
Dim strContraseña As String

    intUsuario = Nz(Me.cbo_Usuario.Value, 0)
   
   
    ' Ocultamos la etiqueta
    If Me.lbl_Mensaje.Visible = True Then Me.lbl_Mensaje.Visible = False
   
    ' Comprobamos si se ha seleccionado usuario


    ' Comprobamos si se ha introducido contraseña


    ' Comprobamos el valor introducido para el usuario y su contraseña
 

        ' -------------------------------------------------------
        ' Aquí podemos insertar el código que queremos que se
        ' ejecute cuando iniciemos la sesión...
        ' -------------------------------------------------------
           
        ' Mostramos mensaje
        MsgBox "Sesión de usuario iniciada", _
                vbInformation, _
                "Inicio de Sesión"

        ' Hacemos log del inicio de sesión
        Log_Sesion intUsuario, "Inicio de sesión."

        ' Cerramos el formulario
        DoCmd.Close acForm, Me.Name
           
   
       
        ' Añadimos +1 a los intentos de login erróneos
1
       
        ' Centramos el foco en el textbox
       

        ' Mostramos mensaje en la etiqueta
        Call MensajeEtiqueta("La contraseña introducida es errónea.")
       
        ' Hacemos log del inicio de sesión fallido
        Call Log_Sesion(intUsuario, "Inicio de sesión erróneo.", strContraseña)

        ' Comprobamos los intentos de inicio de sesión
       
   
   
End Sub
Private Sub MensajeEtiqueta(strMensaje As String)

Dim lbl As Label

    Set lbl = Me.lbl_Mensaje
   
    If Nz(strMensaje, "") <> "" Then

        ' Mostramos mensaje
        With lbl
               
            ' Hacemos visible la etiqueta
            .Visible = True
            ' Mostramos el Mensaje de aviso
            .Caption = strMensaje
               
        End With
   
    End If
   
    ' Borramos el objeto
    Set lbl = Nothing
   
End Sub

 Private Sub Cmd_Salir_Click()
  ' Cerramos el Formulario
 DoCmd.Close acForm, Me.Name
   
    End Sub
Private Sub Form_Load()
    ' Establecemos el valor de la variable que controla los
    ' errores de login...
    bytErrLogin = 0

End Sub

ACCESS II: Práctica III SQL

REALIZA LA SIGUIENTE PRÁCTICA EN CONSULTA SQL.
a) Las instrucciones estan en texto negritas, el código está en  texto color rojo.
b) En Una B.D Nueva realiza las siguientes sentencias en código SQL, si tienes dudas, consulta la parte teórica de Access Avanzado, si persisten las molestias de no comprensión, sigue leyendo, hasta entender. YO QUIERO, YO PUEDO, Y SE QUE LO LOGRARÉ.


    1. Ejercicios SQL en Access
    2. SQL - Structured Query Language P á g i n a | 2 EJERCICIOS SQL Crear en Access la base de datos Empresa_1 y ejecutar las sentencias
SQL EMPLEADOS ID_EMPLEADO NOMBRE APELLIDOS F_NACIMIENTO SEXO CARGO SALARIO
1 Carlos Jiménez Clarín 1985/05/03 H Mozo 1500 2 Elena Rubio Cuestas 1978/09/25 M Secretaria 1300 3 José Calvo Sisman 1990/11/12 H Mozo 1400 4 Margarita Rodríguez Garcés 1992/05/16 M Secretaria 1325 SCRIPT:
 CREACIÓN TABLAS CREATE TABLE EMPLEADOS(id_empleado int primary Key NOT NULL, nombre char(50) NOT NULL, apellidos char(50) NOT NULL, f_nacimiento date NOT NULL, sexo char(1) NOT NULL, cargo char(50) NOT NULL, salario int NOT NULL );
 INSERCION DE DATOS TABLA EMPLEADO INSERT INTO EMPLEADOS (id_empleado, nombre, apellidos, f_nacimiento, sexo, cargo, salario) VALUES ('1','Carlos','Jiménez Clarín','1985/05/03','H','Mozo','1500');
 INSERT INTO EMPLEADOS (id_empleado, nombre, apellidos, f_nacimiento, sexo, cargo, salario) VALUES ('2','Elena','Rubio Cuestas','1978/09/25','M','Secretaria','1300');
 INSERT INTO EMPLEADOS (id_empleado, nombre, apellidos, f_nacimiento, sexo, cargo, salario) VALUES ('3','José','Calvo Sisman','1990/11/12','H','Mozo','1400');
 INSERT INTO EMPLEADOS (id_empleado, nombre, apellidos, f_nacimiento, sexo, cargo, salario) VALUES ('4','Margarita','Rodríguez Garcés','1992/05/16','M','Secretaria','1325');

 Ejemplo 1 ¿Qué empleados tienen un salario mayor a 1350? select NOMBRE , APELLIDOS from EMPLEADOS where SALARIO > 1350
 Ejemplo 2 ¿Realizar una consulta que devuelva el nombre, apellidos y la fecha de nacimiento de aquellos empleados que cobren más de 1350?
select NOMBRE , APELLIDOS , F_NACIMIENTO from EMPLEADOS where SALARIO > 1350
 Ejemplo 3 ¿Qué empleados tienen un sueldo comprendido entre 1350 y 1450?
select NOMBRE , APELLIDOS from EMPLEADOS where SALARIO > 1350 and SALARIO <= 1450

3. SQL - Structured Query Language P á g i n a | 3
 Ejemplo 4 ¿Qué empleados son hombres? select NOMBRE , APELLIDOS from EMPLEADOS where SEXO = 'H'
 Ejemplo 5 ¿Cuáles son los nombres de los empleados tienen el cargo de MOZO? select NOMBRE from EMPLEADOS where CARGO = 'MOZO'
 Ejemplo 6 ¿Cuál es el empleado de código 4? select APELLIDOS from EMPLEADOS where ID_EMPLEADO = 4

    4. SQL - Structured Query Language P á g i n a | 4 Crear en Access la siguiente bases de Datos y Ejecutar las sentencias SQL DEPARTAMENTO cod_dep nombre_dep localización 10 Desarrollo de Software El Coyolar 20 Análisis de Sistemas Guadalupe 30 Contabilidad Subtiava 40 Ventas San Felipe EMPLEADO cod_emp nombre edad oficio dir fecha_ing salario comisión cod_dep 1 Vargas Héctor 27 Vendedor León 12/05/1993 12000 40 2 Hernández Julio 27 Analista Chinandega 14/07/1982 13000 1500 20 3 Esquivel José 31 Director Juigalpa 05/06/1981 16700 1200 30 4 Delgado Carmen 37 Vendedor León 02/03/1983 13400 40 5 Castillo Luis 17 Vendedor Masaya 12/08/1982 16309 1000 40 6 Esquivel Alfonso 26 Presidente Nagarote 12/09/1981 15000 30 7 Pérez Luis 32 Empleado Managua 02/03/1980 16890 10 SCRIPT:
 CREACIÓN TABLAS
CREATE TABLE DEPARTAMENTO( cod_dep int primary Key NOT NULL, nombre_dep char(50) NOT NULL, localización char (50) NOT NULL );
CREATE TABLE EMPLEADO( cod_emp int primary Key NOT NULL, nombre char(50) NOT NULL, edad int NOT NULL, oficio char(50) NOT NULL, dir char(50) NOT NULL, fecha_ing char(50) NOT NULL, salario int NOT NULL, comisión int, cod_dep int NOT NULL );
 INSERCION DE DATOS TABLA DEPARTAMENTO
INSERT INTO DEPARTAMENTO (cod_dep, nombre_dep, localización) VALUES ('10','Desarrollo de Software','El Coyolar');
INSERT INTO DEPARTAMENTO (cod_dep, nombre_dep, localización) VALUES ('20','Análisis de Sistemas','Guadalupe');
INSERT INTO DEPARTAMENTO (cod_dep, nombre_dep, localización) VALUES ('30','Contabilidad','Subtiava');
INSERT INTO DEPARTAMENTO (cod_dep, nombre_dep, localización) VALUES ('40','Ventas','San Felipe');
 INSERCION DE DATOS TABLA EMPLEADO
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('1','Vargas Héctor','27','Vendedor','León','12/05/1993','12000',null,'40');
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('2','Hernández Julio','27',' Analista',' Chinandega','14/07/1982','13000','1500','20');
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('3','Esquivel José','31','Director','Juigalpa','05/06/1981','16700','1200','30');
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('4','Delgado Carmen','37','Vendedor','León','02/03/1983','13400',null,'40');
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('5','Castillo Luis','17','Vendedor','Masaya','12/08/1982','16309','1000','40');
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('6','Esquivel Alfonso','26','Presidente','Naragote','12/09/1981','15000',null,'30');
INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión, cod_dep) VALUES ('7','Pérez Luis','32','Empleado','Managua','02/03/1980','16890',null,'10');

    5. SQL - Structured Query Language P á g i n a | 5
 Ejemplo 7 Listar los nombres de los empleados cuyo nombre termine con la letra ‘o’. select nombre from EMPLEADO where nombre like '*o'
 Ejemplo 8 Seleccionar el nombre, el oficio y salario de los empleados que trabajan en León. select nombre, oficio, salario from EMPLEADO where dir='León'
 Ejemplo 9 Calcular el salario medio de todos los empleados. select avg(salario) from EMPLEADO
 Ejemplo 10 ¿Cuál es el máximo salario de los empleados del departamento número 10? select max(salario) from EMPLEADO where cod_dep = 10
 Ejemplo 11 ¿Cuántos empleados hay en el departamento número 10? select count(*) from EMPLEADO where cod_dep = 10
 Ejemplo 12 ¿Cuántos empleados hay en el departamento de VENTAS? select count(*) from EMPLEADO where cod_dep=40
 Ejemplo 13 ¿Cuántos empleados no tienen comisión? select count(*) from EMPLEADO where comisión is null
 Ejemplo 14 Se desea saber cuántos nombres de los empleados empiezan por la letra ‘A’. select count(*) from EMPLEADO where nombre like 'E*'
 Ejemplo 15 Para cada oficio obtener la suma de salarios. select oficio, sum(salario) from EMPLEADO group by oficio

    6. SQL - Structured Query Language P á g i n a | 6
 Ejemplo 16 Mostrar los datos de los empleados cuyo salario sea mayor que la media de todos los salarios. select * from EMPLEADO where salario>(select avg(salario) from EMPLEADO)
 Ejemplo 17 Seleccionar el nombre del empleado que tiene máximo salario. select nombre from EMPLEADO where salario=(select max(salario)from EMPLEADO)
 Ejemplo 18 Mostrar el nombre del empleado que tiene el salario más bajo. select nombre from EMPLEADO where salario=(select min(salario)from EMPLEADO)
 Ejemplo 19 Insertar en la tabla EMPLEADO un empleado con código 8, nombre ‘Cajas Carlos’ de 32 años, oficio Analista, vive en Matagalpa, fecha de ingreso en la empresa el 22-06-2001, su salario es de 15600, no tiene comisión y pertenece al departamento 20.
 INSERT INTO EMPLEADO (cod_emp, nombre, edad, oficio, dir, fecha_ing, salario, comisión,
cod_dep) VALUES ('8','Cajas Carlos','32','Empleado','Matagalpa','22/06/2001','15600',null,'20');
 Ejemplo 20 Insertar en la tabla DEPARTAMENTO un departamento cuyo número sea 50, de nombre ‘GENERAL’ y cuya localización sea ‘Laborio’.
 INSERT INTO DEPARTAMENTO (cod_dep, nombre_dep, localización) VALUES ('50','General','Laborio');
 Ejemplo 21 Insertar en la tabla DEPARTAMENTO un departamento cuyo número sea 60 y de nombre ‘PRUEBAS’ y cuya localización sea ‘Puerto Cayo’.
 INSERT INTO DEPARTAMENTO (cod_dep, nombre_dep, localización) VALUES ('60','Pruebas','Puerto Cayo');
 Ejemplo 22 Doblar el salario a todos los empleados del departamento 30. update EMPLEADO set salario = salario*2 where cod_dep=30
 Ejemplo 23 Cambiar todos los empleados del departamento número 30 al departamento número 20. update EMPLEADO set cod_dep = 20 where cod_dep = 30
 Ejemplo 24 Incrementar en un 10% el sueldo de los empleados del departamento 10. update EMPLEADO set salario=salario*1.1 where cod_dep=10
    7. SQL - Structured Query Language P á g i n a | 7
 Ejemplo 25 Cambiar la localidad del departamento número 10 a ‘Zaragoza’. update EMPLEADO set localizacion='Zaragoza' where cod_dep = 10
 Ejemplo 26 En la tabla DEPARTAMENTO borrar el departamento número 40. delete from DEPARTAMENTO where cod_dep = 40
 Ejemplo 27 En la tabla EMPELADO borrar todos los empleados que sean del departamento 20. delete from EMPLEADO where cod_dep = 20


ACCESS II: Práctica II SQL Tablas


ACCESS II, Trabajo Final FORMULARIO (Crea una B.D (Llamarla Arrendadora))







ACCESS II: Código del Módulo bas_sesion

Option Compare Database

'---------------------------------------------------------------------
' Procedure : Log_Sesion
' Author : Witigo (Angel Campos Muñoz)
' Date : 22/09/2014
' Purpose : Inserta un registro en la tabla dbo_logs_sesion con los
' datos de la sesión de usuario
'---------------------------------------------------------------------
'
Public Function Log_Sesion(intUsuario As Integer, _
                           strResultado As String, _
                           Optional strContraseña As String = "")




   Set dbs = CurrentDb()
   Set rst = dbs.OpenRecordset("dbo_logs_sesion")

   With rst

      ' Agregamos un registro
      .AddNew

      ' Especificamos los campos en los que vamos a insertar
      ' los datos relativos a la sesión de usuario.
      .Fields("Fecha").Value = Now()
      .Fields("Terminal").Value = Environ("Computername")
      .Fields("ID_Usuario").Value = intUsuario
      .Fields("Resultado").Value = strResultado
      .Fields("ContraseñaErronea").Value = strContraseña

      ' Actualizamos el registro
      .Update

   End With

   ' Cerramos el recordset
   rst.Close

   ' Borramos los objetos
   Set rst = Nothing
   Set dbs = Nothing

End Function

ACCESS II: Código del Módulo bas_seguridad_sesion

Option Compare Database
Option Explicit

' Variable privada que controla los intentos de login fallidos
Private bytErrLogin As Byte
Public Sub Block_Usuario(intUsuario As Integer)

Dim dbs As DAO.Database
Dim rst As DAO.Recordset

Dim strSQL As String

    strSQL = "SELECT dbo_Usuarios.Activo " & _
                "FROM dbo_Usuarios " & _
                "WHERE ID_Usuario = " & intUsuario & ";"
               
    Set dbs = CurrentDb()
    Set rst = dbs.OpenRecordset(strSQL, dbOpenDynaset)

    With rst
       
        ' Modificamos el registro
        .Edit

        .Fields("Activo").Value = False

        ' Actualizamos el registro
        .Update
   
    End With
   
    ' Cerramos el recordset
    rst.Close
    ' Borramos los objetos
    Set rst = Nothing
    Set dbs = Nothing

End Sub

'Purpose   : Devuelve el número máximo de intentos fallidos de iniciar
'             sesión en la aplicación.
'-------------------------------------------------------------------------
'
Public Function Get_ErrMaxLogin() As Byte

Dim dbs As DAO.Database
Dim rst As DAO.Recordset

Dim strSQL As String

    strSQL = "SELECT dbo_Opciones.ID_Opcion, " & _
                    "dbo_Opciones.ErrMaxLogin " & _
                "FROM dbo_Opciones " & _
                "WHERE (((dbo_Opciones.ID_Opcion) = 1));"
               
    Set dbs = CurrentDb()
    Set rst = dbs.OpenRecordset(strSQL, dbOpenDynaset)
   
    With rst
   
        ' Devolvemos 0 por que no hay registros
        If .RecordCount = 0 Then Get_ErrMaxLogin = 0
       
        ' Devolvemos el número máximo de intentos
        Get_ErrMaxLogin = !ErrMaxLogin
   
    End With
   
    ' Cerramos el recordset
    rst.Close
    ' Borramos los objetos
    Set rst = Nothing
    Set dbs = Nothing

End Function
'Procedure:  Comprueba_Intentos
' Purpose   : Comprueba los intentos de inicio de sesión fallidos y actúa
'             en consecuencia.
'-------------------------------------------------------------------------
'
Private Sub Comprueba_Intentos(bytErrLogin As Byte, _
                                intUsuario As Integer)

    If bytErrLogin = Get_ErrMaxLogin Then

        ' Mostramos el mensaje "Se ha superado el número máximo de intentos
        ' de inicio de sesión"
        MsgBox "Se ha superado el número máximo de intentos de " & _
                "inicio de sesión." & _
                vbCrLf & vbCrLf & _
                "Usuario : """ & Me.cbo_Usuario.Column(1) & """." & _
                vbCrLf & vbCrLf & _
                "El usuario ha sido bloqueado.", _
                vbExclamation, "Inicio de sesión"
           
        ' Bloqueamos al usuario
        Call Block_Usuario(intUsuario)
           
        ' Hacemos log del bloqueo del usuario
        Call Log_Sesion(intUsuario, "El usuario ha sido bloqueado.")
       
        With Me
       
            ' Actualizamos el combobox cbo_Usuario
            .cbo_Usuario.Requery
               
            ' Borramos la contraseña
            .txt_Contraseña = ""
               
            ' Ocultamos la etiqueta
            .lbl_Mensaje.Visible = False
     
        End With
     
    End If
           
End Sub

ACCESS II: Vista de Login Access II



ACCESS II: (Informes Parte2)



ACCESS II: (Informes )










Access II (Crear un Informe con Una Condición)



PRÁCTICA ACCESS AVANZADO
CREACIÓN DE UN INFORME, LIGADO A UN FORMULARIO, CON UNA CONDICIÓN

Recupera una Base de Datos, Identifica una Tabla.
1) Crearemos un Formulario Personalizado, basado en una Tabla
  a) Diseño del Formulario, Insertamos un Campo, en este caso (Costo de la Unidad), le ponemos nombre a la etiqueta.
Activamos la Hoja de Propiedades y le pondremos nombre al cuadro de texto, Ejemplo (TxtCostoDeUnidad), Guardar el Formulario.

2)Crear una Consulta Sencilla, Utilizando el asistente, seguir las Instrucciones, pasar todos los campos, Asignar nombre a la consulta, hasta llegar al punto donde dice: modificar el diseño de la consulta. Poner la condición a la consulta que es 1, guardar y probar que funcione.
3) Crear un informe, Utilizando el asistente, en base a la consulta, pasar todos los campos, y probar que funcione
4) Recuperar el formulario y poner un botón de acción que realice todo el proceso, hasta crear el informe.




ACCESS II: Continuación Teoría


Cláusulas SQL básicas: SELECT, FROM y WHERE


Una instrucción SQL tiene el formato general:
SELECT field_1
FROM table_1
WHERE criterion_1
;
Notas: 
  • Access pasa por alto los saltos de línea en una instrucción SQL. En cambio, conviene usar una línea para cada cláusula para que las instrucciones SQL sean más fáciles de leer por todos.
  • Cada una de las instrucciones SELECT termina con un punto y coma (;). El punto y coma puede aparecer al final de la última cláusula o solo en una línea al final de la instrucción SQL.

Un ejemplo en Access

A continuación se muestra el aspecto que podría tener en Access una instrucción SQL para una consulta de selección simple:
Pestaña del objeto SQL en la que se muestra una instrucción SELECT
1. Cláusula SELECT
2. Cláusula FROM
3. Cláusula WHERE
En este ejemplo de instrucción SQL, se indica "Seleccionar los datos almacenados en los campos Dirección de correo electrónico y Empresa de la tabla llamada Contactos, específicamente aquellos registros en los cuales el valor del campo Ciudad sea Seattle".
A continuación se incluye un ejemplo y se describe cada cláusula para mostrar cómo funciona la sintaxis SQL.

Cláusula SELECT

SELECT [E-mail Address], Company
Esta es la cláusula SELECT. Se compone de un operador (SELECT) seguido de dos identificadores ([Dirección de correo electrónico] y Empresa).
Si un identificador contiene espacios o caracteres especiales (como "Dirección de correo electrónico"), se debe escribir entre corchetes.
Una cláusula SELECT no tiene que mencionar las tablas que contienen los campos y no puede especificar las condiciones que deben cumplir los datos que se van a incluir.
La cláusula SELECT siempre aparece antes que la cláusula FROM en una instrucción SELECT.

Cláusula FROM

FROM Contacts
Esta es la cláusula FROM. Se compone de un operador (FROM) seguido de un identificador (Contactos).
Una cláusula FROM no enumera los campos que se van a seleccionar.

Cláusula WHERE

WHERE City="Seattle"
Esta es la cláusula WHERE. Se compone de un operador (WHERE) seguido de un identificador (Ciudad="Seattle").
Nota: A diferencia de las cláusulas SELECT y FROM, la cláusula WHERE no es un elemento obligatorio en una instrucción SELECT.
Puede llevar a cabo muchas de las acciones que le permite realizar SQL con las cláusulas SELECT, FROM y WHERE. En estos artículos adicionales se presenta más información sobre cómo usar estas cláusulas:

Ordenar los resultados: ORDER BY

Como Microsoft Excel, Access le permite ordenar los resultados de la consulta en una hoja de datos. También puede especificar en la consulta cómo quiere ordenar los resultados al ejecutar la consulta, mediante una cláusula ORDER BY. Si usa una cláusula ORDER BY, es la última cláusula en la instrucción SQL.
Una cláusula ORDER BY contiene una lista de los campos que quiere usar para ordenar, en el mismo orden en el que quiere aplicar las operaciones de ordenación.
Por ejemplo, suponga que quiere ordenar los resultados por el valor del campo Empresa en orden descendente y, en caso de que haya registros con el mismo valor para Empresa, quiere ordenarlos además por el valor indicado en el campo Dirección de correo electrónico en orden ascendente. La cláusula ORDER BY podría ser similar a la siguiente:
ORDER BY Company DESC, [E-mail Address]
Nota: De forma predeterminada, Access ordena los valores en orden ascendente (A-Z, de menor a mayor). Use la palabra clave DESC para ordenar los valores en orden descendente en su lugar.
Para obtener más información sobre la cláusula ORDER BY, vea el tema sobre la cláusula ORDER BY.

Trabajar con datos resumidos: GROUP BY y HAVING

A veces quiere trabajar con datos resumidos, como las ventas totales en un mes o los elementos más caros de un inventario. Para ello, aplique una función de agregado a un campo en la cláusula SELECT. Por ejemplo, si quiere que la consulta muestre el recuento de las direcciones de correo electrónico enumeradas de cada empresa, la cláusula SELECT podría ser similar a la siguiente:
SELECT COUNT([E-mail Address]), Company
Las funciones de agregado que puede usar dependen del tipo de datos que haya en el campo o la expresión que quiera usar. Para obtener más información sobre las funciones de agregado disponibles, consulte el artículo Funciones de agregado de SQL.

Especificar campos que no se usan en una función de agregado: Cláusula GROUP BY

Al usar funciones de agregado, normalmente debe crear también una cláusula GROUP BY. Una cláusula GROUP BY enumera todos los campos a los que no se aplica una función de agregado. Si aplica funciones de agregado a todos los campos en una consulta, no tendrá que crear la cláusula GROUP BY.
Una cláusula GROUP BY va inmediatamente después de la cláusula WHERE, o la cláusula FROM si no hay ninguna cláusula WHERE. Una cláusula GROUP BY enumera los campos tal y como aparecen en la cláusula SELECT.
Por ejemplo, siguiendo con el ejemplo anterior, si la cláusula SELECT aplica una función de agregado a [Dirección de correo electrónico] pero no a Empresa, la cláusula GROUP BY sería similar a la siguiente:
GROUP BY Company
Para obtener más información sobre la cláusula GROUP BY, vea el tema sobre la cláusula GROUP BY.

Limitar los valores de agregado mediante los criterios de agrupación: cláusula HAVING

Si quiere usar criterios para limitar los resultados, pero el campo al que quiere aplicar los criterios se usa en una función de agregado, no puede usar una cláusula WHERE. En su lugar, use una cláusula HAVING. Una cláusula HAVING funciona como una cláusula WHERE, pero se usa para los datos agregados.
Por ejemplo, suponga que usa la función COUNT (que devuelve un número de filas) con el primer campo de la cláusula SELECT:
SELECT COUNT([E-mail Address]), Company
Si quiere que la consulta restrinja los resultados según el valor de esa función COUNT, no puede usar un criterio para ese campo en la cláusula WHERE. En su lugar, coloque los criterios en una cláusula HAVING. Por ejemplo, si solo quiere que la consulta devuelva filas si hay más de una dirección de correo electrónico asociada a la empresa, la cláusula HAVING podría ser similar a la siguiente:
HAVING COUNT([E-mail Address])>1
Nota: Una consulta puede incluir una cláusula WHERE y una cláusula HAVING: los criterios para los campos que no se usan en una función de agregado se corresponden con la cláusula WHERE y los criterios de los campos que se usan en las funciones de agregado se corresponden con la cláusula HAVING.
Para obtener más información sobre la cláusula HAVING, vea el tema sobre la cláusula HAVING.

Combinar los resultados de las consultas: UNION

Si quiere revisar todos los datos obtenidos en conjunto de varias consultas de selección similares, como un conjunto combinado, use el operador UNION.
El operador UNION le permite combinar dos instrucciones SELECT en una. Las instrucciones SELECT que combine deben tener el mismo número de campos de resultado, en el mismo orden y con el mismo tipo de datos o con tipos de datos compatibles. Al ejecutar la consulta, los datos de cada conjunto de campos correspondientes se combinan en un único campo de resultado de modo que el resultado de la consulta tenga el mismo número de campos que cada una de las instrucciones SELECT.
Nota: Para las consultas de unión, los tipos de datos Texto y Número son compatibles.
Si usa el operador UNION, también puede usar la palabra clave ALL para especificar si los resultados de la consulta deben incluir las filas duplicadas, si existe alguna.
La sintaxis básica de SQL para una consulta de unión que combina dos instrucciones SELECT es la siguiente:
SELECT field_1
FROM table_1
UNION [ALL]
SELECT field_a
FROM table_a
;
Por ejemplo, supongamos que tiene una tabla denominada Productos y otra tabla denominada Servicios. Ambas tablas tienen campos que contienen el nombre del producto o servicio, el precio, la disponibilidad de garantía del servicio o de garantía del producto, y si el producto o servicio se ofrece de forma exclusiva. Aunque en la tabla Productos se almacena información de garantía del producto y en la tabla Servicios se almacena información de garantía del servicio, la información básica es la misma (si un producto o servicio determinado incluye una garantía de calidad). Puede usar una consulta de unión, como la que se muestra a continuación, para combinar los cuatro campos de las dos tablas:
SELECT name, price, warranty_available, exclusive_offer
FROM Products
UNION ALL
SELECT name, price, guarantee_available, exclusive_offer
FROM Services
;
Para obtener más información sobre cómo combinar instrucciones SELECT mediante el operador UNION, vea Usar una consulta de unión para combinar varias consultas en un mismo resultado.