Principales respuestas
Obtener registros del inicio de Mes y final de Mes

Pregunta
-
Hola, les pido su ayuda para resolver esto, necesito obtener el numero de empleados con los que se cuenta al inicio de cada mes y al final de mes y obtener algo como lo siguiente:
NoEmpleadosAlInicio Mes 38 1 40 2 56 3 50 4 45 5 NoEmpleadosAlFinal Mes 38 1 40 2 56 3 50 4 45 5 Tengo los datos, Número de empleado, fecha de ingreso fecha de baja
De antemano, Muchas gracias!
alozada
Respuestas
-
Hola alozada:
El problema no es la salida (que un poco si), donde tienes que mejorar para obtener el resultado correcto es en la definición. No es lo mismo que las columnas sean date, o datetime, o varchar. No has expuesto si vienen de una sola tabla....
La mejor manera para que el resultado sea siempre el apropiado, o lo más cercano posible, es poner la definición del origen. Si te fijas, yo te he puesto un créate table..... y una sentencia de inserción con múltiples valores.
Si otra persona en los foros, recoge el testigo de lo que yo te he respondido, ya tiene parte del trabajo hecho para poder aportar otra vía. Si esto que yo he realizado, lo haces tú, siempre tendrás una mejor posibilidad de ayuda.
Una posible solución:
DECLARE @fechaAñoCurso DATE= '20190101'; WITH cte AS (SELECT tbl.valor FROM (VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) AS tbl(valor)), fechas AS (SELECT fecha_ingreso , DATEDIFF(MONTH, '19000101', @fechaAñoCurso) AS CURSO , DATEDIFF(month, '19000101', fecha_ingreso) AS INGRESO , DATEDIFF(MONTH, '19000101', ISNULL(fecha_baja, '21000101')) AS BAJA , e.NumEmp FROM empleadosNominal e), agrupado AS (SELECT SUM(CASE WHEN f.BAJA >= F.CURSO + cte.valor - 1 AND INGRESO < (CURSO + cte.valor) - 1 THEN 1 END) AS EmpleadosAlInicio , SUM(CASE WHEN f.BAJA >= F.CURSO + cte.valor AND INGRESO < (CURSO + cte.valor) THEN 1 END) AS EmpleadosAlFinal , cte.valor AS Mes FROM fechas f CROSS JOIN cte GROUP BY cte.VALOR) SELECT a.EmpleadosAlInicio , a.EmpleadosAlFinal , a.Mes , (a.EmpleadosAlInicio + a.EmpleadosAlFinal) as suma , ((a.EmpleadosAlInicio + a.EmpleadosAlFinal)*(1.0)) as sumaConDecimales , ((((a.EmpleadosAlInicio + a.EmpleadosAlFinal)*(1.0)) / 2) * 100) as resultado FROM agrupado a;
Puedes quitar las columnas innecesarias, solo te lo he plasmado, paso por paso, en cada columna para que veas como se puede resolver.
Ya comentas si la solución es lo deseado
- Marcado como respuesta Tonatiuh AbregoModerator martes, 11 de junio de 2019 14:14
Todas las respuestas
-
Hola alozada:
Deberías de exponer mucho mejor tu escenario, porque sino las soluciones, que te podemos dar, serán erróneas, y conllevará mucho más tiempo la resolución satisfactoria de tu pregunta.
create table empleadosNominal (NumEmp int, fecha_ingreso date, fecha_baja date) go insert into empleadosNominal(NumEmp, fecha_ingreso, fecha_baja) values (1, '20181212',null), (2, '20190112',null), (3, '20161030','20190304'), (4, '20181231','20190205'), (5, '20181231','20190226'), (6, '20181231','20190330'), (7, '20181231',null), (8, '20181231',null), (9, '20190102',null), (10,'20181231','20181231'), (11,'20181231',null), (12,'20181231',null), (13,'20181231','20190227'), (14,'20181231',null), (15,'20181231','20190130'), (16,'20181231',null), (17,'20181231','20190330'), (18,'20181231',null), (19,'20181231','20190405'), (20,'20181231',null); go
Voy a partir de la idea, que lo tienes en el mismo conjunto, y que son columnas tipo date.
Que la fecha de baja puede ser null, sino se ha producido.
Que la fecha de alta no puede ser null.
Qué quieres sólo el año en curso.
Para poder solucionarlo, vamos a utilizar dos trucos. El primero, es generar una tabla con los números de los meses para realizar un cross join (producto cartesiano), contra el otro conjunto, donde estarán los datos.
DECLARE @fechaAñoCurso DATE= '20190101'; WITH cte AS (SELECT tbl.valor FROM (VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) AS tbl(valor)), fechas AS (SELECT fecha_ingreso , DATEDIFF(MONTH, '19000101', @fechaAñoCurso) AS CURSO , DATEDIFF(month, '19000101', fecha_ingreso) AS INGRESO , DATEDIFF(MONTH, '19000101', ISNULL(fecha_baja, '21000101')) AS BAJA , e.NumEmp FROM empleadosNominal e) SELECT SUM(CASE WHEN f.BAJA >= F.CURSO + cte.valor - 1 AND INGRESO < (CURSO + cte.valor) - 1 THEN 1 END) AS EmpleadosAlInicio , SUM(CASE WHEN f.BAJA >= F.CURSO + cte.valor AND INGRESO < (CURSO + cte.valor) THEN 1 END) AS EmpleadosAlFinal , cte.valor as Mes FROM fechas f CROSS JOIN cte GROUP BY cte.VALOR;
Declare una variable de tabla con la fecha inicial del año en curso, porque esa fecha, la voy a utilizar como desplazamiento.
Utilizo la diferencia en meses entre una fecha inicial, '01/01/1900' y en este caso, el primer día del mes del año 2019.
De la tabla de empleados, obtengo la misma diferencia también en meses para la fecha de ingreso y para la fecha de baja. (si no hay baja, fuerzo una fecha para comparar numéricamente).
Luego con la salida de estos conjuntos, realizo el cross join ya mencionado de empleados con meses.
De ello realizo una suma cuando el empleado no esta de baja en el mes en curso, y ya había ingresado, Y en la otra columna lo mismo, pero si restarle el desplazamiento del mes.
Espero se parezca en algo a lo que buscas.
Salida
Ctes correlativos
https://javifer2.blogspot.com/2019/01/with-cte-tablas-de-expresion-comun-2.html
Cross join
https://javifer2.blogspot.com/search/label/cross%20join
DateDiff
https://docs.microsoft.com/es-es/sql/t-sql/functions/datediff-transact-sql?view=sql-server-2017
- Propuesto como respuesta Carlos_Ruiz_M martes, 4 de junio de 2019 20:19
-
Muchas gracias, creo que va por ahí, pero tienes razón en lo de explicar mejor mi escenario, lo que necesito hacer es calcular la rotación de empleados, apoyándome con el área de Recursos Humanos, me indican que la rotación se calcula con la siguiente formula:
Total de Ingresos en el mes + Total de Bajas en el mes X 100 2 Plantilla Inicial + Plantilla Final 2 Que esto sería:
total de ingresos en el mes más total de bajas en el mes entre 2 por 100
El resultado lo dividimos con el resultado de Plantilla Inicial Mas Plantilla final entre dos.
Ojala me puedas ayudar, ahora ya me siento abusador, pero eso es lo que tengo que hacer y creo que mi experiencia en SQL no me alcanza aún, muchas gracias!
alozada
-
Hola alozada:
El problema no es la salida (que un poco si), donde tienes que mejorar para obtener el resultado correcto es en la definición. No es lo mismo que las columnas sean date, o datetime, o varchar. No has expuesto si vienen de una sola tabla....
La mejor manera para que el resultado sea siempre el apropiado, o lo más cercano posible, es poner la definición del origen. Si te fijas, yo te he puesto un créate table..... y una sentencia de inserción con múltiples valores.
Si otra persona en los foros, recoge el testigo de lo que yo te he respondido, ya tiene parte del trabajo hecho para poder aportar otra vía. Si esto que yo he realizado, lo haces tú, siempre tendrás una mejor posibilidad de ayuda.
Una posible solución:
DECLARE @fechaAñoCurso DATE= '20190101'; WITH cte AS (SELECT tbl.valor FROM (VALUES(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) AS tbl(valor)), fechas AS (SELECT fecha_ingreso , DATEDIFF(MONTH, '19000101', @fechaAñoCurso) AS CURSO , DATEDIFF(month, '19000101', fecha_ingreso) AS INGRESO , DATEDIFF(MONTH, '19000101', ISNULL(fecha_baja, '21000101')) AS BAJA , e.NumEmp FROM empleadosNominal e), agrupado AS (SELECT SUM(CASE WHEN f.BAJA >= F.CURSO + cte.valor - 1 AND INGRESO < (CURSO + cte.valor) - 1 THEN 1 END) AS EmpleadosAlInicio , SUM(CASE WHEN f.BAJA >= F.CURSO + cte.valor AND INGRESO < (CURSO + cte.valor) THEN 1 END) AS EmpleadosAlFinal , cte.valor AS Mes FROM fechas f CROSS JOIN cte GROUP BY cte.VALOR) SELECT a.EmpleadosAlInicio , a.EmpleadosAlFinal , a.Mes , (a.EmpleadosAlInicio + a.EmpleadosAlFinal) as suma , ((a.EmpleadosAlInicio + a.EmpleadosAlFinal)*(1.0)) as sumaConDecimales , ((((a.EmpleadosAlInicio + a.EmpleadosAlFinal)*(1.0)) / 2) * 100) as resultado FROM agrupado a;
Puedes quitar las columnas innecesarias, solo te lo he plasmado, paso por paso, en cada columna para que veas como se puede resolver.
Ya comentas si la solución es lo deseado
- Marcado como respuesta Tonatiuh AbregoModerator martes, 11 de junio de 2019 14:14