SELECT em Cruz

13 respostas
R

Amigos,

Estou precisando de ajuda para montar uma query que traga uma lista cruzando informações de origem e destino.
Exemplificando fica mais fácil de entender:

CODIGO_PK COD_ORIGEM COD_DESTINO VALOR DEB_CRED 1 45 74 10,50 C 2 32 74 10,50 C 3 1 80 12,00 D 4 74 45 10,50 D 5 74 45 12,00 D

O resultado deveria sair assim:

CODIGO_PK COD_ORIGEM COD_DESTINO VALOR DEB_CRED 3 1 80 12,00 D 5 74 45 12,00 D 1 45 ---..--- 74 10,50 C 4 74 ---´`--- 45 10,50 D 2 50 74 10,50 C

Ou seja, classifica primeiramente por valor (DESC) e, para valores iguais, devem sair juntos (um após o outro) os registros com (COD_ORIGEMa = COD_DESTINOb) e (COD_DESTINOa = COD_ORIGEMb) e (DEB_CREDa <> DEB_CREDb).

Não sei se ficou claro, mas resumindo é isso!

Valeu galera!

13 Respostas

leonardo.vizagre

Bom dia renan, tudo bem?

Analisando sua necessidade, não consegui encontrar uma forma de fazer isso somente com Query SQL.
Como se trata de uma situação muito específica, seria mais interessante você pensar em criar uma STORED PROCEDURE, onde poderá implementar a regra de negócio de forma mais fácil. Crie uma tabela temporária para “descarregar” os dados processados pelos cursores e trabalhe com o retorno dos dados.

Espero ter colaborado.

R

leonardo.vizagre:
Bom dia renan, tudo bem?

Analisando sua necessidade, não consegui encontrar uma forma de fazer isso somente com Query SQL.
Como se trata de uma situação muito específica, seria mais interessante você pensar em criar uma STORED PROCEDURE, onde poderá implementar a regra de negócio de forma mais fácil. Crie uma tabela temporária para “descarregar” os dados processados pelos cursores e trabalhe com o retorno dos dados.

Espero ter colaborado.

Bom dia Leonardo, tudo beleza cara!

Obrigado por responder.

Então, trabalho com um cliente que possui regras muito restritas de codificação e uso de stored procedures é proibido no sistema em que estou atuando.

Estava com vergonha, mas só pra exemplificar vou postar aqui a query (POG horrível que eu havia citado) que obteve o resultado mais próximo, mas ainda não satisfatório:

SELECT DISTINCT ( A.COD_ORIGEM + 0.5) * ( B.COD_DESTINO + 0.7) , A.CODIGO_PK, A.COD_ORIGEM, A.COD_DESTINO, A.VALOR, A.DEB_CRED FROM TESTE_CRUZ2 A, TESTE_CRUZ2 B WHERE A.COD_ORIGEM = B.COD_DESTINO AND B.COD_ORIGEM = A.COD_DESTINO AND A.DEB_CRED <> B.DEB_CRED ORDER BY 5 DESC, 1 ;

O resultado foi:

Column1 CODIGO_PK COD_ORIGEM COD_DESTINO VALOR DEB_CRED 5.565,15 5 74 45 12,00 D 2.079,35 1 45 74 10,50 C 5,565,15 4 74 45 10,50 D

(Não foram listadas as linhas 1 e 3).

drsmachado

2 coisas, o cliente quer isso no banco de dados mesmo? Por que, na aplicação, você consegue fazer isto bem tranquilamente.
Outra, você terá de criar mais de um select, acredito que com um join na mesma tabela (talvez o left outer join) possa te ajudar.
Enfim, se o cliente for leigo, é difícil argumentar, mas dizer a verdade sempre é uma boa coisa. Diga que sem usar outros recursos (stored procedure, por exemplo) fica quase impossível o resultado.
Se ele tiver algum conhecimento, vai entender isso com mais facilidade.

A

Primeiro, o que eue entendi é que você precisa é apenas acertar a ordenação certo?

Bem, não especificou o banco, mas a maioria tem alguma forma de if para aplicar no select (decode no oracle, case no sql server, etc…)

Use esse if para dar um peso as linhas… se for igual os códigos, dê peso zero… se diferente, peso 1…

Depois inclua no order by esse peso…

Se não for isso que precisa, por favor dê mais detalhes…

pmlm

Se for em Oracle:

SELECT
(...)
ORDER by valor desc, 
least(cod_origem, cod_destino),
greatest(cod_origem,cod_destino),
deb_cred
R

drsmachado:
2 coisas, o cliente quer isso no banco de dados mesmo? Por que, na aplicação, você consegue fazer isto bem tranquilamente.

O cliente não é leigo, a questão é que as stored procedures não estão disponíveis no ambiente em que a aplicação será executada.

A idéia era criar um cursor que já resolvesse o problema, mas se não for possível a solução poderá ser efetuada via aplicação sem problemas mesmo!

Você quer dizer um SELECT com join, ou dois SELECTs? Com UNION?

drsmachado:

Enfim, se o cliente for leigo, é difícil argumentar, mas dizer a verdade sempre é uma boa coisa. Diga que sem usar outros recursos (stored procedure, por exemplo) fica quase impossível o resultado.
Se ele tiver algum conhecimento, vai entender isso com mais facilidade.

R

AbelBueno:
Primeiro, o que eue entendi é que você precisa é apenas acertar a ordenação certo?

Bem, não especificou o banco, mas a maioria tem alguma forma de if para aplicar no select (decode no oracle, case no sql server, etc…)

Use esse if para dar um peso as linhas… se for igual os códigos, dê peso zero… se diferente, peso 1…

Depois inclua no order by esse peso…

Se não for isso que precisa, por favor dê mais detalhes…

O banco de dados é DB2!

Nunca usei IF em uma query, tem algum exemplo?

R

pmlm:
Se for em Oracle:

SELECT (...) ORDER by valor desc, least(cod_origem, cod_destino), greatest(cod_origem,cod_destino), deb_cred

Não sei se essas cláusulas existem no DB2 também, vou testar!

Obrigado!

R

renan3006:
pmlm:
Se for em Oracle:

SELECT (...) ORDER by valor desc, least(cod_origem, cod_destino), greatest(cod_origem,cod_destino), deb_cred

Não sei se essas cláusulas existem no DB2 também, vou testar!

Obrigado!

Não funcionou, essas funções não existem mesmo no DB2…

Mas vou salvar esta query no meu arquivinho de referências porque achei bem interessante de qualquer forma…

pmlm

Como são só duas colunas podes experimentar com CASE

SELECT  * FROM TESTE_CRUZ
ORDER BY valor desc,   
CASE WHEN cod_origem>cod_destino THEN cod_destino ELSE cod_origem END,
CASE WHEN cod_origem<cod_destino THEN cod_destino ELSE cod_origem END,
deb_cred
drsmachado

A idéia era criar um cursor que já resolvesse o problema, mas se não for possível a solução poderá ser efetuada via aplicação sem problemas mesmo!

Você quer dizer um SELECT com join, ou dois SELECTs? Com UNION?

Ambos.
Na teoria o union permitiria isso.
Porém, acho que o mais adequado seria o join.

R

pmlm:
Como são só duas colunas podes experimentar com CASE

SELECT * FROM TESTE_CRUZ ORDER BY valor desc, CASE WHEN cod_origem>cod_destino THEN cod_destino ELSE cod_origem END, CASE WHEN cod_origem<cod_destino THEN cod_destino ELSE cod_origem END, deb_cred

Interessante também, mas o Case é mais uma função que não existe no DB2…

R

drsmachado:

Ambos.
Na teoria o union permitiria isso.
Porém, acho que o mais adequado seria o join.

Um amigo deu uma sugestão parecida com essa sua. Acho que vou utilizá-la:

SELECT A.CODIGO_PK, A.COD_ORIGEM, A.COD_DESTINO, A.VALOR, A.DEB_CRED , B.CODIGO_PK, B.COD_ORIGEM, B.COD_DESTINO, B.VALOR, B.DEB_CRED FROM TESTE_CRUZ2 A LEFT OUTER JOIN TESTE_CRUZ2 B ON A.COD_ORIGEM = B.COD_DESTINO AND B.COD_ORIGEM = A.COD_DESTINO AND A.VALOR = B.VALOR AND A.DEB_CRED <> B.DEB_CRED WHERE A.COD_ORIGEM = :host // <-- Falha de explicação, não informei que o cod_origem era entrada, FOI MAL! ORDER BY 4 DESC, 2 ;

Assim, cada linha do recordset implicará em duas linhas na lista a ser demonstrada (quando colunas “B” diferente de nulo).

Valeu galera, aprendi um bocado hoje! :thumbup:

Criado 13 de junho de 2011
Ultima resposta 13 de jun. de 2011
Respostas 13
Participantes 5