Talvez isso já seja bem conhecido, mas quis compartilhar para ajudar.
Considere que você tem as seguintes definições de classes persistentes:
Uma classe Invoice (Fatura) com uma propriedade de referência para Provider (Prestador de serviço):
Class Sample.Invoice Extends (%Persistent, %Populate)
{
Parameter DSTIME = "AUTO"
Property InvoiceNumber As %Integer(MINVAL = 100000) [ Required ]
Property ServiceDate As %Date(MINVAL = "+$h-730") [ Required ]
Index InvoiceNumber On InvoiceNumber
Property Provider As Sample.Provider [ Required ]
Index Provider On Provider [ Type = bitmap ]
ClassMethod Build(pCount As %Integer = 100020, pInit As %Boolean = 0) As %Status
{
#dim tSC As %Status=$$$OK
#dim eException As %Exception.AbstractException
try {
If pInit {
$$$THROWONERROR(tSC,##class(Sample.Provider).%KillExtent())
$$$THROWONERROR(tSC,##class(Sample.Invoice).%KillExtent())
}
$$$THROWONERROR(tSC,##class(Sample.Provider).Populate(100))
$$$THROWONERROR(tSC,##class(Sample.Invoice).Populate(pCount))
}
catch eException {
Set tSC=eException.AsStatus()
}
Quit tSC
}
}
E a classe Provider
Class Sample.Provider Extends (%Persistent, %Populate)
{
Property Name As %String [ Required ]
Property NPI As %Integer(MAXVAL = 9000000000, MINVAL = 100000000) [ Required ]
}
Se você chamar o método Build
da Sample.Invoice
, poderá consultar isso via SQL:
SELECT
InvoiceNumber,Provider->Name, Provider As ProviderId,ServiceDate
FROM Sample.Invoice
E verá algo como:
.png)
O ponto que este artigo discute é: como criar uma dimensão no Provider.
O que eu descobri que funciona bem é seguir esse padrão:
.png)
O que isso faz:
- Define o identificador único da dimensão como o
Id
do Provider
(que vem de Sample.Provider
).
Isso é importante porque é perfeitamente possível existir mais de um prestador com o nome SMITH, JOHN.
Ao definir o nível da dimensão na propriedade Provider, estamos dizendo para construir a tabela de dimensão baseada em um Provider único.
Se olharmos na tabela de dimensão gerada, veremos:
.png)
- Define uma propriedade para o nível que:
- Identifica a propriedade como
Provider.Name
- Define que o valor deve ser buscado em tempo de execução (
Get value at runtime = Yes
)
- Usa esse valor como nome dos membros da dimensão (
Use as member names = Yes
)
Isso tem como efeito colateral gerar na tabela de dimensão a seguinte declaração de propriedade:
Property Name As %String(COLLATION = "SQLUPPER(113)", MAXLEN = 2000)
[ Calculated,
SqlComputeCode = {Set {Name}=##class(Sample.BI.Cube.Invoice.Provider).%FetchName({Provider})}, SqlComputed ]
Com o método %FetchName
assim:
ClassMethod %FetchName(pKey As %String) As %String
{
Set tValue=pKey
&SQL(SELECT Name INTO :tValue FROM Sample.Provider WHERE %ID = :pKey)
Quit tValue
}
O que isso significa?
Quando os membros da dimensão são recuperados, o que será exibido é o nome do Provider e não o seu Id.
No Analyzer, podemos ver:
.png)
Por que isso é importante?
- Se o nome de um Provider for alterado na
Sample.Provider
, o cubo não precisa ser reconstruído ou sincronizado.
Se tivermos centenas de milhões de faturas e o nome de um único Provider mudar, não queremos reconstruir ou sincronizar todo o cubo de Invoice só por isso.
- A tabela de dimensão para Provider é baseada no
Provider.Id
, o que permite termos mais de um Provider com o mesmo nome na tabela de dimensões/cubo.
- Se, em vez de definir a propriedade do nível da dimensão dessa forma, definirmos como
Provider.Name
, o identificador único da dimensão passa a ser o nome, o que faz com que todos os Providers com o mesmo nome sejam agrupados sob o mesmo nome.
- E, se o nome de um Provider for alterado, somos obrigados a reconstruir o cubo.