Laço no banco?

Olá pessoal,

minha dúvida deve ser simples mas não sei como é possível.

Supondo que tenho uma tabela que registra os funcionários e outra que registra os pagamentos mensais de cada funcionário.

Como montar uma consulta direto no banco que para cada funcionário retorne seus últimos 5 pagamentos?

com o retorno das consultas separados consigo fazer nas linguagens que conheço, mas queria fazer a consulta direto no banco em sql.

Vocẽ não disse o banco, mas quanto sua dúvida, laço no banco tem o termo de cursor pesquise a respeito…

Porém seu uso é desencorajado tendo em vista questões de desempenho…

Quanto ao seu problema, já pensou usar inner join? ex em mysql

SELECT
  f.nome AS FUNCIONARIO,
  p.mes AS MES_PAGTO,
  p.valor AS VAL_PAGTO,
FROM funcionarios f
INNER JOIN pagamentos p on p.func_cod = f.func_cod
ORDER BY f.nome ASC, p.mes DESC LIMIT 5

Ordenei o mes de pagto em decrescente (tendo em vista que o campo seja inteiro por ex jan 1 a dez 12) e limitados a 5…

O campo func_cod seria o “elo” que exista nas duas tabelas para vinculá-las…

Obs: ja adiantando, caso você me diga que o campo de data do pagto seja date/datetime, há funções que extraem apenas o mẽs para você…

...
ORDER BY f.nome ASC, MONTH(p.data_pagto) DESC LIMIT 5

Ou simplesmente pela data completa também funciona…

ORDER BY f.nome ASC, p.data_pagto DESC LIMIT 5

Entendi a lógica e segue minha query a exemplo da sua:

SELECT
Bsc.[Cod Segurado] AS segurado,
Bsc_1.[Cod Segurado] AS seguradoFatura
FROM Bsc AS Bsc_1
INNER JOIN Bsc ON Bsc_1.[Cod Segurado] = Bsc.[Cod Segurado]
order by Bsc_1.[Cod Segurado] desc ;

Mas quando tento colocar o limitador top ou limit o banco não aceita…

Qual banco de dados está usando? Oracle, MySQL, Postgre?

Essa informação é importante porque a sintaxe de limit/top varia de banco para banco, o que pode ser o seu problema. Sem saber qual banco é, fica mais difícil te ajudar.

Abraço.

1 curtida

Access

A sintaxe top deveria funcionar (veja no link).

SELECT TOP 5
Bsc.[Cod Segurado] AS segurado,
Bsc_1.[Cod Segurado] AS seguradoFatura
FROM Bsc AS Bsc_1
INNER JOIN Bsc ON Bsc_1.[Cod Segurado] = Bsc.[Cod Segurado]
order by Bsc_1.[Cod Segurado] desc;

Qual a mensagem de erro? Qual a versão do Access?

Abraço.

Neste caso não apresenta erro, mas o retorno está incorreto. Quero retornar todos os registros da primeira tabela e os 5 maiores da segunda.

Access 2010

Você disse ter duas tabelas, uma funcionarios e outra pagamentos mas o que vejo é você usando a mesma duas vezes, qual sentido?

Se estiver guardando registros de diferentes utilidades na mesma tabela, recomendo criar outra e migrar os registros necessários, pois além de má prática é uma péssima idéia…

Realmente o LIMIT no mysql, TOP no Access/SQL Server vai trazer apenas 5 registros mesmo, esqueci esse detalhe…

Outra alternativa é usar a função MAX + GROUP BY ao invés de TOP farei o exemplo no mysql ok?

SELECT
  f.nome AS FUNCIONARIO,
  MAX(p.mes) AS MES_PAGTO,
  p.valor AS VAL_PAGTO,
FROM funcionarios f
INNER JOIN pagamentos p on p.func_cod = f.func_cod
ORDER BY f.nome ASC
GROUP BY f.nome, p.valor

Necessário agrupar por nome do funcionario e valor do pagto… algo nesse sentido, creio que o Access tem suporte a esses recursos…

Obs: E caso não funcione/atenda, pesquise sobre datediff no access

Assim você busca as datas por um período, por exemplo os ultimos 5 meses (pagtos) a partir da data atual…

https://www.w3schools.com/sql/func_msaccess_datediff.asp

Talvez algo nesse sentido…

SELECT
  Bsc.[Cod Segurado] AS segurado,
  Bsc_1.[Cod Segurado] AS seguradoFatura
FROM Bsc AS Bsc_1
INNER JOIN Bsc ON Bsc_1.[Cod Segurado] = Bsc.[Cod Segurado]
WHERE DateDiff("m", NOW(), Bsc_1.[Campo Data Pagto]) <= 5

Em oracle seria assim

SELECT f.id, f.nome, p.mes, p.valor
  from  funcionarios f,
        (select p.funcionario_id, p.mes, p.valor, row_number () over (partition by funcionario_id order by mes desc) as row_n from pagamentos) p
 where f.id = p.funcionario_id
  and p.row_n < 6

Tanto quanto sei não existe partition by em Access…

Só um exemplo men