Consultar datos distintos en una misma tabla de datos

Augusto, soy Ricardo de nuevo, ayer te hice esta misma pregunta, pero parece que no te llego porque no me sale como pregunta activa, de lo que te pregunte anteriormente sobre como recorrer una base de datos esta todo bien pero hay algo que necesito saber, y es si con Recordset dentro de un ciclo, podría comparar dos datos de una misma tabla, ya sea cual es el mayor por ejemplo, pero siendo estos dos datos no consecutivos (comparar por ejemplo el primero de la tabla con el 320 de la misma y después el segundo con el 321 y así sucesivamente) y si no es posible con recordset, como podría hacerlo.
Y una segunda consulta que seria que trabajo con una base de datos que ya tiene muchas consultas y tablas que se crean a partir de ellas, y lo que necesito hacer es utilizar una tabla de las que ya te mencioné, que contiene una lista de lecturas por hora en un mes (24x30) y que corresponden a muchos equipos (400) y están todos juntos, y la idea es calcular el promedio diario y el máximo diario (serian dos tablas) para cada equipo y guardarlo en otra tabla (30 datos por cada equipo). Para ello primero ordené dichos datos, pero cuando quieria registrar por día los máximos y el promedio, las opciones de access no lo permiten (me las calcula para el total de la tabla y no una parte de ella que es lo que necesito) y no se si a través de código es posible.

1 respuesta

Respuesta
1
La respuesta está en el mail anterior, no es necesario un bucle si buscas con indice y ademas así es más rápido
comparo dos datos
--------------------------------------------------------------------------
La cabecera como anteriormente y supongamos que ya tenemos la tabla abierta y el recordset se llama pagos
depende lo que vayas a comparar deberíamos utilizar una variable para guardar el valor antes de moverme al otro registro ( con el que voy a comparar), suponiendo que comparo datos numéricos.:
--------------------------------------------------------------------------------------------------
Dim aux  as integer ' defino una varible de tipo entero
 pagos.index ="xxxxxx" ' nombre del indice con que vas a buscar
 pagos.seek "=", 100  ' busco el registro cuyo indice es 100 
 aux = pagos![total]  ' asigno a la variable  el valor del campo  "total" para el registro 100
pagos.seek "=", 28              ' me muevo al registro 28    y ahora comparo
if  aux > pagos![total]  then   ' si lo que esta en la variable es mayor que  total   (del 28)
Pagos. Edit ' voy a escribir en la tabla o lo que sea
...
pagos.update
pagos.close
End if
Para no tener que repetir el procedimiento por cada valor se supone que ya tienes los dos vales de los indices que vas a comparar podría ser así
Public  sub compara ( n1 , n2 as integer )
cuando llegues a  pagos.seek  pones
pagos.seek "=" , n1   '  o  tambien n2    porque pasamos estos valores  al procedimiento
............
End sub
Ponemos public en vez de private para que puedas llamar a la función desde cualquier lugar de la aplicación
la llamada seria más o menos así
Call  compara ( 100, 28)  ' llamamos a la funcion desde cualquier lugar del codigo
call compara ( 200, 35) etc
Contestando a lo segundo lo que no se puede hacer por código no se puede hacer de ninguna manera
asique un bucle while que cuente los registros que deben cumplir una condición
-----------------------------------------------------------------------------------------------
public function promedio ( valor as integer ) as integer
 while not  pagos.EOF 
 if pagos![total] = valor    then  ' por ejem
  C= C+1  ' cuentos los registros que tienen el valor pasado como parametro
  aux = aux+pagos![importe] ' acumulo  el importe de cada registro = valor
end if
pagos.movenext
¿Wend ' ya tengo el total en la variable C previamente definida no?
Promedio = Aux/ C ' saco el promedio de los registros contados
End function
Llamo a la función pero como devuelve un valor necesariamente lo tengo que poner en un control o una variable
ej en otro procedimiento
dim totalp as integer
totalp = promedio ( 20 ) ' me cuenta los registros que tienen el valor 20 y saca su promedio del campo que yo indique en el primer procedimiento claro
  Bueno espero saques algo de esto saludos
Augusto, primero que todo perdona por no responderte antes, pero tenia problemas para conectarme a internet, gracias por tu ayuda, el programa casi funciona de maravillas, lo único que me falta por hacer y que te quiero preguntar es como hago para que una consulta, que crea una tabla con nombres de campo de otras tablas, cree una nueva columna dentro de la tabla que siempre crea, pero con un nombre de campo que no exista en ninguna tabla (que sea totalmente nuevo, si es que me entiendes lo que quiero decir) y que tenga como valor por defecto el numero cero, porque cuando lo hago en la tabla de manera tradicional, se pierde el campo cada vez que ejecuto la consulta. Esperando que me hayas podido entender, me despido y nuevamente gracias totales.
Saludos, Ricardo.
Augusto, ahora que iba a probar el programa con la base de datos, no se que pasa, pareciera que queda en un loop, te anexo el código por si ves lo que yo no:
Option Compare Database
'Solo devuelve el minimo para dar la mayor fraccion en una comparacion mas adelante
Function minimo(x As Double, y As Double) As Integer
    If (x < y) Then
        minimo = 1
    Else
        minimo = 0
