Montar SQL no PostgreSQL

Olá Gurizada, To batendo a cabeça aqui para retornar o seguinte resultado em SQL…

Preciso mostrar a porcentagem de Produtos Ok durante o dia…

Alguns Produtos estão duplicados (serial+status) e não podem entrar no resultado
tipo assim:

SELECT distinct
serial,
cod_status – 0 = ok e 1 produto com defeito.
[…]

A Dúvida é: Como retornar, a soma dos status = 0 e status = 1, estes estando sem os duplicados

Até agora fiz este:
SELECT
extract(day from datah) as dia,
cod_prod,
count(cod_prod)
FROM
tb_registro
WHERE
cod_status = 0
and
extract(day from datah) = 7
AND
cod_prod = '000092’
GROUP BY
extract(day from datah),cod_prod
ORDER BY dia

Mas não sei escluir os duplicados.

Depois de resolvido isto, estava pensando em fazer uma função com 2 SELECT para fazer a comparação dos ok, existe maneira mais simples?

Abraços…


select 
  sum(case when status = 0 then 1 else 0 end) as qt_status_0,
  sum(status)
from produtos p
left join (
  select serial, status
  from produtos
  group by serial, status
  having count(*)>1
) d 
on  p.serial = d.serial
and p.status = d.status
where d.serial is null
  and d.status = null

Não me fiz entender muito bem, vamos lá…

Esta função Retorna uma linha com o número 25

SELECT 
 count(cod_prod)
FROM 
  tb_registro
WHERE 
  cod_status = 0 
  and
  extract(day from  datah) = 7
  AND
  cod_prod = '000092'
GROUP BY 
  cod_prod

E esta aqui, retorna 24 registros, omitindo um registro duplicado:


SELECT distinct
 serial,
 cod_status
FROM 
  tb_registro
WHERE 
  cod_prod = '000092'
AND extract(day from  datah) = 7
AND cod_status = 0

Como fazer para esta ultima, retornar apenas uma linha? com o numero 24?
não estou encontrando um meio termo…
valew

nesse seu último post, vc quer que a consulta retorne o número 24? Visto que tem uma linha duplicada?

Nesse caso é mais fácil, rsrs.

SELECT count(DISTINCT cod_prod) FROM tb_registro WHERE cod_status = 0 and extract(day from datah) = 7 AND cod_prod = '000092'

Obs: acho que na sua primeira consulta sobrou um group by.

Mais ou menos isso…

só que imagine uma chave primária composta por

cod_prod status
’000092’ 0
’000092’ 0 <<duplicado
’000092’ 1

SELECT count(distinct serial, cod_status) […]

Somar o status =0, ignorando os duplicados (cod_prod + status)

Agora meiio que dominei… ficou legal, como eu queria…

SELECT distinct
cod_prod,
count(cod_prod),
 count(distinct serial) as contS,
 cod_status
FROM 
  tb_registro
WHERE 
 --cod_status = 0   and
  extract(day from  datah) = 21
  AND cod_prod = '000367'
GROUP BY 
  cod_prod
  ,cod_status

fazendo um coment no cod_status = 0, retorna duas linhas:
cod_prod;count;counts;cod_status
"000367"; 249; 247; 0
"000367"; 6; 6; 1

Teria como “contar” o cod_status=1 e colocar na mesma linha para retornar apenas um registro?
ex:
cod_prod;count;counts;cont(cod_status=1)
“000367”; 249; 247; 6

Valew

não entendi bem seu problema, você quer contar quantos cod_prod distintos tem?

Olá,
Sim sim, inicialmente não era isso, agora eu matei a charada aqui com o “cliente”, já está resolvido

Mas precisava agora montar um gráfico com um único resultado com a % de Produtos bons.
ou Seja queria que retornasse, como no exemplo, só um resultado… a diferença entre status Zero, e Status Um, do Procuto X.

agora tá assim: 2 linhas:

prod           cont          status
"000367";      900;       0
"000367";       10;       1 

//poderia ser assim:

prod           porcent
"000367";       90%;

Entendeu a dif?
inves de duas linhas, um cálculo que retorna uma linha com o resultado entre as duas…
não tem como fazer isso via SQL puro correto? só com uma função que pegue estas duas linhas e calcule?

Valew

deixa eu ver se entendi, você quer algo assim:

SELECT
  cod_prod,
  SUM(CASE WHEN cod_status = 0 THEN 1 ELSE 0 END)/
    SUM(1) as perc_bons
FROM tb_registro
GROUP BY cod_prod

não funcionou
o resultado foi ZERO:

“011036”; 0

Qual resultado traz para:

SELECT  
  cod_prod,  
  SUM(CASE WHEN cod_status = 0 THEN 1 ELSE 0 END) as qt_bons,
  SUM(1) as qt_total,
  SUM(CASE WHEN cod_status = 0 THEN 1 ELSE 0 END)/  
    SUM(1) as perc_bons  
FROM tb_registro  
GROUP BY cod_prod  

hum,
cod_prod;qt_bons;qt_total;perc_bons
"011036";624;640;0

Me explica esta condição:
(CASE WHEN cod_status = 0 THEN 1 ELSE 0 END)

se for 0 é 1 se for 1 é zero? isto é para fazer o calculo da divisão? soma todos os zeros… ah… não pode se fazer isso com o COUNT? não tem como escolher dái só os zeros verdade verdade…

para contar somente os 0 com o count, você precisaria fazer os outros valores retornar null, algo assim:

COUNT(CASE WHEN cod_status = 0 THEN cod_status ELSE NULL END)

Provavelmente o seu cliente SQL está cortando casas decimais, dá uma verificada nisso.

Outra forma, seria multiplicar por 100 conforme a consulta:

SELECT cod_prod, SUM(CASE WHEN cod_status = 0 THEN 1 ELSE 0 END) as qt_bons, SUM(1) as qt_total, SUM(CASE WHEN cod_status = 0 THEN 1 ELSE 0 END)*100/ SUM(1) as perc_bons FROM tb_registro GROUP BY cod_prod

Perfeito, Olha funcionou, mostrou o resultado agora,
sim eu to no Query do Postgre, ele tá retornando todas as colunas como bigint, estranho…
Mas na aplicação talvez funcione…

Valew Achei que não daria pra fazer em uma unica linha.
Obrigado Abração!