Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Way to find data of a sql table with same status for consecutive 3 days

I have a SQL table like Below

Code Name    DayStatus  Date
101  John    A          20-May-2018
101  John    A          19-May-2018
101  John    A          18-May-2018
102  Karl    A          20-May-2018
102  Karl    A          19-May-2018
102  Karl    P          18-May-2018
103  Lorem   P          20-May-2018
103  Lorem   A          19-May-2018
103  Lorem   A          18-May-2018
104  Ipsum   A          20-May-2018
104  Ipsum   P          19-May-2018
104  Ipsum   A          18-May-2018
105  Milton  A          20-May-2018
105  Milton  A          19-May-2018
105  Milton  A          18-May-2018
107  Saleh   A          20-May-2018
107  Saleh   A          19-May-2018
107  Saleh   W          18-May-2018
107  Saleh   A          17-May-2018
108  Virat   A          20-May-2018
108  Virat   H          19-May-2018
108  Virat   A          18-May-2018
108  Virat   A          17-May-2018

Here "A" stands for Absent, "P" stands for the present, "H" is stand for Holiday, "W" stands for the weak off.

From the table, I need to figure out the employees who are consecutively absent for 3 days and It only calculable when employees today's day status is A(absent).

For virat and saleh it will also count as consecutive Absent.But if P(present) will appear in between consecutive day's then it not count as consecutive absent.

The expected output should be---

Code Name    
101  John          
105  Milton          
107  Saleh             
108  Virat       
like image 997
Abdullah Al Mamun Avatar asked May 20 '18 07:05

Abdullah Al Mamun


People also ask

How do you find consecutive data in SQL?

Using DENSE_RANK We're going to use the DENSE_RANK function to help create an identifier to group values that are part of a sequence. Begin by applying the DENSE_RANK function to the rows. To produce the group identifier, we subtract the result of DENSE_RANK from the row value.

How can get last 30 days data from a table in SQL Server?

How do I find last 30 days in SQL? SELECT * FROM product WHERE pdate >= DATEADD(day, -30, getdate()).

What does CTE do in SQL?

The common table expression (CTE) is a powerful construct in SQL that helps simplify a query. CTEs work as virtual tables (with records and columns), created during the execution of a query, used by the query, and eliminated after query execution.


1 Answers

Try a query from this demo

SELECT code, name, count(*) absent_days
FROM (
  SELECT *,
        sum( xx ) over (partition by code order by date ) ss
  FROM (
    SELECT *,
          case when DayStatus = lag(DayStatus) over(partition by code order by Date)
               then 0 else 1
          end as xx
    FROM table1
    WHERE DayStatus not in( 'W','H')
  ) x
) y
WHERE DayStatus = 'A'
GROUP BY code, name, ss
HAVING count(*) >=3
order by code

| code |   name |     absent_days |
|------|--------|-----------------|
|  101 |   John |               3 |
|  105 | Milton |               3 |
|  107 |  Saleh |               3 |
|  108 |  Virat |               3 |

This version gives a count of days and a beginning date of each period

    SELECT code, name, count(*) absent_days, min(date) from_date
    FROM (
      SELECT *,
            sum( xx ) over (partition by code order by date ) ss
      FROM (
        SELECT *,
              case when DayStatus = lag(DayStatus) over(partition by code order by Date)
                   then 0 else 1
              end as xx
        FROM table1
        WHERE DayStatus not in( 'W','H')
      ) x
    ) y
    WHERE DayStatus = 'A'
    GROUP BY code, name, ss
    HAVING count(*) >=3
    order by code

| code |   name | absent_days |            from_date |
|------|--------|-------------|----------------------|
|  101 |   John |           3 | 2018-05-18T00:00:00Z |
|  105 | Milton |           3 | 2018-05-18T00:00:00Z |
|  107 |  Saleh |           3 | 2018-05-17T00:00:00Z |
|  108 |  Virat |           3 | 2018-05-17T00:00:00Z |
like image 67
krokodilko Avatar answered Sep 24 '22 14:09

krokodilko