Cómo eliminar registros de acceso repetidos en un corto espacio de tiempo usando DAX

Un usuario Pregunto ✅

WestMart

Queridos amigos:

Necesitaría ayuda para suprimir, mediante el editor de consultas de Power BI, ciertos registros en una tabla de control de acceso de personal.

El caso concreto es que, al acceder al edificio, el personal registra su entrada en lectores que se almacenan en una base de datos. Pero a veces pasan la tarjeta varias veces y se registran múltiples entradas en un corto espacio de tiempo, y tendríamos que eliminarlas de la consulta para tener datos consistentes, y me gustaría hacerlo usando DAX (Query Editor power BI) .

La tabla tiene el formato siguiente y quería eliminar los registros de la misma persona que se repiten en un momento específico.

Por ejemplo, eliminar registros realizados en un espacio temporal de menos de 5 minutos., Por lo que en el caso de esta tabla las filas con Access ID 2 y 3 tendrían que eliminarse, ya que solo hay unos segundos entre un registro y otro.

IDAcceso IDPersona IDNivel IDDispositivo IDInstalación FechaHora Fecha Tiempo
1 1 1 2 5578 24/06/2020 8:19 24/06/2020 8:19:16
2 1 1 2 5578 24/06/2020 8:19 26/06/2020 8:19:19
3 1 1 2 5578 24/06/2020 8:19 24/06/2020 8:19:22
4 1 1 2 5578 25/06/2020 9:19 25/06/2020 9:19:11
5 1 1 2 5578 24/06/2020 18:36 24/06/2020 18:36:09
6 1 1 2 5578 24/06/2020 18:36 24/06/2020 18:36:17
7 1 1 2 5578 25/06/2020 18:31 25/06/2020 18:31:55
8 2 1 2 5578 28/06/2020 9:24 28/06/2020 9:24:52
9 3 1 2 5578 28/06/2020 9:24 28/06/2020 9:24:59
10 4 1 2 5578 28/06/2020 9:25 28/06/2020 9:25:04

También quería que el espacio temporal por el que se borran las filas registradas fuera parametrizable, es decir, que pudieran ser de 5 minutos, o 10 minutos, etc., y entiendo que esto tendría que hacerse mediante un parámetro.

Le he dado muchas vueltas para conseguir lo que se pretendía, pero aún no he llegado a una solución así que vengo a este fantástico foro, por si me pueden ayudar, lo cual agradecería enormemente.

Muchas gracias.

Atentamente.

Agustín Martínez.

WestMart

En respuesta a v-kelly-msft

Hola Kelly, ¡Fantástico! Maravillosa contribución ..

Funciona perfectamente y esto es justo lo que estaba buscando y me ayudará mucho en el informe de acceso.

Muchas gracias por la ayuda y estoy a tu disposición para lo que necesites.

Un saludo cariñoso,

Agustín

Hola @WestMart,

Primero cree una tabla de parámetros como se muestra a continuación:

Parameter = GENERATESERIES(5, 20, 5)

Luego cree una medida como se muestra a continuación:

Measure = 
var _ID=CALCULATE(MAX('Table'[IDAcceso]),FILTER(ALL('Table'),'Table'[IDPersona]=MAX('Table'[IDPersona])&&'Table'[IDAcceso]<MAX('Table'[IDAcceso])))
var _previoustime=CALCULATE(MAX('Table'[FechaHora]),FILTER(ALL('Table'),'Table'[IDPersona]=MAX('Table'[IDPersona])&&'Table'[IDAcceso]=_ID))
Return
IF(_previoustime=BLANK(),MAX('Table'[FechaHora]),IF(ABS(DATEDIFF(_previoustime,MAX('Table'[FechaHora]),MINUTE))<SELECTEDVALUE(Parameter[Parameter]),BLANK(),MAX('Table'[FechaHora]))
)

Y tu verás:

Captura de pantalla 2020-10-27 174859.png

Aquí noté que El ID de acceso 6 también debe eliminarse, ya que solo hay unos segundos entre el ID6 y el ID 5.

Para el archivo .pbix relacionado, consulte el adjunto.

Atentamente,
Kelly

¿Respondí tu pregunta? ¡Marque mi publicación como una solución!

WestMart

En respuesta a v-kelly-msft

Muchas gracias

Muchas gracias y la medida que propones funciona a la perfección.

Aunque lo que buscaba era borrar los registros de la tabla porque no son útiles y también me permitirían hacer mejor los análisis, como agregar accesos por persona, por dispositivo, etc. y según tu propuesta es más complicado porque los registros aún permanecen en la base de datos.

Aprovecharé su útil contribución y continuaré investigando cómo eliminar dicho registro de la tabla, y seguramente la mejor opción será usar DAX o el lenguaje M del editor de consultas.

Me reitero en mis gracias.

Un saludo afectuoso.

Agustín Martínez.

En respuesta a WestMart

Hola @WestMart,

Si es así, debe hacerlo en Power query, usando el siguiente código M:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("pdBbCsQgDAXQrQx+F2pi4iNbEfe/jWliKa0zg6XzIbQXPSS3VgduOQ5uhzll/aTVxxU9+lcWKJdk+9FMILq2VHt1T4gfQjEhPJ8B0QT6IfAhlF3gk1BsBjCBpzNAlhDHISwU3/eI/xiQzEjTTfQ6jKtYKMxm5P3taORTG0iXxNpAEu59alXhodC7AA1oRvAXgsWTa+0N", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [IDAcceso = _t, IDPersona = _t, IDNivel = _t, IDDispositivo = _t, IDInstalacion = _t, FechaHora = _t, Date = _t, Time = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"IDAcceso", Int64.Type}, {"IDPersona", Int64.Type}, {"IDNivel", Int64.Type}, {"IDDispositivo", Int64.Type}, {"IDInstalacion", Int64.Type}, {"FechaHora", type text}, {"Date", type text}, {"Time", type time}}),
    #"Changed Type with Locale" = Table.TransformColumnTypes(#"Changed Type", {{"FechaHora", type datetime}}, "en-SB"),
    #"Added Custom" = Table.AddColumn(#"Changed Type with Locale", "Custom", each let 
id = [IDPersona], index = [IDAcceso],
tab = Table.SelectRows(#"Changed Type with Locale",each [IDPersona]=id and [IDAcceso]=index-1)
in 
if Table.IsEmpty(tab) then
null
else
Table.Max(tab,"IDAcceso")[FechaHora]),
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "Custom.1", each if
[Custom]=null then Time.Hour([FechaHora])*60+Time.Minute([FechaHora])+Time.Second([FechaHora])/60
else Number.Abs(Duration.TotalMinutes([FechaHora]-[Custom])))
in
    #"Added Custom1"

Luego cree un parámetro de consulta como se muestra a continuación:

Captura de pantalla 2020-10-28 183131.png

Finalmente filtrar la columna según el parámetro:

Captura de pantalla 2020-10-28 183450.png

Luego, las filas que están por debajo de la duración se filtrarán.

Captura de pantalla 2020-10-28 183555.png

Para el archivo .pbix relacionado, consulte el adjunto.

Atentamente,
Kelly

¿Respondí tu pregunta? ¡Marque mi publicación como una solución!

WestMart

En respuesta a v-kelly-msft

Hola Kelly, ¡Fantástico! Maravillosa contribución ..

Funciona perfectamente y esto es justo lo que estaba buscando y me ayudará mucho en el informe de acceso.

Muchas gracias por la ayuda y estoy a tu disposición para lo que necesites.

Un saludo cariñoso,

Agustín

mahoneypat

En su publicación, indicó que la solución debería usar «DAX (Editor de consultas)». En realidad, son dos cosas diferentes (el editor de consultas usó el lenguaje «M». Esto es complicado, pero se puede hacer de dos maneras. Por favor, aclare si quiere

1. Para establecer un parámetro estático (pero modificable) que se utilizará para eliminar filas replicadas dentro del período de tiempo del parámetro cada vez que se actualicen los datos.

o

2. Mantenga todas las filas en el modelo de datos, pero tenga un control deslizante en su informe donde los usuarios del informe pueden cambiar el período de tiempo para incluir / excluir réplicas (1 min, 2 min, 5 min, etc.).

Además, será más fácil y eficaz crear contenedores de tiempo y contar personas / deslizamientos de tarjetas dentro de cada contenedor, pero siempre existe el riesgo de que dos deslizamientos cercanos en el tiempo estén en contenedores diferentes (final de uno, comienzo del siguiente). Comparar realmente cada fila / deslizamiento para confirmar que no hay otras filas por la misma persona dentro del período de tiempo especificado podría ser un cálculo intensivo (pero posible) si se necesita capacidad de respuesta a las segmentaciones.

Saludos,

Palmadita

WestMart

En respuesta a mahoneypat

muchas gracias por tu :

Con respecto a su solicitud de aclaración, indique que deseo la opción 1. que propone: establecer un parámetro estático (pero modificable) que se usará para eliminar filas de réplicas dentro del período de tiempo del parámetro cada vez que se actualicen los datos.

De esa manera, esos registros no deseados ya no aparecerán y no serán útiles para el análisis de datos.

Muchas gracias por la ayuda y esperamos la solución.

Saludos.

Agustín Martínez.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *