SQL - Retornar a linha com o menor valor de uma coluna, entre várias colunas com valores diferentes.

SQL

PHP

Banco de Dados

25/10/2021

Olá,

Preciso de ajuda para elaborar uma query em um banco de dados SQL, onde a mesma me retorne o produto que tem o menor valor entre todos, sendo que cada produto possui 5 valores distintos ou iguais, sendo que a query não pode trazer valores null, ou zero.
Exemplo:

Tenho os seguintes produtos e valores:

PRODUTO A -> ID = '' 1 '' VALORES => 4, 2, 9 , 0 ,7
PRODUTO B -> ID = '' 2 '' VALORES => 0, 0, 3, 1, 7
PRODUTO C-> ID = '' 3 '' VALORES => 9, 0, 4 , 5, 2

No caso gostaria que a query me retornasse a linha com ID = '' 2 ''
pois ignoraria os zeros e nulls, e o menor preço entre todas as linha seria o 1.

Alguém pode me ajudar ? Desde já agradeço a ajuda !!!
Bruno Murad

Bruno Murad

Curtidas 0

Respostas

Emerson Nascimento

Emerson Nascimento

25/10/2021

VALORES é uma coluna ou são várias colunas?
Quanto mais informações puder passar, mais fácil ter uma resposta pertinente.
Lembre-se: não conhecemos a estrutura das tuas tabelas; não temos acesso ao teu banco de dados.
GOSTEI 0
Bruno Murad

Bruno Murad

25/10/2021

VALORES é uma coluna ou são várias colunas?
Quanto mais informações puder passar, mais fácil ter uma resposta pertinente.
Lembre-se: não conhecemos a estrutura das tuas tabelas; não temos acesso ao teu banco de dados.


valores, são várias colunas cada uma com um valor dessa forma:

+----------+----------+----------+----------+---------+---------+---------+
| id | Prod | Val1 | Val2 | Val3 | Val4 | Val5 |
+----------+----------+-----------+----------+--------+---------+---------+
| 1 | A | 4 | 2 | 9 | 0 | 7 |
+----------+----------+-----------+----------+--------+---------+---------+
| 2 | B | 0 | 0 | 3 | 1 | 7 |
+----------+----------+-----------+----------+--------+---------+---------+
| 3 | C | 9 | 0 | 4 | 5 | 2 |
+----------+----------+-----------+----------+--------+---------+---------+

Preciso de uma query que me retorne o ID 2, pois ele tem o menor valor entre todos os produtos, descartando os campos com valor zero.
Acho que assim ficou melhor de entender...


GOSTEI 0
Emerson Nascimento

Emerson Nascimento

25/10/2021


qual o banco de dados utilizado ?
sql server
firebird
mysql
postgre
oracle
GOSTEI 0
Bruno Murad

Bruno Murad

25/10/2021


qual o banco de dados utilizado ?
sql server
firebird
mysql
postgre
oracle


Desculpe a falta de atenção... estou trabalhando com mysql e php.
GOSTEI 0
Emerson Nascimento

Emerson Nascimento

25/10/2021

segundo minhas pesquisas o MySQL não tem função própria pra isso, então tem que ser na 'criatividade'.
+----+------+------+------+------+------+------+
| id | Prod | Val1 | Val2 | Val3 | Val4 | Val5 |
+----+------+------+------+------+------+------+
| 1  | A    | 4    | 2    | 9    | 0    | 7    |
+----+------+------+------+------+------+------+
| 2  | B    | 0    | 0    | 3    | 1    | 7    |
+----+------+------+------+------+------+------+
| 3  | C    | 9    | 0    | 4    | 5    | 2    |
+----+------+------+------+------+------+------+
com base na tabela acima, a primeira coisa a fazer é transformar as colunas em linhas.
a instrução abaixo não é a melhor (se você acrescentar a coluna Val6 terá que fazer manutenção no código) mas acredito que seja a única possível até o momento.
SELECT id , prod, 'Val1' CAMPO, Val1 CONTEUDO FROM tabela WHERE coalesce(Val1,0) > 0 UNION ALL
SELECT id , prod, 'Val2' CAMPO, Val2 CONTEUDO FROM tabela WHERE coalesce(Val2,0) > 0 UNION ALL
SELECT id , prod, 'Val3' CAMPO, Val3 CONTEUDO FROM tabela WHERE coalesce(Val3,0) > 0 UNION ALL
SELECT id , prod, 'Val4' CAMPO, Val4 CONTEUDO FROM tabela WHERE coalesce(Val4,0) > 0 UNION ALL
SELECT id , prod, 'Val5' CAMPO, Val5 CONTEUDO FROM tabela WHERE coalesce(Val5,0) > 0
o resultado será:
+----+------+-------+----------+
| id | Prod | CAMPO | CONTEUDO |
+----+------+-------+----------+
| 1  | A    | Val1  | 4        |
+----+------+-------+----------+
| 1  | A    | Val2  | 2        |
+----+------+-------+----------+
| 1  | A    | Val3  | 9        |
+----+------+-------+----------+
| 1  | A    | Val5  | 7        |
+----+------+-------+----------+
| 2  | B    | Val3  | 3        |
+----+------+-------+----------+
| 2  | B    | Val4  | 1        |
+----+------+-------+----------+
| 2  | B    | Val5  | 7        |
+----+------+-------+----------+
| 3  | C    | Val1  | 9        |
+----+------+-------+----------+
| 3  | C    | Val3  | 4        |
+----+------+-------+----------+
| 3  | C    | Val4  | 5        |
+----+------+-------+----------+
| 3  | C    | Val5  | 2        |
+----+------+-------+----------+
sabendo que os dados estão corretos, basta usar a mesma consulta executada anteriormente, porém agora agrupada:
SELECT id, prod, min(CONTEUDO) VALOR FROM
(
	SELECT id , prod, 'Val1' CAMPO, Val1 CONTEUDO FROM tabela WHERE coalesce(Val1,0) > 0 UNION ALL
	SELECT id , prod, 'Val2' CAMPO, Val2 CONTEUDO FROM tabela WHERE coalesce(Val2,0) > 0 UNION ALL
	SELECT id , prod, 'Val3' CAMPO, Val3 CONTEUDO FROM tabela WHERE coalesce(Val3,0) > 0 UNION ALL
	SELECT id , prod, 'Val4' CAMPO, Val4 CONTEUDO FROM tabela WHERE coalesce(Val4,0) > 0 UNION ALL
	SELECT id , prod, 'Val5' CAMPO, Val5 CONTEUDO FROM tabela WHERE coalesce(Val5,0) > 0
) TAB
GROUP BY id, prod
o resultado será:
+----+------+-------+-------+
| id | Prod | CAMPO | VALOR |
+----+------+-------+-------+
| 1  | A    | Val2  | 2     |
+----+------+-------+-------+
| 2  | B    | Val4  | 1     |
+----+------+-------+-------+
| 3  | C    | Val5  | 2     |
+----+------+-------+-------+
com esse resultado em mãos, podemos obter o id do menor valor utilizando a cláusula LIMIT e a cláusula ORDER BY:
SELECT id, prod, min(CONTEUDO) VALOR FROM
(
	SELECT id , prod, 'Val1' CAMPO, Val1 CONTEUDO FROM tabela WHERE coalesce(Val1,0) > 0 UNION ALL
	SELECT id , prod, 'Val2' CAMPO, Val2 CONTEUDO FROM tabela WHERE coalesce(Val2,0) > 0 UNION ALL
	SELECT id , prod, 'Val3' CAMPO, Val3 CONTEUDO FROM tabela WHERE coalesce(Val3,0) > 0 UNION ALL
	SELECT id , prod, 'Val4' CAMPO, Val4 CONTEUDO FROM tabela WHERE coalesce(Val4,0) > 0 UNION ALL
	SELECT id , prod, 'Val5' CAMPO, Val5 CONTEUDO FROM tabela WHERE coalesce(Val5,0) > 0
) TAB
GROUP BY id, prod
ORDER BY VALOR -- não sei se o MySQL trabalha com o alias do campo. Se não funcionar tente com o índice do campo (3) ou com a função de agregação (min(CONTEUDO))
LIMIT 1
o resultado será:
+----+------+-------+
| id | Prod | VALOR |
+----+------+-------+
| 2  | B    | 1     |
+----+------+-------+



GOSTEI 0
Bruno Murad

Bruno Murad

25/10/2021

