Sql um pouco avançado - pelo menos pra mim [RESOLVIDO]

É possível eu fazer o seguinte:

1 - Tenho um método que realiza uma consulta no banco.
2 - Tenho um segundo método que realiza uma outra consulta no banco.
3 - Eu quero criar um terceiro método que pegue o resultado da consulta dos dois primeiros métodos, junte-os e mostre sem repetições.

Abaixo eu posto os métodos:

-> Neste primeiro, seleciono os itens da tabela produtos com o distinct, quando eles aparecem em alguma nota de entrada

[code] private static void listaProdutosEntradas(ProdutoSC filtro, Transacao t) {
try {
SQL sql = new SQL(t);
sql.add("SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla ");
sql.add("FROM etqnfe e, etquni u, etqprod p INNER JOIN etqnfe_item nfe ");
sql.add("ON nfe.id_prod = p.id ");
sql.add("WHERE nfe.id_nfe = e.id ");
sql.add("AND e.dt_rec BETWEEN :dtInicial AND :dtFinal ");
sql.add("AND p.id_uni_sai = u.id ");
sql.add("AND e.id_uni = :id_uni ");
sql.add("AND e.id_emp = :id_emp ");
sql.add("ORDER BY codProd ");

        sql.setParam("id_uni", filtro.unidade.id);
        sql.setParam("id_emp", Sessao.getEmpresaLogada().id);
        sql.setParam("dtInicial", filtro.dtInicial);
        sql.setParam("dtFinal", filtro.dtFinal);
           
    } catch (Exception e) {
        Msg.alert(null, "Erro ao gerar SQL. " + e.getLocalizedMessage());
        e.printStackTrace();
    }

}[/code]
-> Neste segundo, seleciono os itens da tabela produtos com o distinct, quando eles aparecem em alguma nota de saída

[code]private static void listarProdutosSaidas(ProdutoSC filtro, Transacao t) {
try {
SQL sql = new SQL(t);
sql.add("SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla ");
sql.add("FROM pdvnfs s, etquni u, etqprod p INNER JOIN pdvnfs_item nfs ");
sql.add("ON nfs.id_prod = p.id ");
sql.add("WHERE nfs.id_nfs = s.id ");
sql.add("AND s.dt_emis BETWEEN :dtInicial AND :dtFinal ");
sql.add("AND p.id_uni_sai = u.id ");
sql.add("AND s.id_uni = :id_uni ");
sql.add("AND s.id_emp = :id_emp ");
sql.add("ORDER BY codProd ");

        sql.setParam("id_uni", filtro.unidade.id);
        sql.setParam("id_emp", Sessao.getEmpresaLogada().id);
        sql.setParam("dtInicial", filtro.dtInicial);
        sql.setParam("dtFinal", filtro.dtFinal);

    } catch (Exception e) {
        Msg.alert(null, "Erro ao gerar SQL. " + e.getMessage());
        e.printStackTrace();
    }
 }[/code]

O que eu quero fazer, é pegar o primeiro sql, juntar com o segundo sql, e exibir todos os itens (codProd e nomeProd), sem repetições.

Alguém expert em SQL se dispõe a me ajudar? Ou alguém sugere uma outra forma para mim fazer isso? Tentei fazer tudo em um sql só, mas não ficou legal, creio que assim, ganho em performance. E cada sql, separado, já está testado e retornando o resultado que eu quero. Resta junta-los.

O que eu poderia retornar em cada um desses dois métodos, que eu conseguisse pegar no terceiro, e fazer esta separação que eu quero. Pensei em HashMap, mas não sei, por isso estou buscando ajuda.

Agradeço.

Opa.
Como tu tentou juntar os dois sqls??
Com um union ou union all??
O que nao ficou legal quando voce tentou juntar os dois?

:slight_smile:

Usa o union como disse o nebal, só que atente-se em dar os mesmos nomes aos alias dos campos, senão ja era…

Já que você não quer repetições no Resultset, então você pode juntar as duas consultas, e utilizar o Union, ao invés de criar 2 métodos, e unir o Resultset de cada um em um terceiro método.

Aí, vc teria q colocar um campo a mais no Select, para vc distinguir qual registro eh nota de entrada, e qual registro eh nota de saída.
Por exemplo:

            sql.add("SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla, 'Nota_Entrada' AS TipoNota      ");   
            sql.add("FROM etqnfe e, etquni u, etqprod p INNER JOIN etqnfe_item nfe      "); 

No segundo Select:

            sql.add("SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla, 'Nota_Saida' AS TipoNota          ");   
            sql.add("FROM pdvnfs s, etquni u, etqprod p INNER JOIN pdvnfs_item nfs          ");

O código ficaria assim:

            sql.add("SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla, 'Nota_Entrada' AS TipoNota      ");   
            sql.add("FROM etqnfe e, etquni u, etqprod p INNER JOIN etqnfe_item nfe           ");   
            sql.add("ON nfe.id_prod = p.id                                                                       ");   
            sql.add("WHERE nfe.id_nfe = e.id                                                                   ");   
            sql.add("AND e.dt_rec BETWEEN :dtInicial AND :dtFinal                                    ");   
            sql.add("AND p.id_uni_sai = u.id                                                                    ");   
            sql.add("AND e.id_uni = :id_uni                                                                     ");   
            sql.add("AND e.id_emp = :id_emp                                                                 ");   
            sql.add("ORDER BY codProd                                                                          ");   
            sql.add("UNION                                                                                            ");
            sql.add("SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla, 'Nota_Saida' AS TipoNota          ");   
            sql.add("FROM pdvnfs s, etquni u, etqprod p INNER JOIN pdvnfs_item nfs          ");   
            sql.add("ON nfs.id_prod = p.id                                                                       ");   
            sql.add("WHERE nfs.id_nfs = s.id                                                                    ");   
            sql.add("AND s.dt_emis BETWEEN :dtInicial AND :dtFinal                                  ");   
            sql.add("AND p.id_uni_sai = u.id                                                                    ");   
            sql.add("AND s.id_uni = :id_uni                                                                      ");   
            sql.add("AND s.id_emp = :id_emp                                                                  ");   
            sql.add("ORDER BY codProd                                                                           ");  