End Function
Public Sub ProgramaAlim()
    Dim db As Database
    Dim registro111 As Recordset
    Dim registro222 As Recordset
    Dim num As Double, auxIc As Double, calc As Double, frac As Double
    Dim i As Integer, j As Integer, min As Integer, counter As Long
    Dim word As String, auxNa As String
    Set db = CurrentDb
    'abro dos tablas de la base de datos, que son creadas por dos consultas
    Set registro111 = db.OpenRecordset("0025 I_Alim_max_diario")
    Set registro222 = db.OpenRecordset("003 I_max_prom_desv")
    registro222.Edit
    registro111.Edit
     'variable word para comparar que ambos nombres sean idénticos
word = registro222![Nombre Alimentador]
    While Not registro111.EOF
        If (word = registro111![Nombre Alimentador]) Then
            If (registro111![MáxDeIc] > (registro222![Promedio Ic] + (registro222![Desv Ic]) * (registro111![Crit_DESV]))) Then
        ' registro en una tabla valor 1 para diferenciar de los demas
                registro111![Not Reprs] = 1
                registro111.MoveNext
            End If
        Else
            registro222.MoveNext
            word = registro222![Nombre Alimentador]
        End If
    Wend
 'actualizo ambas tablas
    registro111.Update
    registro222.Update
'me posiciono nuevamente en la primera posicion del registro
    registro111.MoveFirst
    j = 7
    i = 1
'reviso los datos con un nuevo criterio
    Do While Not registro111.EOF
        auxNa = registro111![Nombre Alimentador]
        auxIc = registro111![MáxDeIc]
        registro111.Index = "FECHA"
        j = j + i
        registro111.Seek "=", j
        If (registro111![MáxDeIc] = Null) Then
            Exit Do
        End If
        If (auxNa = registro111![Nombre Alimentador]) Then
            calc = registro111![MáxDeIc] - auxIc
            min = minimo(registro111![MáxDeIc], auxIc)
            If (min = 1) Then
                frac = cal / registro111![MáxDeIc]
            Else
                frac = cal / auxIc
            End If
            If (frac > 0.6 Or frac < (-0.6)) Then
                registro111![Not Reprs] = 1
            End If
            registro111.Index = "FECHA"
            registro111.Seek "=", i
            registro111.MoveNext
            i = i + 1
        Else
            i = j
            registro111.Index = "FECHA"
            registro111.Seek "=", i
            j = 7
        End If
    Loop
   'cierro las tablas
    registro111.Close
    registro222.Close
End Sub
Después llamo a este sub a través de un botón que ademas tiene una etiqueta, con el siguiente código:
 Private Sub Comando12_Click()
    DoCmd.SetWarnings False
    DoCmd.Hourglass True
    msg = "Proceso en curso..."
    msg1 = "PROCESO TERMINADO"
    Forms![Principal]![Texto14] = msg
    Call ProgramaAlim
    DoCmd.Hourglass False
    Forms![Principal]![Texto14] = msg1
    DoCmd.SetWarnings True
End Sub
Esperando no ser de mucha molestia, se despide:
Ricardo.
Parece que has usado bien algunos temas de los que hablamos, queda el reloj de arena y no te deja salir, pues eso si es un loop, se queda sin ram y ejecutando el mismo, para detectar errores de ese tipo te aconsejo que que llames a cada procedimiento en forma individual, ya que hay una opción que permite detectar errores pero los loops no los ataja . ya me has intrigado, ¿para qué es todo esto?, si quieres me cuentas
  If (word = registro111![Nombre Alimentador]) Then
            If (registro111![MáxDeIc] > (registro222![Promedio Ic] + (registro222![Desv Ic]) * (registro111![Crit_DESV]))) Then
        ' registro en una tabla valor 1 para diferenciar de los demas
                registro111![Not Reprs] = 1
                registro111.MoveNext
            End If
        Else
            registro222.MoveNext --> ESTA LINEA DE CODIGO  VA ANTES DEL WEND
      ( Y NO DENTRO DEL IF  PORQUE SINO EL BUCLE NO AVANZA NUNCA CUANDO NO ENTRE AL IF Y NO SALE DEL WHILE   )
            word = registro222![Nombre Alimentador]
        End IF
