Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Faccruz

[Resolvido] Checar meses incluidos

Recommended Posts

Boa tarde,

 

Possuo uma tabela na seguinte estrutura

idMetas       Int AutoIncremento
MesAno        Varchar(10)
Atingiu       Char(1)
idFuncionario Int
Nessa Tabela o funcionario insere se ele atingiu ou não a meta estipulada para o mês.

Preciso saber como retornar o(s) mês(es) que ele não incluiu e obrigar a ele incluir o mês faltante antes de continuar. Estipulamos aqui um inicio para a digitação dessas metas (Agosto de 2008) ou, caso a data de admissão desse funcionario for maior que a estipulada (agosto/2008), comece a vigorar a data de admissão.

Ele pode incluir os meses anteriores e/ou posteriores a data vigente na CPU.

 

Espero ter sido claro.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você pode até criar o "calendário" na query, mas terá que fazer isso manualmente, mas precisamente em relação aos anos. (Embora você possa especificar vários e vários e não ter que se preocupar com eles tão cedo :D)

 

Fiz um simples teste com esses dados:

 

mysql> select  * from metas;
+---------+--------+---------+---------------+
| idmetas | mesano | atingiu | idfuncionario |
+---------+--------+---------+---------------+
|       1 | 082008 | S       |             1 | 
|       2 | 102008 | S       |             1 | 
|       3 | 092009 | S       |             2 | 
+---------+--------+---------+---------------+
3 rows in set (0.00 sec)

Com a seguinte query:

 

mysql> SELECT B.ANO, B.MES
    ->   FROM (
    ->     SELECT *
    ->       FROM (
    ->     SELECT 2008 ANO
    ->     UNION
    ->     SELECT 2009
    ->       ) ANOS, (
    ->         SELECT '01' MES
    ->         UNION
    ->         SELECT '02'
    ->         UNION
    ->         SELECT '03'
    ->         UNION
    ->         SELECT '04'
    ->         UNION
    ->         SELECT '05'
    ->         UNION
    ->         SELECT '06'
    ->         UNION
    ->         SELECT '07'
    ->         UNION
    ->         SELECT '08'
    ->         UNION
    ->         SELECT '09'
    ->         UNION
    ->         SELECT '10'
    ->         UNION
    ->         SELECT '11'
    ->         UNION
    ->         SELECT '12'
    ->       ) MESES
    ->   ) B
    ->   LEFT JOIN metas A
    ->   ON A.MESANO = CONCAT(B.MES, B.ANO) AND A.IDFUNCIONARIO = 1
    ->   WHERE CONCAT(B.ANO, B.MES) BETWEEN '200808' AND EXTRACT(YEAR_MONTH FROM CURDATE())
    ->     AND A.IDFUNCIONARIO IS NULL
    ->   ORDER BY B.ANO, B.MES;
+------+-----+
| ANO  | MES |
+------+-----+
| 2008 | 09  | 
| 2008 | 11  | 
| 2008 | 12  | 
| 2009 | 01  | 
| 2009 | 02  | 
| 2009 | 03  | 
| 2009 | 04  | 
| 2009 | 05  | 
| 2009 | 06  | 
| 2009 | 07  | 
| 2009 | 08  | 
| 2009 | 09  | 
+------+-----+
12 rows in set (0.00 sec)

Perceba que no caso, eu gero a combinação de mês e ano só para 2008 e 2009, e também defino o intervalo do mês inicial e final, talvez isto lhe atenda.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você pode até criar o "calendário" na query, mas terá que fazer isso manualmente, mas precisamente em relação aos anos. (Embora você possa especificar vários e vários e não ter que se preocupar com eles tão cedo :D)

 

Fiz um simples teste com esses dados:

 

mysql> select  * from metas;
+---------+--------+---------+---------------+
| idmetas | mesano | atingiu | idfuncionario |
+---------+--------+---------+---------------+
|       1 | 082008 | S       |             1 | 
|       2 | 102008 | S       |             1 | 
|       3 | 092009 | S       |             2 | 
+---------+--------+---------+---------------+
3 rows in set (0.00 sec)

Com a seguinte query:

 