Qualquer dúvida, eh soh falar ae…

Desculpa ae pelo "); tudo desordenado.

Desculpem a demora, hora do almoço.

Realmente, eu não tentei com o operador UNION, mas agora somente fazendo as modificação propostas por você brunoha, executando direto no Postgree, obtenho o seguinte erro:

ERROR:  syntax error at or near "SELECT" at character 277

O SQL ficou assim:
Eu ainda não analisei e nem pesquisei para ver o porque do erro, mas se alguém quiser facilitar e já me responder eu agradeço.

SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla, 'Nota_Entrada' AS tipoNota FROM etqnfe e, etquni u, etqprod p INNER JOIN etqnfe_item nfe ON nfe.id_prod = p.id WHERE nfe.id_nfe = e.id AND e.dt_rec BETWEEN '01/01/2008' AND '01/31/2008' AND p.id_uni_sai = u.id ORDER BY codProd UNION SELECT DISTINCT p.cod as codProd, p.nome as nomeProd, u.sigla, 'Nota_Saida' AS tipoNota FROM pdvnfs s, etquni u, etqprod p INNER JOIN pdvnfs_item nfs ON nfs.id_prod = p.id WHERE nfs.id_nfs = s.id AND s.dt_emis BETWEEN '01/01/2008' AND '01/31/2008' AND p.id_uni_sai = u.id ORDER BY codProd
O erro tá lá no inicio do segundo select…

tira o order by do primeiro select deixa só na ultima expressão, e tenta usar o UNION ALL

Era isso mesmo Guitar_Men.

Obrigado, por enquando. No resultado da consulta, reparei alguns resultados indesejados, mas por enquanto agradeço muito.

:smiley: SQL rlz a lot !!!

[quote=brunoha]Já que você não quer repetições no Resultset, então você pode juntar as duas consultas, e utilizar o Union, ao invés de criar 2 métodos, e unir o Resultset de cada um em um terceiro método.
[/quote]
Não entendi, como eu poderia unir o ResultSet de cada consulta em um terceiro método???

Olhem uma parte da saída produzida pela execução do SQL:

101     "GASOLINA ORIGINAL C"    "LTS"     "Nota_Entrada"
101     "GASOLINA ORIGINAL C"    "LTS"     "Nota_Saida"
103     "GASOLINA MASTER"          "LTS"     "Nota_Entrada"
103     "GASOLINA MASTER"          "LTS"     "Nota_Saida"
201     "GASOLINA F1 MASTER"      "LTS"     "Nota_Entrada"
201     "GASOLINA F1 MASTER"      "LTS"     "Nota_Saida"
203     "GASOLINA ORIGINAL"        "LTS"     "Nota_Entrada"
203     "GASOLINA ORIGINAL"        "LTS"     "Nota_Saida"
301     "OLEO DIESEL COMUM"       "LTS"     "Nota_Entrada"
301     "OLEO DIESEL COMUM"       "LTS"     "Nota_Saida"
303     "ALCOOL"                          "LTS"     "Nota_Entrada"
303     "ALCOOL"                          "LTS"     "Nota_Saida"

Tá dando uma linha para a Nota de Entrada e uma linha para a Nota de Saída (tem alguns produtos que não, coincidentemente estes que peguei, todos deram uma linha para a entrada e para a saída). Mas a questão é:

Como que eu excluo daqui esses registros repetidos agora?? Adiciono mais alguma coisa no meu SQL, ou trato o resultado deste em um novo método, ou alguma outra sugestão??? Agradeço.
Obs: Não consegui alinhar direito a tabela.

fernandoeick, que tipo de resultado indesejado???

Se for repetido, vc vai ter que usar o Union, ao invés do Union All

Não sabia que era Postgree SQL, e tbm não tinha testado a query por aqui para ver se tava funfando realmente.
Desculpae…

Pelo resultset que vc passou, penso eu q existe uma nota de entrada, e uma nota de saída para cada produto.
Não é isso?

Quais registros repetidos, se vc usou o distinct não tem result repetido…

Pois é, esqueci de mencionar que era Postgree.

Mas o resultado indesejado, é este que colei acima, duplicação.

Bom, na verdade, o que eu quero, é que não apareçam duas linhas com o mesmo produto. Um produto (ou melhor, um codProd) pode aparecer somente uma vez.

Se o mesmo produto estiver na entrada, e estiver também na saída, eu quero exibir só um dos dois.

Ficou mais claro agora?

Ficou muito complexo aí pessoal?

huuuum… então tira a minha sugestão do “‘Nota_Entrada’ AS tipoNota” e “‘Nota_Saida’ AS tipoNota”.

Aí funfa! Sugeri isso, porque imaginava que você iria precisar identificar daonde vinha cada produto. Mas como vc quer um registro de cada produto, sem o tipoNota funciona.

Hummm… mas que idiota mesmo :shock: … como não percebi que era isso.

Desculpa aí pela falta de atenção. Agora ficou perfeito!

Agradeço muito a ajuda de vocês. :mrgreen: