Contagem condicional distinta em Relatórios de cristais
tenho um conjunto de dados como este:
ID PersonID ClassID Attended Converted
1 1 1 1 0
2 1 1 1 1
3 1 1 1 1
4 2 1 1 1
5 3 2 0 0
6 3 2 1 1
7 4 2 1 0
estou a construir um relatório que agrupa por ClassID (na verdade, estou a usar um parâmetro que permite agrupar em algumas cols diferentes, mas para simplificar, estou apenas a usar ClassID). Preciso de fazer um cálculo em cada rodapé de grupo. A fim de fazer o cálculo, eu preciso contar registros com PersonIDs únicos a esse grupo. A captura é, em um caso, esses registros também precisam corresponder a um critério. EG:
X = [Count of records where Converted = 1 with distinct PersonID]
Y = [Count of records where Attended = 1]
Então preciso de mostrar o quociente em percentagem:
(X/Y)*100
O relatório final seria parecido com isto.
ID PersonID Attended Converted
CLASS 1 GROUP
1 1 1 0
2 1 1 1
3 1 1 1
4 2 1 1
Percent= 2/4 = 50%
CLASS 2 GROUP
5 3 0 0
6 3 1 1
7 4 1 0
Percent= 1/2 = 50%
Notice in Class 1 Group, there are 3 records with Converted = 1 but ' X ' (the numerator) is equal to 2 because of the duplicate PersonID. Como posso calcular isso em Relatórios de Cristal?
1 answers
Eu tive que criar algumas fórmulas diferentes para fazer este trabalho com a ajuda de Este site .
Primeiro eu criei uma função chamada fNull como sugerido por esse site, que é apenas em branco. Estava a pensar se escrever null no seu lugar faria o trabalho, mas não o testava. Em seguida, eu criei fórmulas para avaliar se uma linha foi atendida e se uma linha foi convertida.
Ptrialattended:
//Allows row to be counted if AttendedTrial is true
if {ConversionData.AttendedTrial} = true
then CStr({ConversionData.PersonID})
else {@fNull}
Frialsconvertido:
//Allows row to be counted if Converted is true
if {ConversionData.Converted} = true
then CStr({ConversionData.PersonID})
else {@fNull}
Note que estou a voltar. o PersonID se atendido ou convertido é verdadeiro. Isto permite - me fazer a contagem distinta na próxima Fórmula (X da pergunta original):
FX:
DistinctCount({@fTrialsConverted}, {ConversionData.ClassID})
Isto é colocado no rodapé do grupo. Mais uma vez lembre-se @fTrialsConverted está retornando o PersonID dos testes convertidos (ou fNull, que não será contado). Uma coisa que eu não entendo é por que eu tive que incluir explicitamente o grupo por campo (ClassID) se ele está no rodapé do grupo, mas eu fiz ou ele iria contar o total em todos os grupos. A seguir, era só uma contagem directa.
FY:
//Counts the number of trials attended in the group
Count({@fTrialsAttended}, {ConversionData.ClassID})
E finalmente uma fórmula para calcular a percentagem:
if {@fY} = 0 then 0
else ({@fX}/{@fY})*100
A última coisa que vou partilhar é que também queria calcular o total em todos os grupos no rodapé do relatório. Contar o total Y foi fácil, é o mesmo que a fórmula fY exceto que você deixa de fora o grupo por parâmetro. Contar o total X era mais complicado porque eu preciso da soma do X de cada grupo e o cristal não pode somar outra soma. Por isso actualizei a minha fórmula X para mantenha também um total em execução numa variável global:
FX:
//Counts the number of converted trials in the group, distinct to a personID
whileprintingrecords;
Local NumberVar numConverted := DistinctCount({@fTrialsConverted}, {@fGroupBy});
global NumberVar rtConverted := rtConverted + numConverted; //Add to global running total
numConverted; //Return this value
Agora posso usar o rtConverted no rodapé para o cálculo. Isto levou a mais uma coisa desconcertante que me levou algumas horas a descobrir. rtConverted não estava sendo tratada como uma variável global, até que eu adicionados explicitamente a palavra-chave global, apesar de toda a documentação que eu vi dizendo global é o padrão. Assim que percebi isso, correu tudo bem.