mysql> SELECT B.ANO, B.MES
    ->   FROM (
    ->     SELECT *
    ->       FROM (
    ->     SELECT 2008 ANO
    ->     UNION
    ->     SELECT 2009
    ->       ) ANOS, (
    ->         SELECT '01' MES
    ->         UNION
    ->         SELECT '02'
    ->         UNION
    ->         SELECT '03'
    ->         UNION
    ->         SELECT '04'
    ->         UNION
    ->         SELECT '05'
    ->         UNION
    ->         SELECT '06'
    ->         UNION
    ->         SELECT '07'
    ->         UNION
    ->         SELECT '08'
    ->         UNION
    ->         SELECT '09'
    ->         UNION
    ->         SELECT '10'
    ->         UNION
    ->         SELECT '11'
    ->         UNION
    ->         SELECT '12'
    ->       ) MESES
    ->   ) B
    ->   LEFT JOIN metas A
    ->   ON A.MESANO = CONCAT(B.MES, B.ANO) AND A.IDFUNCIONARIO = 1
    ->   WHERE CONCAT(B.ANO, B.MES) BETWEEN '200808' AND EXTRACT(YEAR_MONTH FROM CURDATE())
    ->     AND A.IDFUNCIONARIO IS NULL
    ->   ORDER BY B.ANO, B.MES;
+------+-----+
| ANO  | MES |
+------+-----+
| 2008 | 09  | 
| 2008 | 11  | 
| 2008 | 12  | 
| 2009 | 01  | 
| 2009 | 02  | 
| 2009 | 03  | 
| 2009 | 04  | 
| 2009 | 05  | 
| 2009 | 06  | 
| 2009 | 07  | 
| 2009 | 08  | 
| 2009 | 09  | 
+------+-----+
12 rows in set (0.00 sec)

Perceba que no caso, eu gero a combinação de mês e ano só para 2008 e 2009, e também defino o intervalo do mês inicial e final, talvez isto lhe atenda.

 

 

Não entendi muito bem como verifico o mes que o funcionario esqueceu de digitar.

A minha dúvida é saber qual mês/ano o funcionario pulou ou esqueceu de digitar.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Deixa tentar explicar melhor

 

como faço para percorrer uma tabela identificando se o funcionario esqueceu/pulou algum registro?

 

Estrutura da tabela

idMetas int AutoInc
MesAno VarChar(10)
Atingiu  Char(1)
idFuncionario int

 

Ex. de dados gravados

idMetas      MesAno       Atingiu    idFuncionario
1             2008-08-01       S              115
2             2008-09-01       S              115
3             2008-11-01       N              115

 

nesse exemplo, deveria acusar que ele esqueceu/pulou o mês 10/2008.

Obs. Gravo todas as datas como sendo o dia 1 de cada mês

 

Como faço para resolver isso?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Aproveitando a sua questão, postei em meu blog uma pequena explicação do que eu fiz para resolver, inclusive melhorei a abordagem levando em conta as suas informações a respeito da data.

 

Dê uma olhada: http://felipe.c2zlabs.com/identificando-intervalos-entre-datas-no-mysql

Compartilhar este post


Link para o post
Compartilhar em outros sites

Aproveitando a sua questão, postei em meu blog uma pequena explicação do que eu fiz para resolver, inclusive melhorei a abordagem levando em conta as suas informações a respeito da data.

 

Dê uma olhada: http://felipe.c2zlabs.com/identificando-intervalos-entre-datas-no-mysql

 

 

Vou testar na segunda-feira daí posto o resultado

 

Valeu!

Compartilhar este post


Link para o post
Compartilhar em outros sites

 

Aproveitando a sua questão, postei em meu blog uma pequena explicação do que eu fiz para resolver, inclusive melhorei a abordagem levando em conta as suas informações a respeito da data.

 

Dê uma olhada: http://felipe.c2zlabs.com/identificando-intervalos-entre-datas-no-mysql

 

 

Vou testar na segunda-feira daí posto o resultado

 

Valeu!

 

Bom dia Amigo, Fiz o teste aqui, mas não está funcionando perfeitamente, alem de exibir a data que falta, esta exibindo também a data já cadastrada, onde posso fazer alteração?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Amigo... tem um erro nesse SQL que você montou,

 

caso algum funcionário tenha incluido o mês que falta para outro (com seus proprios códigos), ele não me retorna para esse que está faltando.

 

Tentei incluir uma clausula para filtrar o código, mas sem sucesso.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Partindo do principio q pelo menos 1 funcionario lembrou de fazer algum mes (nao houve um esquecimento de todos de algum mes) daria pra fazer assim, de maneira simples:

 

 

select t.funcionario, m.mes from

(select distinct mesano mes from tabela)m ,

