2016-01-20 20 views
5

Dopo il post da Chris Web, sto cercando un modo veloce per trovare l'ultimo acquisto da un cliente.MDX Query per trovare l'ultimo valore non vuoto in icCube

Io uso un'istruzione MDX come la seguente:

WITH FUNCTION previous_buys() AS tail(nonempty({NULL:[Time].[Time].currentmember.prevmember} ,[measures].[sales amt]),1) 
MEMBER [last buy] as previous_buys().(0).key 

select [measures].[last buy] on 0 
,  [Customers].[Customers].[name].members on 1 
from [Store Sales] 
where [Time].[Time].[day].&[2015-12-20T00:00:00.000] 

Questo dà come previsto, ma si sta prendendo un tempo molto lungo. C'è un modo semplice per velocizzare questa query in qualche modo. Dato che icCube è leggermente diverso da Microsoft MDX, non posso semplicemente copiare la soluzione di Chris Web.

Qualche idea?

risposta

2

Il problema principale che avremo con questa soluzione è la scalabilità mentre stiamo valutando {NULL: [Time]. [Time] .currentmember.prevmember} conteggio membri.

Ho pensato che l'utilizzo di una funzione Reverse con Head non avrebbe valutato l'intero set, ma l'implementazione corrente della funzione Empty "materializza" l'insieme. Ciò significa che stiamo valutando tutti i membri. Non ancora una soluzione valida.

Un'altra soluzione e più elegante è l'utilizzo di una funzione ricorsiva. Questo dovrebbe ridurre drasticamente il numero di membri valutati.

WITH 
    FUNCTION previous_buys(t_) AS IIF((t_,[Measures].[Amount]) = NULL, previous_buys(t_.prevMember), t_) 
    MEMBER [last buy] as previous_buys([Time].[Calendar].current).name 

SELECT 
    [measures].[last buy] on 0, 
    [Customers].[Geography].[Region] on 1 
FROM [Sales] 
WHERE [Time].[Calendar].[Year].[2006].[Q1 2006].[Jan 2006].[8 Jan 2006] 

Se hai un sacco di date vuote si potrebbe complicare un po 'l'algoritmo scendendo a un livello al mese per controllare il vuoto. Questo valuterà un intero mese in un'unica iterazione invece del 30/31 che avremo nella versione del giorno.


L'ultima e più veloce da un ordine di grandezza si basa del motore aggregazione di icCube. Quello che vogliamo qui è una misura che restituisce l'ultimo giorno esistente.

L'idea sarebbe quella di aggiungere una misura con una data come valore di input e il massimo come metodo di aggregazione. Quindi dovremmo usare eval - importante come stiamo memorizzando nella cache il sottocubo - sul set con questa nuova misura.

+0

Grazie per questa soluzione. Aiuta molto molto! – Arthur

0

Questo è relativamente veloce utilizzando SSAS rispetto a AdvWrks. Ti ho amalgamato due strutture personalizzate (& necessaria per cambiare da FUNCTION come io non credo che questo fa parte della implementazione di MS di mdx):

WITH 
    MEMBER [Measures].[previous_buys] AS 
    Tail 
    (
     NonEmpty 
     (
     {NULL : [Date].[Calendar].CurrentMember.PrevMember} 
     ,[Measures].[Internet Sales Amount] 
    ) 
    ).Item(0).Item(0).Member_Key 
SELECT 
    NON EMPTY 
    [Measures].[previous_buys] ON 0 
,NON EMPTY 
    [Product].[Product Categories].[Product] ON 1 
FROM [Adventure Works] 
WHERE 
    [Date].[Calendar].[Date].&[20071015]; 

Essa si traduce nella seguente:

enter image description here

+0

FUNCTION è un modo per creare codice riutilizzabile in icCube, utile come è possibile dichiararlo a livello di schema. – ic3

+0

whyteq, sui nostri schemi demo sta prendendo anche un secondo subsecond ;-) – ic3