Search code examples
sqlsql-serverdatabasesql-query-store

sql query with multiple headers and multiple counts


I have a table with client task details (attached picture). I want result like number of tasks received for a particular month for each client, no. of tasks completed within 5days from the start date and its compliance. could someone help with a SQL query

enter image description here

client | No.of tasks of a month | No.of tasks completed on time | % of compliance
A      | 5                      | 4                             | 75%

Solution

  • About your last comment, this is a minimal, not-production-ready, idea:

    suppose you have a combobox for months and year

    cbYear.DataSource = new int[] { 2017, 2018, 2019 };
    cbMonth.DataSource = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dec" };
    

    and a datagridview dgv, you can do something like this (in a button)

            SqlConnection con = new SqlConnection("Data Source=(LocalDb)\\MSSQLLocalDB;Initial Catalog=test;Integrated Security=SSPI");
            con.Open();
            SqlCommand cmd = con.CreateCommand();
            cmd.CommandText = @"
    select 
        x.Client
    ,   x.MonthTasks
    ,   x.CompletedOnTime
    ,   Compliance = x.CompletedOnTime * 100 / x.MonthTasks
    from (
        select 
            t.Client
       ,    MonthTasks = Count(1)
       ,    CompletedOnTime = SUM(CASE WHEN DATEDIFF(day, t.TaskStart, t.TaskEnd)<=5 THEN 1 ELSE 0 END)
       from tasks as t
       where
            year(t.TaskStart) = @year
       and month(t.TaskStart) = @month
       group by t.Client
    ) as x
    order by x.Client
            ";
    
            cmd.Parameters.AddWithValue("@year", cbYear.SelectedItem);
            cmd.Parameters.AddWithValue("@month", cbMonth.SelectedIndex +1);
    
            var dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            var dt = new DataTable();
            dt.Load(dr);
    
            dgv.AutoGenerateColumns = true;
            dgv.DataSource = dt;
            dgv.Refresh();
    

    I repeat you have to catch any errors, maybe transform the query in a stored procedure, but this can be a starting point.