Left join tabela t ON m.mes = t.mesano

where t.mesano is null

Compartilhar este post


Link para o post
Compartilhar em outros sites

Partindo do principio q pelo menos 1 funcionario lembrou de fazer algum mes (nao houve um esquecimento de todos de algum mes) daria pra fazer assim, de maneira simples:

 

 

select t.funcionario, m.mes from

(select distinct mesano mes from tabela)m ,

Left join tabela t ON m.mes = t.mesano

where t.mesano is null

 

Onde eu encaixo essa SQL?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Essa SQL te traz todos os funcionarios com os meses q eles esqueceram de digitar

 

Entendi, mas pra isso teria que ter os todos os meses cadastrados na base, me corrija se estiver errado.

 

No meu cadastro, o funcionario seleciona o Mês e o Ano que deseja incluir, e nisso ele poderia pular/esquecer de algum.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Partindo do principio q pelo menos 1 funcionario lembrou de fazer algum mes (nao houve um esquecimento de todos de algum mes) daria pra fazer assim, de maneira simples:

 

 

Ou seja a nao ser q você tenha uma equipe imbecis, sempre alguem vai ter lembrado de colocar os meses, pode ser q eles esqueceram um mes ou outro, mas TODOS esquecerem algum mes nao tem como, a consulta se baseia nisso, entendeu?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Partindo do principio q pelo menos 1 funcionario lembrou de fazer algum mes (nao houve um esquecimento de todos de algum mes) daria pra fazer assim, de maneira simples:

 

 

Ou seja a nao ser q você tenha uma equipe imbecis, sempre alguem vai ter lembrado de colocar os meses, pode ser q eles esqueceram um mes ou outro, mas TODOS esquecerem algum mes nao tem como, a consulta se baseia nisso, entendeu?

 

Mas são vários funcionarios, códigos de acesso diferentes, várias lojas (70 ao todo), ou seja, são mais de 200 códigos, não estou dizendo que TODOS irão esquecer, mas no minimo, chutando baixo, 10 esqueceram de digitar um ou outro, e é essa a minha dúvida.

O tópico do Eclesiastes, resolveu qndo existe apenas UM (1) funcionario cadastrado na tabela METAS, com mais, ele se perde.

 

Agora essa equipe de imbecis, como você disse, são usuários finais e muitos com mais de 20 anos de empresa, então tudo pode acontecer. Me lembro na época da faculdade, um dos orientadores me disse, "Qndo criar um sistema pense em um usuário que nunca viu um computador na frente, e monte um sistema para esse usuário."

Compartilhar este post


Link para o post
Compartilhar em outros sites

Aproveitando a sua questão, postei em meu blog uma pequena explicação do que eu fiz para resolver, inclusive melhorei a abordagem levando em conta as suas informações a respeito da data.

 

Dê uma olhada: http://felipe.c2zlabs.com/identificando-intervalos-entre-datas-no-mysql

 

Amigo, alguma posição?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá, quando eu montei a query, eu pensei que você fosse rodar apenas para obter as informações acerca de um único usuário.

 

Enfim, levando em consideração que a primeira e a última data marcada do usuário delimita a busca pelo buracos, com uma pequena alteração na query que eu fiz, obtemos o resultado:

 

mysql> select * from metas;
+---------+------------+---------+---------------+
| idmetas | mesano     | atingiu | idfuncionario |
+---------+------------+---------+---------------+
|       1 | 2009-01-01 | S       |             1 | 
|       2 | 2009-02-01 | S       |             1 | 
|       3 | 2009-04-01 | S       |             1 | 
|       4 | 2009-05-01 | S       |             1 | 
|       5 | 2009-08-01 | S       |             1 | 
|       6 | 2008-02-01 | S       |             2 | 
|       7 | 2008-05-01 | S       |             2 | 
+---------+------------+---------+---------------+
7 rows in set (0.00 sec)

 

mysql> SELECT X.idfuncionario, DATE_ADD(X.INICIO, INTERVAL Y.N MONTH) DATA
    ->   FROM (
    ->     SELECT idfuncionario, MIN(mesano) inicio, MAX(mesano) fim
    ->       FROM metas
    ->       GROUP BY idfuncionario
    ->   ) X
    ->   JOIN (
    ->     SELECT A.A+B.B+1 N
    ->       FROM (SELECT 0 A UNION ALL
    ->           SELECT 1 UNION ALL
    ->           SELECT 2 UNION ALL
    ->           SELECT 3 UNION ALL
    ->           SELECT 4 UNION ALL
    ->           SELECT 5 UNION ALL
    ->           SELECT 6 UNION ALL
    ->           SELECT 7 UNION ALL
    ->           SELECT 8 UNION ALL
    ->           SELECT 9) A,
    ->          (SELECT 0 B UNION ALL
    ->           SELECT 10 UNION ALL
    ->           SELECT 20 UNION ALL
    ->           SELECT 30 UNION ALL
    ->           SELECT 40 UNION ALL
    ->           SELECT 50 UNION ALL
    ->           SELECT 60 UNION ALL
    ->           SELECT 70 UNION ALL
    ->           SELECT 80 UNION ALL
    ->           SELECT 90) B
    ->     ORDER BY 1
    ->   ) Y
    ->     ON DATE_ADD(X.inicio, INTERVAL Y.N MONTH) < X.FIM
    ->   LEFT JOIN metas M
    ->     ON M.mesano = DATE_ADD(X.inicio, INTERVAL Y.N MONTH)
    ->     AND M.idfuncionario = X.idfuncionario
    ->   WHERE M.mesano IS NULL;
+---------------+------------+
| idfuncionario | DATA       |
+---------------+------------+
|             2 | 2008-03-01 | 
|             1 | 2009-03-01 | 
|             2 | 2008-04-01 | 
|             1 | 2009-06-01 | 
|             1 | 2009-07-01 | 
+---------------+------------+
5 rows in set (0.00 sec)

Correto!?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá, quando eu montei a query, eu pensei que você fosse rodar apenas para obter as informações acerca de um único usuário.

 

Enfim, levando em consideração que a primeira e a última data marcada do usuário delimita a busca pelo buracos, com uma pequena alteração na query que eu fiz, obtemos o resultado:

 

mysql> select * from metas;
+---------+------------+---------+---------------+
| idmetas | mesano     | atingiu | idfuncionario |
+---------+------------+---------+---------------+
|       1 | 2009-01-01 | S       |             1 | 
|       2 | 2009-02-01 | S       |             1 | 
|       3 | 2009-04-01 | S       |             1 | 
|       4 | 2009-05-01 | S       |             1 | 
|       5 | 2009-08-01 | S       |             1 | 
|       6 | 2008-02-01 | S       |             2 | 
|       7 | 2008-05-01 | S       |             2 | 
+---------+------------+---------+---------------+
7 rows in set (0.00 sec)

 

mysql> SELECT X.idfuncionario, DATE_ADD(X.INICIO, INTERVAL Y.N MONTH) DATA
    ->   FROM (
    ->     SELECT idfuncionario, MIN(mesano) inicio, MAX(mesano) fim
    ->       FROM metas
    ->       GROUP BY idfuncionario
    ->   ) X
    ->   JOIN (
    ->     SELECT A.A+B.B+1 N
    ->       FROM (SELECT 0 A UNION ALL
    ->           SELECT 1 UNION ALL
    ->           SELECT 2 UNION ALL
    ->           SELECT 3 UNION ALL
    ->           SELECT 4 UNION ALL
    ->           SELECT 5 UNION ALL
    ->           SELECT 6 UNION ALL
    ->           SELECT 7 UNION ALL
    ->           SELECT 8 UNION ALL
    ->           SELECT 9) A,
    ->          (SELECT 0 B UNION ALL
    ->           SELECT 10 UNION ALL
    ->           SELECT 20 UNION ALL
    ->           SELECT 30 UNION ALL
    ->           SELECT 40 UNION ALL
    ->           SELECT 50 UNION ALL
    ->           SELECT 60 UNION ALL
    ->           SELECT 70 UNION ALL
    ->           SELECT 80 UNION ALL
    ->           SELECT 90) B
    ->     ORDER BY 1
    ->   ) Y
    ->     ON DATE_ADD(X.inicio, INTERVAL Y.N MONTH) < X.FIM
    ->   LEFT JOIN metas M
    ->     ON M.mesano = DATE_ADD(X.inicio, INTERVAL Y.N MONTH)
    ->     AND M.idfuncionario = X.idfuncionario
    ->   WHERE M.mesano IS NULL;
+---------------+------------+
| idfuncionario | DATA       |
+---------------+------------+
|             2 | 2008-03-01 | 
|             1 | 2009-03-01 | 
|             2 | 2008-04-01 | 
|             1 | 2009-06-01 | 
|             1 | 2009-07-01 | 
+---------------+------------+
5 rows in set (0.00 sec)