segundo minhas pesquisas o MySQL não tem função própria pra isso, então tem que ser na 'criatividade'.
+----+------+------+------+------+------+------+
| id | Prod | Val1 | Val2 | Val3 | Val4 | Val5 |
+----+------+------+------+------+------+------+
| 1  | A    | 4    | 2    | 9    | 0    | 7    |
+----+------+------+------+------+------+------+
| 2  | B    | 0    | 0    | 3    | 1    | 7    |
+----+------+------+------+------+------+------+
| 3  | C    | 9    | 0    | 4    | 5    | 2    |
+----+------+------+------+------+------+------+
com base na tabela acima, a primeira coisa a fazer é transformar as colunas em linhas.
a instrução abaixo não é a melhor (se você acrescentar a coluna Val6 terá que fazer manutenção no código) mas acredito que seja a única possível até o momento.
SELECT id , prod, 'Val1' CAMPO, Val1 CONTEUDO FROM tabela WHERE coalesce(Val1,0) > 0 UNION ALL
SELECT id , prod, 'Val2' CAMPO, Val2 CONTEUDO FROM tabela WHERE coalesce(Val2,0) > 0 UNION ALL
SELECT id , prod, 'Val3' CAMPO, Val3 CONTEUDO FROM tabela WHERE coalesce(Val3,0) > 0 UNION ALL
SELECT id , prod, 'Val4' CAMPO, Val4 CONTEUDO FROM tabela WHERE coalesce(Val4,0) > 0 UNION ALL
SELECT id , prod, 'Val5' CAMPO, Val5 CONTEUDO FROM tabela WHERE coalesce(Val5,0) > 0
o resultado será:
+----+------+-------+----------+
| id | Prod | CAMPO | CONTEUDO |
+----+------+-------+----------+
| 1  | A    | Val1  | 4        |
+----+------+-------+----------+
| 1  | A    | Val2  | 2        |
+----+------+-------+----------+
| 1  | A    | Val3  | 9        |
+----+------+-------+----------+
| 1  | A    | Val5  | 7        |
+----+------+-------+----------+
| 2  | B    | Val3  | 3        |
+----+------+-------+----------+
| 2  | B    | Val4  | 1        |
+----+------+-------+----------+
| 2  | B    | Val5  | 7        |
+----+------+-------+----------+
| 3  | C    | Val1  | 9        |
+----+------+-------+----------+
| 3  | C    | Val3  | 4        |
+----+------+-------+----------+
| 3  | C    | Val4  | 5        |
+----+------+-------+----------+
| 3  | C    | Val5  | 2        |
+----+------+-------+----------+
sabendo que os dados estão corretos, basta usar a mesma consulta executada anteriormente, porém agora agrupada:
SELECT id, prod, min(CONTEUDO) VALOR FROM
(
	SELECT id , prod, 'Val1' CAMPO, Val1 CONTEUDO FROM tabela WHERE coalesce(Val1,0) > 0 UNION ALL
	SELECT id , prod, 'Val2' CAMPO, Val2 CONTEUDO FROM tabela WHERE coalesce(Val2,0) > 0 UNION ALL
	SELECT id , prod, 'Val3' CAMPO, Val3 CONTEUDO FROM tabela WHERE coalesce(Val3,0) > 0 UNION ALL
	SELECT id , prod, 'Val4' CAMPO, Val4 CONTEUDO FROM tabela WHERE coalesce(Val4,0) > 0 UNION ALL
	SELECT id , prod, 'Val5' CAMPO, Val5 CONTEUDO FROM tabela WHERE coalesce(Val5,0) > 0
) TAB
GROUP BY id, prod
o resultado será:
+----+------+-------+-------+
| id | Prod | CAMPO | VALOR |
+----+------+-------+-------+
| 1  | A    | Val2  | 2     |
+----+------+-------+-------+
| 2  | B    | Val4  | 1     |
+----+------+-------+-------+
| 3  | C    | Val5  | 2     |
+----+------+-------+-------+
com esse resultado em mãos, podemos obter o id do menor valor utilizando a cláusula LIMIT e a cláusula ORDER BY:
SELECT id, prod, min(CONTEUDO) VALOR FROM
(
	SELECT id , prod, 'Val1' CAMPO, Val1 CONTEUDO FROM tabela WHERE coalesce(Val1,0) > 0 UNION ALL
	SELECT id , prod, 'Val2' CAMPO, Val2 CONTEUDO FROM tabela WHERE coalesce(Val2,0) > 0 UNION ALL
	SELECT id , prod, 'Val3' CAMPO, Val3 CONTEUDO FROM tabela WHERE coalesce(Val3,0) > 0 UNION ALL
	SELECT id , prod, 'Val4' CAMPO, Val4 CONTEUDO FROM tabela WHERE coalesce(Val4,0) > 0 UNION ALL
	SELECT id , prod, 'Val5' CAMPO, Val5 CONTEUDO FROM tabela WHERE coalesce(Val5,0) > 0
) TAB
GROUP BY id, prod
ORDER BY VALOR -- não sei se o MySQL trabalha com o alias do campo. Se não funcionar tente com o índice do campo (3) ou com a função de agregação (min(CONTEUDO))
LIMIT 1
o resultado será:
+----+------+-------+
| id | Prod | VALOR |
+----+------+-------+
| 2  | B    | 1     |
+----+------+-------+





Perfeito !!! Funcionou corretamente !!!
Obrigado pela ajuda e pela excelente explicação passo a passo do processo. Com ele consegui resolver a situação e de quebra ainda adquiri esse excelente conhecimento que me passou, mais uma vez muito obrigado pela aula !!!
GOSTEI 0
POSTAR