Stack Overflow em Português Asked by INOVAARTE TECNOLOGIA on December 11, 2021
Então, estou com um dúvida, de como fazer uma consulta relacionadas entre 3 tabelas, sendo:
Tabela 1:
Nome: tb_os
Campos: id_os, id_cliente, valor_os
Tabela 2:
Nome: tb_clientes
Campos: id_cliente, endereco_cliente, tel_cliente
Tabela 3:
Nome: tb_status_os
Campos: id_status_os, id_os, status_os
A tabela de número 3, conterá pelo menos, 3 status amarrados a uma os, podendo ser: Aberto, Bancada, Liberado.
Qual a dúvida?
Preciso fazer uma consulta relacionando as 3 tabelas, porém, por conta da tabela tb_status_os, será retornado para cada consulta 3 linhas ou registros, o que preciso é agrupar em uma linha para cada O.S. (tabela 1), sendo que o resultado trazido da tabela 3, seja somente o último, sendo os status atual.
Tentei de inúmeras formas, segue a que cheguei mais próximo:
SELECT * FROM tb_os AS a
INNER JOIN tb_clientes AS b USING(id_os)
INNER JOIN tb_status_os AS c ON c.ids_os =
(
SELECT MAX(id_os) FROM tb_status_os
ORDER BY id_status_os DESC
)
GROUP BY a.id_os;
Retorna os registros agrupados corretamente, porém não retorna o último registro da tabela 3 ( ex.: Liberado), para cada 1 da tabela 1, retorna sempre o primeiro da tabela 3 (ex.: Aberto).
Poderiam me ajudar neste sentido?
Obrigado!
Boa parceiro, tem uma forma que bolei aqui para outras situações que deve servir para a sua :)
usa group_concat e poe um order by id desc, e usa substring_index para pegar o primeiro registro :D O pulo do gato é isso aqui: SUBSTRING_INDEX(GROUP_CONCAT(status_os order by id_status_os desc),',',1)
SELECT
a.*,
b.*,
SUBSTRING_INDEX(GROUP_CONCAT(status_os order by id_status_os desc),',',1) as status_atual
FROM tb_os AS a
INNER JOIN tb_clientes AS b USING(id_cliente)
INNER JOIN tb_status_os AS c ON USING(c.ids_os)
GROUP BY a.id_os;
Answered by Allan de Sá on December 11, 2021
Para solucionar esse tipo de problema de uma forma clara é necessário realizar o cruzamento com a tabela status_os duas vezes, porque?
Na primeira etapa você irá trazer todos os campos e trazer o MAX(cd_status) nessa etapa se você já trouxer a descrição o GROUP BY não irá funcionar:
SELECT a.id_os, a.id_cliente, cli.endereco_cliente, cli.tel_cliente,
a.valor_os, MAX(sta.id_status_os) AS cd_ultimo_status
FROM tb_os AS os
INNER JOIN tb_clientes AS cli
ON cli.id_cliente = os.id_cliente
INNER JOIN tb_status_os AS sta
ON sta.id_os = os.id_os
GROUP BY a.id_os, a.id_cliente, cli.endereco_cliente, cli.tel_cliente,
a.valor_os
Depois disso utilize o conceito de SUBSELECT (sub-consulta) para cruzar novamente com a tabela status_os somente para trazer a descrição da do status os:
SELECT res.* sta_desc.status_os
FROM (SELECT a.id_os, a.id_cliente, cli.endereco_cliente, cli.tel_cliente,
a.valor_os, MAX(sta.id_status_os) AS cd_ultimo_status
FROM tb_os AS os
INNER JOIN tb_clientes AS cli
ON cli.id_cliente = os.id_cliente
INNER JOIN tb_status_os AS sta
ON sta.id_os = os.id_os
GROUP BY a.id_os, a.id_cliente, cli.endereco_cliente, cli.tel_cliente,
a.valor_os
) res
INNER JOIN tb_status_os AS sta_desc
ON sta_desc.id_os = res.id_os
Simulei seu caso de maneira simples para você entender melhor o conceito:
SELECT tot.*, sta.status
FROM (
SELECT res.cd_os, MAX(cd_status) AS cd_status
FROM (SELECT 1 as cd_os, 1 AS cd_status, 'aberto' AS status
FROM DUAL
UNION ALL
SELECT 1 as cd_os, 2 AS cd_status, 'fechado' AS status
FROM DUAL ) res
GROUP BY res.cd_os) tot
INNER JOIN (SELECT 1 AS cd_status, 'aberto' AS status
FROM DUAL
UNION ALL
SELECT 2 AS cd_status, 'fechado' AS status
FROM DUAL) sta
ON sta.cd_status = tot.cd_status
No primeiro SELECT traz os dois valores, no segundo eu trago o MAX(cd_status), crio um SUBSELECT e depois cruzo com a tabela sta para trazer a descrição.
Obs.: Sempre que criar um SUBSELECT que precise cruzar a mesma tabela varias vezes, utilize apelidos diferentes para a "mesma" tabela para evitar conflitos.
Answered by Heitor Scalabrini on December 11, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP