SELECT com UNION e com parâmetros ou não [RESOLVIDO]

16 respostas
P

Pessoal, tenho uma funcionalidade (que está ok) que recebe ou não parâmetro de uma lista… só que vou ter que aumentar esse SELECT, colocando um UNION, ou seja, agora terá que repetir as condições… só que não sei como gravar essas condições para apenas adicionar…

Consulta SQL fixa (ONDE EU QUERO E PRECISO ADICIONAR UM UNION):

private static final String SQL_ATUAL = " SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia, "
			+ "(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora, "
			+ "(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha, "
			+ "COUNT(*) as Quantidade "
			+ "FROM SIMCard LEFT JOIN SIMCardDispositivo ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero "
			+ "LEFT JOIN Dispositivo ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero "
			+ "INNER JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha "
			+ "LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento) "
			+ "WHERE (";

segue minha classe:

StringBuilder sql = new StringBuilder("");

	public List<ConsultaGerarRelatorio> listaTecnologias(
			List<Integer> tecnologias, List<Integer> operadoras,
			List<Integer> status) {
		Connection conn = null;
		PreparedStatement ps = null;
		List<ConsultaGerarRelatorio> listaConsultaGeraRelatorio = new ArrayList<ConsultaGerarRelatorio>();

		if (!tecnologias.isEmpty()) {
			sql.append(" Dispositivo.CodigoTecnologia IN (");
			for (Iterator<Integer> it = tecnologias.iterator(); it.hasNext();) {
				it.next();
				sql.append("?");
				if (it.hasNext()) {
					sql.append(",");
				}
			}
			sql.append(")");
		}

		if (!operadoras.isEmpty()) {

			if (!tecnologias.isEmpty()) {
				sql.append(" AND SIMCard.CodigoOperadora IN (");
				for (Iterator<Integer> it = operadoras.iterator(); it.hasNext();) {
					it.next();
					sql.append("?");
					if (it.hasNext()) {
						sql.append(",");
					}
				}
				sql.append(")");

			} else {

				sql.append(" SIMCard.CodigoOperadora IN (");
				for (Iterator<Integer> it = operadoras.iterator(); it.hasNext();) {
					it.next();
					sql.append("?");
					if (it.hasNext()) {
						sql.append(",");
					}
				}
				sql.append(")");
			}
		}

		if (!status.isEmpty()) {

			if (!tecnologias.isEmpty() || !operadoras.isEmpty()) {
				sql.append(" AND Linha.CodigoStatusLinha IN (");
				for (Iterator<Integer> it = status.iterator(); it.hasNext();) {
					it.next();
					sql.append("?");
					if (it.hasNext()) {
						sql.append(",");
					}
				}
				sql.append(")");
			} else {

				sql.append(" Linha.CodigoStatusLinha IN (");
				for (Iterator<Integer> it = status.iterator(); it.hasNext();) {
					it.next();
					sql.append("?");
					if (it.hasNext()) {
						sql.append(",");
					}
				}
				sql.append(")");
			}
		}

		sql.append(" )");

		try {

			conn = ConnectionManager.obterConexao();
			ps = conn.prepareStatement(SQL_ATUAL + sql.toString() + GROUP);
			int indicePs = 1;

			if (!tecnologias.isEmpty()) {
				for (Integer i : tecnologias) {
					ps.setInt(indicePs++, i);
				}
			}
			if (!operadoras.isEmpty()) {
				for (Integer i : operadoras) {
					ps.setInt(indicePs++, i);
				}
			}
			if (!status.isEmpty()) {
				for (Integer i : status) {
					ps.setInt(indicePs++, i);
				}
			}

			System.out.println("Consulta: " + SQL_ATUAL + sql.toString()
					+ GROUP);

			ResultSet rs = ps.executeQuery();

			while (rs.next()) {

				ConsultaGerarRelatorio listaRelatorio = new ConsultaGerarRelatorio(
						rs.getString("CodTecnologia"),
						rs.getString("Operadora"), rs.getString("StatusLinha"),
						rs.getString("Quantidade"));

				listaConsultaGeraRelatorio.add(listaRelatorio);

				System.out.println(rs.getString("CodTecnologia") + " "
						+ rs.getString("Operadora") + " "
						+ rs.getString("StatusLinha") + " "
						+ rs.getString("Quantidade"));

			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			ConnectionManager.fecharConexao(conn, null, ps);
		}

		return listaConsultaGeraRelatorio;

	}

16 Respostas

Aleksandro

Cara não entendi sua dúvida …

O union deve ser usado com a mesma quantidade de colunas contido em outra query … por exemplo :

SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2

Senão houver esta condição não funcionará, portanto penso eu … você pode fazer assim …

faz a montagem desta query e junta(UNION) com a sua SQL_ATUAL… ou você já viu a possibilidade de mexer na sua SQL_ATUAL adicionando a necessidade do negócio , sem precisar incluir o UNION , por exemplo ?

P

É o seguinte...

Eu tenho esse SELECT que adicionei aqui.... e nele vai virar um UNION, onde vou adicionar nova consulta...

A minha dúvida está em, como vou adicionar as condições iguais para ele... pois eu monto as condições de maneira dinâmica, assim, não sei como adicionar as condições.

O select ficaria assim:

-- Consulta coletiva exeplo dos campos para juntar com a consulta unitária histórico
SELECT DISTINCT (Dispositivo.Numero) AS Dispositivo, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoAPNConfigurada) AS APNConfigurada, 
(SIMCard.Numero) AS SIMCard, 
(Linha.Numero) AS Linha, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoAPNProvisionada) AS APNProvisionada, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoStatusSIMCard) AS StatusSIMCard, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Processamento.CodigoFonteDados) AS Fonte, 
(Processamento.dataProcessamento) AS DtAlteracao, 
(Dispositivo.IMEI) AS IMEI, 
(SIMCard.IMSI) AS IMSI, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha, 
(SIMCard.ConsumoDados) AS ConsDados, 
(SIMCard.MatriculaAlteracao) AS Matricula 
FROM Dispositivo LEFT JOIN SimcardDispositivo ON SimcardDispositivo.Dispositivo_numero = Dispositivo.Numero 
LEFT JOIN SIMCard ON SIMCard.Numero = SIMCardDispositivo.SIMCard_Numero 
LEFT JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha 
LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento) 
WHERE Dispositivo.Numero = 'aaaaaa'

UNION ALL
-- Unitária
SELECT DISTINCT (Historico.NumeroDispositivo) AS Dispositivo,
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoTecnologia) AS CodTecnologia,
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoAPNConfigurada) AS APNConfigurada, 
(Historico.NumeroSIMCard) AS SIMCard, 
(Historico.NumeroLinha) AS Linha, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoOperadora) AS Operadora, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoAPNProvisionada) AS APNProvisionada, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusSIMCard) AS StatusSIMCard, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Processamento.CodigoFonteDados) AS Fonte, 
(Processamento.dataProcessamento) AS DtAlteracao, 
(Historico.IMEI) AS IMEI, 
(Historico.IMSI) AS IMSI, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusLinha) AS StatusLinha, 
(Historico.ConsumoDados) AS ConsDados, 
(Processamento.MatriculaCadastro) AS Matricula 
FROM Historico, Processamento 
WHERE Historico.CodigoProcessamento = Processamento.Codigo 
AND Historico.NumeroDispositivo = 'aaaaaa'

as condições where serão as mesmas... mas na hora que eu to montando, com o índice em cada um, não sei continuar, para preecher igual ao primeiro... fui mais claro? ou ainda ta confuso?

P

Consegui ajuntar colocando os parâmetros.. bastou eu repetir o processo de preenchimento.. sei que talvez não seja a melhor maneira mais funciona

só que to apanhando para agurpar... fica dando erro:

Consulta:  SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoTecnologia) AS CodTecnologia, (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoOperadora) AS Operadora, (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusLinha) AS StatusLinha, COUNT(*) as Quantidade FROM Historico WHERE ( Historico.CodigoOperadora IN (?) AND Historico.StatusLinha IN (?) ) UNION ALL  SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia, (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora, (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha, COUNT(*) as Quantidade FROM SIMCard LEFT JOIN SIMCardDispositivo ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero LEFT JOIN Dispositivo ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero INNER JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento) WHERE ( SIMCard.CodigoOperadora IN (?) AND Linha.CodigoStatusLinha IN (?) ) GROUP BY CodTecnologia, Operadora, StatusLinha ORDER BY CodTecnologia, Operadora, StatusLinha 
org.postgresql.util.PSQLException: ERRO: subconsulta utiliza coluna desagrupada "historico.codigotecnologia" na consulta externa
  Posição: 66
Aleksandro

Neste caso do erro, o ideal é você pegar a query que esta sendo gerada no java e rodar no banco diretamente , me parece que uma coluna não esta sendo agrupada , faça isto e veja o que retorna …

P

Aleksandro blz?

Da o mesmo erro…

ERRO: subconsulta utiliza coluna desagrupada “historico.codigotecnologia” na consulta externa
SQL state: 42803
Character: 65

Aleksandro

Pacato:
Aleksandro blz?

Da o mesmo erro…

ERRO: subconsulta utiliza coluna desagrupada “historico.codigotecnologia” na consulta externa
SQL state: 42803
Character: 65

Mande a query que você executou no BD …? para eu dar uma olhada …

P

Segue consulta:

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoTecnologia) AS CodTecnologia, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoOperadora) AS Operadora, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusLinha) AS StatusLinha, 
COUNT(*) as Quantidade 
FROM Historico 
WHERE ( Historico.StatusLinha IN (16) ) 
UNION ALL  

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora, 
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha, 
COUNT(*) as Quantidade 
FROM SIMCard LEFT JOIN SIMCardDispositivo ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero LEFT JOIN Dispositivo ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero INNER JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento) 
WHERE ( Linha.CodigoStatusLinha IN (16) ) 

GROUP BY CodTecnologia, Operadora, StatusLinha ORDER BY CodTecnologia, Operadora, StatusLinha

valeu

Aleksandro

tenta assim :

select CodTecnologia, Operadora, StatusLinha FROM (

SELECT
  (SELECT Dominio.Nome
  FROM Dominio
  WHERE Dominio.Codigo = Historico.CodigoTecnologia
  ) AS CodTecnologia,
  (SELECT Dominio.Nome
  FROM Dominio
  WHERE Dominio.Codigo = Historico.CodigoOperadora
  ) AS Operadora,
  (SELECT Dominio.Nome
  FROM Dominio
  WHERE Dominio.Codigo = Historico.StatusLinha
  )        AS StatusLinha,
  COUNT(*) AS Quantidade
FROM Historico
WHERE ( Historico.StatusLinha IN (16) )
UNION ALL
SELECT
  (SELECT Dominio.Nome
  FROM Dominio
  WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia
  ) AS CodTecnologia,
  (SELECT Dominio.Nome
  FROM Dominio
  WHERE Dominio.Codigo = SIMCard.CodigoOperadora
  ) AS Operadora,
  (SELECT Dominio.Nome
  FROM Dominio
  WHERE Dominio.Codigo = Linha.CodigoStatusLinha
  )        AS StatusLinha,
  COUNT(*) AS Quantidade
FROM SIMCard
LEFT JOIN SIMCardDispositivo
ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero
LEFT JOIN Dispositivo
ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero
INNER JOIN Linha
ON Linha.Numero = SIMCard.NumeroLinha
LEFT JOIN Processamento
ON (Processamento.Codigo         = SIMCard.CodigoProcessamento
OR PROCESSAMENTO.CODIGO          = DISPOSITIVO.CODIGOPROCESSAMENTO)
WHERE ( Linha.CodigoStatusLinha IN (16) ))
GROUP BY CodTecnologia,
  Operadora,
  StatusLinha
ORDER BY CodTecnologia,
  Operadora,
  StatusLinha

Seu agrupamento(group by) não pode ficar para fora …

P

Da erro

ERRO: subconsulta no FROM deve ter um aliás
SQL state: 42601
Hint: Por exemplo, FROM (SELECT …) [AS] foo.
Character: 51

Aleksandro

coloque um alias …

assim por exemplo :

o a será alias de toda consulta interna …

P

Assim vai complicar aleksandro… pois eu to montando o select… e nem imagino como colocaria em cima mais uma condição… to tentando ver um outro jeito…

mas valeu mesmo pela força

Aleksandro

Pacato:
Assim vai complicar aleksandro… pois eu to montando o select… e nem imagino como colocaria em cima mais uma condição… to tentando ver um outro jeito…

mas valeu mesmo pela força

Cara mas você rodou no BD funcionou ? este é o primeiro passo … depois você faz as respectivas modificações no java …entendeu …

P

Não funcionou… por isso falei

Funcionou assim:

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoTecnologia) AS CodTecnologia,
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoOperadora) AS Operadora,
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusLinha) AS StatusLinha,
COUNT(*) as Quantidade
FROM Historico
WHERE ( Historico.StatusLinha IN (16) )
GROUP BY CodTecnologia, Operadora, StatusLinha

UNION ALL

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha,

COUNT(*) as Quantidade

FROM SIMCard LEFT JOIN SIMCardDispositivo ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero LEFT JOIN Dispositivo ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero INNER JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento)

WHERE ( Linha.CodigoStatusLinha IN (16) )

GROUP BY CodTecnologia, Operadora, StatusLinha ORDER BY CodTecnologia, Operadora, StatusLinha

Só que os resultados estão repetidos… queria colocar na mesma linha…

por exemplo

veio
A - A - A
A - A - A

ao invés de AA - AA - AA

entende??

Aleksandro

Pacato:
Não funcionou… por isso falei

Funcionou assim:

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoTecnologia) AS CodTecnologia,
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoOperadora) AS Operadora,
(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusLinha) AS StatusLinha,
COUNT(*) as Quantidade
FROM Historico
WHERE ( Historico.StatusLinha IN (16) )
GROUP BY CodTecnologia, Operadora, StatusLinha

UNION ALL

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha,

COUNT(*) as Quantidade

FROM SIMCard LEFT JOIN SIMCardDispositivo ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero LEFT JOIN Dispositivo ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero INNER JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento)

WHERE ( Linha.CodigoStatusLinha IN (16) )

GROUP BY CodTecnologia, Operadora, StatusLinha ORDER BY CodTecnologia, Operadora, StatusLinha

Só que os resultados estão repetidos… queria colocar na mesma linha…

por exemplo

veio
A - A - A
A - A - A

ao invés de AA - AA - AA

entende??

Então você não quer unir seu select e sim concatenar colunas … seu BD é postgres certo ? faça assim então :

P

Consegui assim…

select CodTecnologia, Operadora, StatusLinha , sum(Quantidade)

from

(

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoTecnologia) AS CodTecnologia,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.CodigoOperadora) AS Operadora,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Historico.StatusLinha) AS StatusLinha,

COUNT(*) as Quantidade

FROM Historico

WHERE ( Historico.StatusLinha IN (16) )

GROUP BY CodTecnologia, Operadora, StatusLinha

UNION ALL

SELECT (SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Dispositivo.CodigoTecnologia) AS CodTecnologia,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = SIMCard.CodigoOperadora) AS Operadora,

(SELECT Dominio.Nome FROM Dominio WHERE Dominio.Codigo = Linha.CodigoStatusLinha) AS StatusLinha,

COUNT(*) as Quantidade

FROM SIMCard LEFT JOIN SIMCardDispositivo ON SIMCardDispositivo.SIMCard_Numero = SIMCard.Numero LEFT JOIN Dispositivo ON Dispositivo.Numero = SIMCardDispositivo.Dispositivo_Numero INNER JOIN Linha ON Linha.Numero = SIMCard.NumeroLinha LEFT JOIN Processamento ON (Processamento.Codigo = SIMCard.CodigoProcessamento OR Processamento.Codigo = Dispositivo.CodigoProcessamento)

WHERE ( Linha.CodigoStatusLinha IN (16) )

GROUP BY CodTecnologia, Operadora, StatusLinha

) tabela_virtual

group by CodTecnologia, Operadora, StatusLinha

ORDER BY CodTecnologia, Operadora, StatusLinha

valeu…

abs

Aleksandro

legal.

Criado 23 de abril de 2013
Ultima resposta 24 de abr. de 2013
Respostas 16
Participantes 2