Cambios de inventario con DAX: dilema de apertura y cierre dentro de la ubicación

Un usuario Pregunto ✅

mwimberger

Hola amigos

Tengo un problema interesante que resolver. Implica calcular los saldos de apertura y cierre para las ubicaciones de inventario o las existencias. La operación cuenta con un sistema de seguimiento de materiales que rastrea el material movido desde el origen hasta los destinos para una operación a cielo abierto. En la mayoría de los casos, los saldos de apertura y cierre se resuelven utilizando las siguientes medidas:

Opening Stock Tonnes =
CALCULATE ( [Tonnage Movement],
     FILTER (
         ALLEXCEPT ( Data, Data[Stockpile_ID],Data[Stockpile_ID_Detail] )
       ,'Data'[Date] < min('Data'[Date])
    )
	

Closing Stock Tonnes = 
CALCULATE (
    [Tonnage Movement],
    FILTER (
        ALLEXCEPT ( Data, Data[Stockpile_ID] ),
        'Data'[Date] <= MAX ( 'Data'[Date] )
    )
)

Tonnage Movement =
CALCULATE ( SUMX ( 'Data', 'Data'[Tonnes] ), 'Data'[In_Code] = "IN" )
    - CALCULATE ( SUMX ( 'Data', 'Data'[Tonnes] ), 'Data'[In_Code] = "OUT" )

Todo esto funciona bien hasta que haya dentro de la pila movimientos – o movimientos Entre reservas No debería ocurrir, pero la realidad, por supuesto, está en el trabajo.

El problema se resume en las siguientes imágenes:

Diagrama.jpg

¡El problema ocurre en el signo de exclamación! arriba – en que la Reserva C tiene toneladas restadas, la Reserva D tiene toneladas añadidas, todo en una línea de transacción en la base de datos. Mi columna «In_Code» obviamente no puede manejar un código «In» y «Out» simultáneamente.

Hoja de calculo.jpg

La hoja de cálculo anterior es un intento de mostrar en fórmulas qué deberían sucede con los tonelajes.

¿Alguien tiene una idea para manejar esto con elegancia en DAX? Tengo alrededor de 1,4 millones de filas de transacciones y sé que necesito optimizar un poco los cálculos (creo que mis iteradores SUMX posiblemente estén ralentizando las cosas) además del hecho de que los usuarios quieren esta información en una tabla de matriz que también se suma a los gastos generales . Pero lo primero es lo primero: ¿cómo manejar los movimientos dentro de las existencias? 🤷‍♂️😥

Cualquier ayuda sería muy apreciada. He estado intentando/luchando con USERRELATIONSHIP pero estaba saliendo de problemas de memoria, y no tengo pelo para sacar.

Gracias por adelantado

Manfredo

roseta03

Hola Manfred,

También necesito resolver un problema similar, también para el bloque de mineral para acopio de movimientos de trituradora para una operación a cielo abierto… con una tabla idéntica.
¡Solo me preguntaba si lograste resolver esto y si podrías compartir algunos detalles!

Muchas gracias,

Tim

mwimberger

En respuesta a roseta03

Hola Tim

Logré resolver esto. Mi solución inicial fue usar USERRELATIONSHIP, pero esto no estuvo completamente libre de problemas, ya que parecía ralentizar las cosas.

Lo que luego decidí fue una segunda consulta referenciada (subconjunto de los datos iniciales) y una relación de esta consulta con la lista Distinta de ubicaciones (entradas y salidas)
Detallaré exactamente cómo hice esto con una publicación más larga pronto. ¡Es bueno ver algún interés relacionado con la minería por ahí!

Salud

Manfredo

roseta03

En respuesta a mwimberger

¡Aprecio la actualización Manfred! Sería genial si pudiera actualizarnos a su debido tiempo. Esperemos que podamos comparar notas y trabajar en una solución realmente agradable.

Supongo que su objetivo final es similar al mío: ¿para la planificación de mezclas para el grado de alimentación de la trituradora?

¡Muchas gracias!

Tim

mwimberger

En respuesta a roseta03

Hola @roset03

El objetivo final es, en parte, la combinación, pero, con mucho, el objetivo principal era completar un marco completo de reconciliación de la cadena de valor que vinculara la geología, la minería y la metalurgia. Como sabrá, las reservas son generalmente un punto de transferencia entre departamentos y, por lo tanto, pueden resultar los más difíciles de administrar. Y para la mayoría de los estudios de conciliación, el Delta en las pilas de acopio es lo que se necesita para contabilizar el material que no va directamente del tajo a la planta.

Mi solución fue hacer lo siguiente:

Crear una tabla separada de datos (filtrados) de dentro de la pila movimientos desde el Datos tabla

Data Filtered IntraStockpile =
FILTER (
    Data,
    LEFT ( Data[Unified_Origen], 6 ) = "Stock "
        && LEFT ( Data[Unified_Destination], 6 ) = "Stock "

Tenga en cuenta que creé un identificador «unificado» ya que el sistema de envío, por alguna razón, tiene diferentes órdenes de taxonomía al nombrar fuentes y destinos.

Luego creé una tabla de dimensiones que generaba una lista de la identificación de la reserva y el detalle de la identificación de la reserva (necesitaba las reservas agrupadas en óxido, sulfuro o mixto)

tblStockpileIDUnique =
FILTER (
    SUMMARIZE ( data, Data[Stockpile_ID], Data[Stockpile_ID_Detail] ),
    Data[Stockpile_ID_Detail] <> ""
)

Esta tabla de dimensiones estaba vinculada a la tabla de datos original y a la tabla filtrada, pero utiliza las siguientes relaciones:

datos[Source] *—->tblStockpileIDUnique[Stockpile_ID_Detail] <----* Datos filtrados IntraStockpile[Destination]

El tonelaje In se calcula como

Tonnage In = 
CALCULATE (
    SUM ( 'Data Filtered IntraStockpile'[TON_AJUSTADO] ),
    'Data Filtered IntraStockpile'[In_Code] = "OUT"
)
    + CALCULATE ( SUM ( 'Data'[TON_AJUSTADO] ), 'Data'[In_Code] = "IN" )

Tonelaje fuera calculado como

Tonnage Out = calculate(sum('Data'[TON_AJUSTADO]),'Data'[In_Code]="OUT")

Movimiento de tonelaje calculado como:

Tonnage Movement = [Tonnage In]-[Tonnage Out]

Y luego aperturas y cierres definidos como:

Opening Stock Tonnes = 
VAR vLastDate = min('Data'[FECHA])
Return
CALCULATE ( [Tonnage Movement],
     FILTER (
         ALLEXCEPT ( Data, Data[Stockpile_ID],Data[Stockpile_ID_Detail] )
       ,'Data'[FECHA] < vLastDate )
    )


Closing Stock Tonnes = 
CALCULATE (
    [Tonnage Movement],
    FILTER (
        ALLEXCEPT ( Data, Data[Stockpile_ID], Data[Stockpile_ID_Detail] ),
        'Data'[FECHA] <= MAX ( 'Data'[FECHA] )
    )

(nota Fecha significa fecha en español)
Entonces, básicamente, la solución es vincular las reservas a ambos el origen y el destino (usando las dos tablas separadas) y use el código de ENTRADA o SALIDA para calcular sumas y restas del movimiento de material. Hay un poco más en las configuraciones que preceden a estos pasos, como definir si el material se mueve ADENTRO o AFUERA (según el diagrama anterior), pero eso es bastante fácil.
Envíeme un mensaje instantáneo en LinkedIn si necesita más información. Estaremos encantados de discutir si necesita más ayuda.

Salud

Manfredo

mwimberger

Hola amigos

Tengo un problema interesante que resolver. Implica calcular los saldos de apertura y cierre para las ubicaciones de inventario o las existencias. La operación cuenta con un sistema de seguimiento de materiales que rastrea el material movido desde el origen hasta los destinos para una operación a cielo abierto. En la mayoría de los casos, los saldos de apertura y cierre se resuelven utilizando las siguientes medidas:

Opening Stock Tonnes =
CALCULATE ( [Tonnage Movement],
     FILTER (
         ALLEXCEPT ( Data, Data[Stockpile_ID],Data[Stockpile_ID_Detail] )
       ,'Data'[Date] < min('Data'[Date])
    )
	

Closing Stock Tonnes = 
CALCULATE (
    [Tonnage Movement],
    FILTER (
        ALLEXCEPT ( Data, Data[Stockpile_ID] ),
        'Data'[Date] <= MAX ( 'Data'[Date] )
    )
)

Tonnage Movement =
CALCULATE ( SUMX ( 'Data', 'Data'[Tonnes] ), 'Data'[In_Code] = "IN" )
    - CALCULATE ( SUMX ( 'Data', 'Data'[Tonnes] ), 'Data'[In_Code] = "OUT" )

Todo esto funciona bien hasta que haya dentro de la pila movimientos – o movimientos Entre reservas No debería ocurrir, pero la realidad, por supuesto, está en el trabajo.

El problema se resume en las siguientes imágenes:

Diagrama.jpg

¡El problema ocurre en el signo de exclamación! arriba – en que la Reserva C tiene toneladas restadas, la Reserva D tiene toneladas añadidas, todo en una línea de transacción en la base de datos. Mi columna «In_Code» obviamente no puede manejar un código «In» y «Out» simultáneamente.

Hoja de calculo.jpg

La hoja de cálculo anterior es un intento de mostrar en fórmulas qué deberían sucede con los tonelajes.

¿Alguien tiene una idea para manejar esto con elegancia en DAX? Tengo alrededor de 1,4 millones de filas de transacciones y sé que necesito optimizar un poco los cálculos (creo que mis iteradores SUMX posiblemente estén ralentizando las cosas) además del hecho de que los usuarios quieren esta información en una tabla de matriz que también se suma a los gastos generales . Pero lo primero es lo primero: ¿cómo manejar los movimientos dentro de las existencias? 🤷‍♂️😥

Cualquier ayuda sería muy apreciada. He estado intentando/luchando con USERRELATIONSHIP pero estaba saliendo de problemas de memoria, y no tengo pelo para sacar.

Gracias por adelantado

Manfredo

Deja un comentario

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