Сумма больничных листов по месяцам - PullRequest
0 голосов
/ 08 ноября 2019

Сотрудники получают больничные листы по датам. Поэтому они установили диапазон следующим образом.

Employees Sick Leaves

Я бы хотел, чтобы данные отображались следующим образом.

Result should look like this

Мне удалось представить запрос следующим образом, но я не знал, как его изменить, чтобы получить данные, которыми я поделился.

SELECT MONTH(t.FromDate) AS [Month], FORMAT(t.FromDate, 'MMM') AS [MonthName],
       SUM(DATEDIFF(DAY,t.FromDate,t.ToDate)+1) AS [AbsenceCount] 
FROM Test AS t
GROUP BY FORMAT(t.FromDate, 'MMM'), MONTH(t.FromDate)
ORDER BY MONTH(t.FromDate)

Ответы [ 3 ]

1 голос
/ 08 ноября 2019

Диапазон дат можно построить с помощью CTE, после чего вы можете СОЕДИНИТЬ свои отсутствия с датами, которые попадают в пределы отсутствия. Затем просто посчитайте эти даты и сгруппируйте их по году и месяцу даты.

Я узнал, как преобразовать номер вашего месяца в текст. Вы можете взять ЛЕВЫЙ (..., 3) из этого, если хотите.

WITH  DATRANGE AS (SELECT MIN((FromDate)) as startDate, max(ToDate) endDate From Test),
      YourCal AS (SELECT startDate d FROM DATRANGE 
                  UNION ALL
                  SELECT DATEADD(day,1,d) d FROM YourCal, DATRANGE WHERE d < enddate
                 )
        SELECT T.empid, 
                YEAR(Y.d), 
                DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))) As M,
                COUNT(1) As DayCount 
                        FROM TEST T JOIN 
                                    YourCal Y 
                                            ON Y.d BETWEEN FromDate AND ToDate
        GROUP BY T.empid,YEAR(Y.d),DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))),MONTH(y.d)
        ORDER BY empid, YEAR(y.d), MONTH(y.d)
        option (maxrecursion 0);

с метками из 3 буквенных месяцев, это будет

WITH  DATRANGE AS (SELECT MIN((FromDate)) as startDate, max(ToDate) endDate From Test),
      YourCal AS (SELECT startDate d FROM DATRANGE 
                  UNION ALL
                  SELECT DATEADD(day,1,d) d FROM YourCal, DATRANGE WHERE d < enddate
                 )
        SELECT T.empid, 
                YEAR(Y.d) Yr, 
                LEFT(DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))),3) As M,
                COUNT(1) As DayCount 
                        FROM TEST T JOIN 
                                    YourCal Y 
                                            ON Y.d BETWEEN FromDate AND ToDate
        GROUP BY T.empid,
                YEAR(Y.d),
                LEFT(DATENAME(month, DATEADD(month, MONTH(y.d)-1, CAST('2008-01-01' AS datetime))),3),
                MONTH(y.d)
        ORDER BY empid, YEAR(y.d), MONTH(y.d)
        option (maxrecursion 0);
0 голосов
/ 08 ноября 2019

РЕДАКТИРОВАТЬ : Используйте этот запрос для решения вашего варианта использования (работает для MySQL, прежде чем имя БД было указано в вопросе):

CREATE TABLE Calendar_Table(
  dt DATE
);

INSERT INTO Calendar_Table VALUES
("2019-01-01"), ("2019-01-02"), ("2019-01-03"), ...

CREATE TABLE Sick_Leave (
  EmpId INT,
  FromDate DATE,
  ToDate DATE
);

INSERT INTO Sick_Leave VALUES
(1, "2019-01-01", "2019-01-31"),
(2, "2019-02-01", "2019-02-28"),
(3, "2019-03-01", "2019-05-01");

SELECT 
    x.month, COUNT(*) AS cnt 
FROM ( 
    SELECT 
        a.EmpID,
        b.dt AS FromDate,
        SUBSTRING_INDEX(b.dt, "-", 2) AS month
    FROM
        Sick_Leave a 
    JOIN 
        Calendar_Table b
    WHERE (b.dt BETWEEN a.FromDate AND a.ToDate)
) x 
GROUP BY 
    x.month;

Вы можете обратиться к этомуSQLFiddle ссылка для решения. : http://sqlfiddle.com/#!9/0ebafe/5

enter image description here

Однако можно использовать еще одно вычисление из case statements или another lookup table для преобразования результата *От 1019 * до Jan.

Для SQL Server : Это ссылка SQL Fiddle для БД SQL Server: http://sqlfiddle.com/#!18/8dae7/6

0 голосов
/ 08 ноября 2019

Единственное решение, которое я вижу, - это присоединиться к таблице calendar, содержащей все даты. Вы должны сами понять, как вы хотите создать эту таблицу. Я обычно генерирую это в php-скрипте.

select month(c.date)
,      count(*)
from calendar c
join test t on c.date >= t.FromDate 
            and c.date <= t.ToDate
group by month(c.date)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...