Correto!?

 

Realmente irei listar apenas de um funcionário, o erro que menciono é se um determinado usuário (ex.1) esqueceu de preencher o mês 10/2008 e o usuário 2 preencheu essa data, ela não retorna para o usuário 1 que faltou essa data, tendo em vista que são cadastros diferentes.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ok. Eu havia entendido errado, tinha entendido que a primeira e última data do usuário delimitaria a busca. Levando então em conta que a primeira e última de todos os usuários delimitará a busca, você poderia fazer algo como:

 

mysql> SELECT DATE_ADD(X.INICIO, INTERVAL Y.N MONTH) DATA
    ->   FROM (
    ->     SELECT MIN(mesano) inicio, MAX(mesano) fim
    ->       FROM metas
    ->   ) X
    ->   JOIN (
    ->     SELECT A.A+B.B+1 N
    ->       FROM (SELECT 0 A UNION ALL
    ->           SELECT 1 UNION ALL
    ->           SELECT 2 UNION ALL
    ->           SELECT 3 UNION ALL
    ->           SELECT 4 UNION ALL
    ->           SELECT 5 UNION ALL
    ->           SELECT 6 UNION ALL
    ->           SELECT 7 UNION ALL
    ->           SELECT 8 UNION ALL
    ->           SELECT 9) A,
    ->          (SELECT 0 B UNION ALL
    ->           SELECT 10 UNION ALL
    ->           SELECT 20 UNION ALL
    ->           SELECT 30 UNION ALL
    ->           SELECT 40 UNION ALL
    ->           SELECT 50 UNION ALL
    ->           SELECT 60 UNION ALL
    ->           SELECT 70 UNION ALL
    ->           SELECT 80 UNION ALL
    ->           SELECT 90) B
    ->     ORDER BY 1
    ->   ) Y
    ->     ON DATE_ADD(X.inicio, INTERVAL Y.N MONTH) <= X.FIM
    ->   LEFT JOIN metas M
    ->     ON M.mesano = DATE_ADD(X.inicio, INTERVAL Y.N MONTH)
    ->     AND M.idfuncionario = 2
    ->   WHERE M.mesano IS NULL;
+------------+
| DATA       |
+------------+
| 2008-03-01 | 
| 2008-04-01 | 
| 2008-06-01 | 
| 2008-07-01 | 
| 2008-08-01 | 
| 2008-09-01 | 
| 2008-10-01 | 
| 2008-11-01 | 
| 2008-12-01 | 
| 2009-01-01 | 
| 2009-02-01 | 
| 2009-03-01 | 
| 2009-04-01 | 
| 2009-05-01 | 
| 2009-06-01 | 
| 2009-07-01 | 
| 2009-08-01 | 
+------------+
17 rows in set (0.01 sec)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Muito Obrigado! Funcionou do jeito que eu queria, apenas fazendo uma alteração!

Segue a alteração.

 

SELECT DATE_ADD(X.INICIO, INTERVAL Y.N MONTH) DATA
FROM (SELECT MIN(mesano) inicio, MAX(mesano) fim
        FROM metas
       where idFuncionario = 118 --> Acrescentei essa linha) X
   JOIN (
     SELECT A.A+B.B+1 N
       FROM (SELECT 0 A UNION ALL
           SELECT 1 UNION ALL
           SELECT 2 UNION ALL
           SELECT 3 UNION ALL
           SELECT 4 UNION ALL
           SELECT 5 UNION ALL
           SELECT 6 UNION ALL
           SELECT 7 UNION ALL
           SELECT 8 UNION ALL
           SELECT 9) A,
          (SELECT 0 B UNION ALL
           SELECT 10 UNION ALL
           SELECT 20 UNION ALL
           SELECT 30 UNION ALL
           SELECT 40 UNION ALL
           SELECT 50 UNION ALL
           SELECT 60 UNION ALL
           SELECT 70 UNION ALL
           SELECT 80 UNION ALL
           SELECT 90) B
     ORDER BY 1
   ) Y
     ON DATE_ADD(X.inicio, INTERVAL Y.N MONTH) <= X.FIM
   LEFT JOIN metas M
     ON M.mesano = DATE_ADD(X.inicio, INTERVAL Y.N MONTH)
     AND M.idfuncionario = 118
   WHERE M.mesano IS NULL;

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.