No post anterior no assunto DAX, vimos que podemos utilizar a função values para retornar valores lineares mesmo ela sendo uma função tabular. Essa situação é possível pois um recurso dentro do engine  do PBI permite que tal tipo (tabular), retorne um valor linear caso trate de apenas uma coluna com uma única linha.

Embora este seja um recurso válido de se aplicar, existem funções que são desenhadas especialmente para esse tipo de situação, que são as funções hasonevalue e selectedvalue

Para exemplificar, veja esta simples medida criada utilizando a função values filtrando as marcas por categoria de produtos. Perceba a seguinte peculiaridade:

mrNumOfBrands =
VAR BND =
    COUNTROWS (
        VALUES ( 'Product'[Brand] )
    )
RETURN
    BND

Como esta medida atende ao requisito especial do engine do PBI, temos o resultado desejado. Uma outra situação que garante a certeza de atender o requisito seria colocar aquela mesma medida dentro de um IF e igualar a um, veja:

Primeiro o código utilizado na criação:

mrNumofBrandswIF =
VAR IFCNT =
    IF (
        COUNTROWS (
            VALUES ( 'Product'[Brand] )
        ) = 1,
        VALUES ( 'Product'[Brand] )
    )
RETURN
    IFCNT

Veja no gráfico abaixo que quando há mais de um valor, quebrando a lógica do IF, o nome da marca não é exibido.

Podemos notar que mesmo utilizando IF a consistência do resultado não é das melhores. Para solucionar esse problema em questão, vamos analisar as duas funções que dão origem ao post.

HASONEVALUE

Esta função tem um trabalho mais simples dentro da expressão: checar se há apenas um valor dentro da coluna informada. Como a função true/false ela não faz muito sentido fora de um teste lógico, veja as duas medidas aplicadas no gráfico.

mrHasOneBrand =
VAR HSOV =
    IF (
        HASONEVALUE ( 'Product'[Brand] ),
        VALUES ( 'Product'[Brand] )
    )
RETURN
    HSOV
        
------------------
mrHasTrueFalse =
VAR HSTF =
    HASONEVALUE ( 'Product'[Brand] )
RETURN
    HSTF

Como dito, faz mais sentido aplicar em um teste lógico do que de forma aleatória.

SELECTEDVALUE

Com a função selectedvalue a situação muda um pouco de figura. Nesta função temos a opção de adicionar um ‘tratamento’ caso o valor seja maior do que um, que é exatamente o resultado que buscamos.

mrSelVLBrand =
VAR SLTV =
    SELECTEDVALUE (
        'Product'[Brand],
        "Mais de um valor"
    )
RETURN
    SLTV

Agora temos um resultado mais apresentável, incluindo uma mensagem de saída caso não satisfaça a condição determinada.

É importante destacar que a função não realiza nenhuma outra operação se não buscar os valores únicos. Então, qualquer valor no argumento é puramente um valor de preenchimento e não de resultado de uma expressão. Deixe isso claro aos que forem analisar o dashboard.

Assim como a função values, ela não funciona em um row context.

Uma boa aplicação para uma medida com esta função é dentro de um gráfico de tabela. Quando aplicamos neste, diferente do que ocorre quando utilizamos no gráfico de matriz, a medida não exibe linhas me brancos com produtos que não foram vendidos, por exemplo.

Sublinhado em azul no gráfico de matriz, as linhas em branco representando produtos sem vendas.

CONCLUSÃO

Este post foi para reforçar e relembrar como é possível que funções de tabela retornem resultados como linhas.

Abordei três formas diferentes cada uma com sua particularidade, sendo o mais indicado utilizar a função selectedvalue.

Além de deixar o código mais clean, é possível passar um valor de retorno caso a condição não se satisfaça, o que melhora muito a legibilidade do código.

Lembre que estas funções são melhores quando em filter context e que para um row context utilize a função related.

Espero que tenham gostado, Deus os abençoe!

Saúde!