Eu tenho uma tabela com estrutura e dados abaixo:
create table PTEST
(
col_name VARCHAR(50),
col_value VARCHAR(50)
)
COL_NAME COL_VALUE
-----------------------
first apple
first banana
second apple
second banana
second orange
third apple
third banana
**) o que eu quero fazer é dividir cada valor na col_value
coluna em duas categorias: [Comum,Not common]
**) Um valor é considerado 'Common'
se for exibido para cada col_name
, Então apple
é comum, pois é exibido para col_name = first and col_name = second and col_name = third
. O mesmo vale para banana
. Orange
não é comum, pois é apenas apareceu para col_name = second
.
A saída desejada seria assim:
COL_NAME COL_VALUE STATUS
---------------------------------
first apple Common
first banana Common
second banana Common
second apple Common
second orange Not common
third apple Common
third banana Common
A consulta que escrevi para isso é:
select col_name,
col_value,
case
when count_col = count_val then
'Common'
else
'Not common'
end STATUS
from (select t.col_name,
count(distinct t.col_name) over() count_col,
t.col_value,
count(t.col_value) over(partition by t.col_value) count_val
from PTEST t)
Eu queria saber se existem maneiras melhores de fazer isso.
desde já, obrigado
Duas maneiras de fazer isso seriam as seguintes (todo o código abaixo está disponível no violino para SQL Server - com planos - aqui - análise de desempenho no final:
Mesa:
Preencha-o:
Primeira forma:
Primeiro, queremos descobrir quantas vezes uma fruta aparece na tabela geral.
Resultado:
Você tem várias maneiras de encontrar o número de vezes que uma fruta apareceu menor que o máximo de cnt (3) que é sua definição de
common
- para que possamos ver de relance queorange
éuncommon
.Então, estou usando CTEs para fazer isso:
Resultado:
E voilà!
Para obter algo mais próximo da sua consulta original (não está funcionando - veja o violino), você pode fazer isso (novamente, no violino):
Mesmo resultado.
Segunda maneira:
Você também pode fazer isso se estiver executando uma versão antiga (ou versões recentes do MySQL :-) ) que não possui funções de janela da seguinte forma:
Resultado:
E voilà bis!!
Você pergunta na pergunta:
Então, adicionei à parte inferior do violino as seguintes linhas (documentadas aqui ):
e finalmente
Parece impossível obter temporizações muito refinadas do db<>fiddle, mas os planos são interessantes.
A consulta da função da janela produz o seguinte plano (23 linhas):
E o "antiquado" produz esse plano de 11 linhas:
Dado que não temos timings explícitos - e de qualquer forma, testar com uma quantidade tão pequena de dados é mais ou menos sem sentido, recomendo que você teste todas e quaisquer soluções propostas em suas próprias tabelas e hardware ... polegar, quanto mais longos os planos, mais lentos eles são e as funções da janela incorrem em uma sobrecarga! A partir daqui :
No futuro, ao fazer perguntas dessa natureza, você poderia fornecer o violino - ele fornece uma única fonte de verdade e elimina a duplicação de esforços - ajude-nos a ajudá-lo! :-)