Me olvidaba fíjate que en un recordset tiene que esta algún comando para crear un campo nuevo, no recuerdo pero debe existir entonces en ese mismo momento que lo creas le asignas después de edit el valor 0
Prueba con este comando donde rs es un recordset abierto
Rs. Append "nomcampo1", adinteger
Rs. Append "nomcampo2", advarchar, 30
Te cuento lo que hago, pero primero tengo dos dudas, la primera es que agregar un indice a una tabla que es creada a partir de una consulta pero cada vez que ejecuto la consulta, se pierde el indice, ¿así qué como lo debo hacer para el indice se mantenga a pesar de las consultas?.
La segunda consulta es que corregí el primer ciclo del programa anterior, con tu ayuda y estoy tratando de corregir el segundo ciclo pero parece que el problema es con los registros, da la impresión de que no los reconoce, pero el ciclo anterior funciona bien, y la pregunta es si hay que hacer algo con el registro(recordset) porque ya lo abrí, le puse edit, luego le agregue un valor y finalmente lo actualice (update) y no lo cierro hasta el final del programa. A continuación te adjunto el programa y parte del código que quiero me ayudes a solucionar:
Function minimo(x As Double, y As Double) As Integer
    If (x < y) Then
        minimo = 1
    Else
        minimo = 0
End Function
Public Sub ProgramaAlim()
    Dim db As Database
    Dim registro111 As Recordset
    Dim registro222 As Recordset
    Dim num As Double, auxIc As Double, calc As Double, frac As Double
    Dim i As Integer, j As Integer, min As Integer, counter As Long
    Dim word As String, auxNa As String
    Set db = CurrentDb
    Set registro111 = db.OpenRecordset("0025 I_Alim_max_diario")
    Set registro222 = db.OpenRecordset("003 I_max_prom_desv")
    registro222.Edit
    registro111.Edit
'ACA VA EL CICLO QUE FUNCIONA BIEN
'//////////////////////////////////////////////////
'Luego posiciono nuevamente en la primera posicion de la tabla "0025..."
registro111.MoveFirst
    j = 7
    i = 1
    frac = 0
Do While Not registro111.EOF
'guardo datos de la linea que leo para luego, a traves del indice cambiarme de linea
        auxNa = registro111![Nombre Alimentador]
        auxIc = registro111![MáxDeIc]
        registro111.Index = "FECHA"
        j = j + i
        registro111.Seek "=", j
     'SI EXISTE VALOR REALIZA LA TAREA
        If (registro111![MáxDeIc] <> Null) Then
        'COMPARA DATOS DE LA LINEA AUXILIAR CON LA ACTUAL
             If (auxNa = registro111![Nombre Alimentador]) Then
                   calc = registro111![MáxDeIc] - auxIc
                   'LLAMO A UNA FUNCION PARA ASERGURAR QUE DIVIDA POR EL MENOR
                   min = minimo(registro111![MáxDeIc], auxIc)
                   If (min = 1) Then
                       frac = cal / registro111![MáxDeIc]
                   Else
                       frac = cal / auxIc
                   End If
             'PREGUNTO SI ESTÁ DENTRO DEL RANGO Y REGISTRA ESE VALOR 1
                   If (frac > 0.6 Or frac < (-0.6)) Then
                       registro111.Edit
                       registro111![Not Reprs] = 1
                       registro111.Update
                       registro111.MoveNext
                    Else
                       registro111.MoveNext
                    End If
               'LUEGO VUELVO A POSICIONARME EN LA POSICION SIGUIENTE DE LA QUE      COMENCE EL CICLO
                    i = i + 1
                    registro111.Index = "FECHA"
                    registro111.Seek "=", i
    'Si comparacion if (2° anidado) es false                               
            Else
                  i = j
                  registro111.Index = "FECHA"
                  registro111.Seek "=", i
                  j = 7
             End If
   'SI NO ES DISTINTO DE NULL SE SALE DEL CICLO 
    Else
            Exit Do
    End If
 Loop
    registro111.Close
    registro222.Close
End Sub
Estoy haciendo una practica en electricidad y debo corregir unas lecturas erróneas con un programa en VBA, y gracias a tu ayuda, voy muy bien. Saludos.
Amigo disculpas por la demora, realmente no he podido analizar el código pero el consejo es que crees las tablas a través de código . seguramente encontrás por ahí el código y también ponerles los atributos a los campos . Lamento no haberte podido ayudar más .
Amigo no te preocupes, solucione el problema anterior creando otra tabla con los mismos datos pero que la adelanto en la cantidad de lineas y así puedo comparar los datos, el programa ya funciona y gracias por toda tu ayuda. Saludos.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas