Group Customers by Status in T-SQL












6















I have a table like this:



customer_id mis_date  status
----------------------------
10003 2014-01-01 1
10003 2014-01-02 1
10003 2014-01-03 0
10003 2014-01-04 0
10003 2014-01-05 0
10003 2014-01-06 1
10003 2014-01-07 1
10003 2014-01-08 1
10003 2014-01-09 1
10003 2014-01-10 0
10003 2014-01-11 0
10003 2014-01-12 0
10003 2014-01-13 1
10003 2014-01-14 1
10003 2014-01-15 1


I'm trying to build the "group" column:



customer_id mis_date status group
----------------------------------
10003 2014-01-01 1 1
10003 2014-01-02 1 1
10003 2014-01-03 0 NULL
10003 2014-01-04 0 NULL
10003 2014-01-05 0 NULL
10003 2014-01-06 1 2
10003 2014-01-07 1 2
10003 2014-01-08 1 2
10003 2014-01-09 1 2
10003 2014-01-10 0 NULL
10003 2014-01-11 0 NULL
10003 2014-01-12 0 NULL
10003 2014-01-13 1 3
10003 2014-01-14 1 3
10003 2014-01-15 1 3


Does anyone know how I can build this group column?



The logic: each day I'm tracking after the customer status and I want to know in each day what is the number of times that that status happened in the customer history but only when he is in the status.



For example: first_time - 1, second_time - 2 etc.



I am kicking my head off and can't find a solution. I guess it's not so complex.



Thanks!










share|improve this question

























  • Seems like you want a partition, not a group

    – Diego Rafael Souza
    Jan 27 at 11:31











  • I think this is the expected result, we need to know actual data and logic behind it

    – Simonare
    Jan 27 at 11:31











  • I've edit my post.

    – Jordan1200
    Jan 27 at 11:40











  • please explain more

    – Dumidu Udayanga
    Jan 27 at 11:44
















6















I have a table like this:



customer_id mis_date  status
----------------------------
10003 2014-01-01 1
10003 2014-01-02 1
10003 2014-01-03 0
10003 2014-01-04 0
10003 2014-01-05 0
10003 2014-01-06 1
10003 2014-01-07 1
10003 2014-01-08 1
10003 2014-01-09 1
10003 2014-01-10 0
10003 2014-01-11 0
10003 2014-01-12 0
10003 2014-01-13 1
10003 2014-01-14 1
10003 2014-01-15 1


I'm trying to build the "group" column:



customer_id mis_date status group
----------------------------------
10003 2014-01-01 1 1
10003 2014-01-02 1 1
10003 2014-01-03 0 NULL
10003 2014-01-04 0 NULL
10003 2014-01-05 0 NULL
10003 2014-01-06 1 2
10003 2014-01-07 1 2
10003 2014-01-08 1 2
10003 2014-01-09 1 2
10003 2014-01-10 0 NULL
10003 2014-01-11 0 NULL
10003 2014-01-12 0 NULL
10003 2014-01-13 1 3
10003 2014-01-14 1 3
10003 2014-01-15 1 3


Does anyone know how I can build this group column?



The logic: each day I'm tracking after the customer status and I want to know in each day what is the number of times that that status happened in the customer history but only when he is in the status.



For example: first_time - 1, second_time - 2 etc.



I am kicking my head off and can't find a solution. I guess it's not so complex.



Thanks!










share|improve this question

























  • Seems like you want a partition, not a group

    – Diego Rafael Souza
    Jan 27 at 11:31











  • I think this is the expected result, we need to know actual data and logic behind it

    – Simonare
    Jan 27 at 11:31











  • I've edit my post.

    – Jordan1200
    Jan 27 at 11:40











  • please explain more

    – Dumidu Udayanga
    Jan 27 at 11:44














6












6








6


3






I have a table like this:



customer_id mis_date  status
----------------------------
10003 2014-01-01 1
10003 2014-01-02 1
10003 2014-01-03 0
10003 2014-01-04 0
10003 2014-01-05 0
10003 2014-01-06 1
10003 2014-01-07 1
10003 2014-01-08 1
10003 2014-01-09 1
10003 2014-01-10 0
10003 2014-01-11 0
10003 2014-01-12 0
10003 2014-01-13 1
10003 2014-01-14 1
10003 2014-01-15 1


I'm trying to build the "group" column:



customer_id mis_date status group
----------------------------------
10003 2014-01-01 1 1
10003 2014-01-02 1 1
10003 2014-01-03 0 NULL
10003 2014-01-04 0 NULL
10003 2014-01-05 0 NULL
10003 2014-01-06 1 2
10003 2014-01-07 1 2
10003 2014-01-08 1 2
10003 2014-01-09 1 2
10003 2014-01-10 0 NULL
10003 2014-01-11 0 NULL
10003 2014-01-12 0 NULL
10003 2014-01-13 1 3
10003 2014-01-14 1 3
10003 2014-01-15 1 3


Does anyone know how I can build this group column?



The logic: each day I'm tracking after the customer status and I want to know in each day what is the number of times that that status happened in the customer history but only when he is in the status.



For example: first_time - 1, second_time - 2 etc.



I am kicking my head off and can't find a solution. I guess it's not so complex.



Thanks!










share|improve this question
















I have a table like this:



customer_id mis_date  status
----------------------------
10003 2014-01-01 1
10003 2014-01-02 1
10003 2014-01-03 0
10003 2014-01-04 0
10003 2014-01-05 0
10003 2014-01-06 1
10003 2014-01-07 1
10003 2014-01-08 1
10003 2014-01-09 1
10003 2014-01-10 0
10003 2014-01-11 0
10003 2014-01-12 0
10003 2014-01-13 1
10003 2014-01-14 1
10003 2014-01-15 1


I'm trying to build the "group" column:



customer_id mis_date status group
----------------------------------
10003 2014-01-01 1 1
10003 2014-01-02 1 1
10003 2014-01-03 0 NULL
10003 2014-01-04 0 NULL
10003 2014-01-05 0 NULL
10003 2014-01-06 1 2
10003 2014-01-07 1 2
10003 2014-01-08 1 2
10003 2014-01-09 1 2
10003 2014-01-10 0 NULL
10003 2014-01-11 0 NULL
10003 2014-01-12 0 NULL
10003 2014-01-13 1 3
10003 2014-01-14 1 3
10003 2014-01-15 1 3


Does anyone know how I can build this group column?



The logic: each day I'm tracking after the customer status and I want to know in each day what is the number of times that that status happened in the customer history but only when he is in the status.



For example: first_time - 1, second_time - 2 etc.



I am kicking my head off and can't find a solution. I guess it's not so complex.



Thanks!







sql sql-server






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 27 at 12:13









marc_s

577k12911141259




577k12911141259










asked Jan 27 at 11:25









Jordan1200Jordan1200

17111




17111













  • Seems like you want a partition, not a group

    – Diego Rafael Souza
    Jan 27 at 11:31











  • I think this is the expected result, we need to know actual data and logic behind it

    – Simonare
    Jan 27 at 11:31











  • I've edit my post.

    – Jordan1200
    Jan 27 at 11:40











  • please explain more

    – Dumidu Udayanga
    Jan 27 at 11:44



















  • Seems like you want a partition, not a group

    – Diego Rafael Souza
    Jan 27 at 11:31











  • I think this is the expected result, we need to know actual data and logic behind it

    – Simonare
    Jan 27 at 11:31











  • I've edit my post.

    – Jordan1200
    Jan 27 at 11:40











  • please explain more

    – Dumidu Udayanga
    Jan 27 at 11:44

















Seems like you want a partition, not a group

– Diego Rafael Souza
Jan 27 at 11:31





Seems like you want a partition, not a group

– Diego Rafael Souza
Jan 27 at 11:31













I think this is the expected result, we need to know actual data and logic behind it

– Simonare
Jan 27 at 11:31





I think this is the expected result, we need to know actual data and logic behind it

– Simonare
Jan 27 at 11:31













I've edit my post.

– Jordan1200
Jan 27 at 11:40





I've edit my post.

– Jordan1200
Jan 27 at 11:40













please explain more

– Dumidu Udayanga
Jan 27 at 11:44





please explain more

– Dumidu Udayanga
Jan 27 at 11:44












5 Answers
5






active

oldest

votes


















3














Something like this should work:



;WITH CTE AS (
SELECT customer_id, mis_date, status,
ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY mis_date) -
ROW_NUMBER() OVER (PARTITION BY customer_id, status ORDER BY mis_date) AS grp
FROM mytable
), CTE2 AS (
SELECT customer_id, status, grp,
ROW_NUMBER() OVER (ORDER BY MIN(mis_date)) AS rn
FROM CTE
WHERE status = 1
GROUP BY customer_id, status, grp
)
SELECT c.customer_id, c.mis_date, c.status, rn
FROM CTE c
LEFT JOIN CTE2 c2
ON c.customer_id = c2.customer_id AND c.status = c2.status AND c.grp = c2.grp
ORDER BY mis_date


CTE identifies islands of consecutive records having the same status value. CTE2 enumerates status = 1 subgroups.






share|improve this answer































    3














    Another approach of doing it without CTE is like following query.



    SELECT customer_id, mis_date, status, 
    CASE WHEN status = 0 THEN NULL ELSE Dense_rank() OVER (ORDER BY rc) END grp
    FROM (SELECT *,
    (SELECT CASE WHEN status = 0 THEN 0
    ELSE (SELECT Count(status) FROM table1 t2
    WHERE t2.mis_date <= t1.mis_date AND status = 0) END grp)rc
    FROM table1 t1) t2
    ORDER BY mis_date


    Output:



    +-------------+-------------------------+--------+------+
    | customer_id | mis_date | status | grp |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-01 00:00:00.000 | 1 | 1 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-02 00:00:00.000 | 1 | 1 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-03 00:00:00.000 | 0 | NULL |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-04 00:00:00.000 | 0 | NULL |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-05 00:00:00.000 | 0 | NULL |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-06 00:00:00.000 | 1 | 2 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-07 00:00:00.000 | 1 | 2 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-08 00:00:00.000 | 1 | 2 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-09 00:00:00.000 | 1 | 2 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-10 00:00:00.000 | 0 | NULL |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-11 00:00:00.000 | 0 | NULL |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-12 00:00:00.000 | 0 | NULL |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-13 00:00:00.000 | 1 | 3 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-14 00:00:00.000 | 1 | 3 |
    +-------------+-------------------------+--------+------+
    | 10003 | 2014-01-15 00:00:00.000 | 1 | 3 |
    +-------------+-------------------------+--------+------+


    Online Demo






    share|improve this answer

































      2














      Check this solution please. This adds grouping as per your need



       with cte0 as 
      (
      select [customer_id], [mis_date], [status],
      COALESCE(LAG(status) over (order by mis_date), status) oldstatus
      FRom Table1
      ),
      cte1 as (
      select cte0.*,
      case when status = 0 then
      null
      else
      COUNT( case when status != oldStatus and status = 0 then 1 else null end) OVER (ORDER BY mis_date)
      end + 1 grp
      from cte0
      )
      select * from cte1
      GO




      customer_id | mis_date | status | oldstatus | grp
      ----------: | :------------------ | -----: | --------: | ---:
      10003 | 01/01/2014 00:00:00 | 1 | 1 | 1
      10003 | 02/01/2014 00:00:00 | 1 | 1 | 1
      10003 | 03/01/2014 00:00:00 | 0 | 1 | null
      10003 | 04/01/2014 00:00:00 | 0 | 0 | null
      10003 | 05/01/2014 00:00:00 | 0 | 0 | null
      10003 | 06/01/2014 00:00:00 | 1 | 0 | 2
      10003 | 07/01/2014 00:00:00 | 1 | 1 | 2
      10003 | 08/01/2014 00:00:00 | 1 | 1 | 2
      10003 | 09/01/2014 00:00:00 | 1 | 1 | 2
      10003 | 10/01/2014 00:00:00 | 0 | 1 | null
      10003 | 11/01/2014 00:00:00 | 0 | 0 | null
      10003 | 12/01/2014 00:00:00 | 0 | 0 | null
      10003 | 13/01/2014 00:00:00 | 1 | 0 | 3
      10003 | 14/01/2014 00:00:00 | 1 | 1 | 3
      10003 | 15/01/2014 00:00:00 | 1 | 1 | 3


      Working Fiddle






      share|improve this answer

































        1














        You can identify each group of "1" by the number of non-zero statuses before them. If you don't care that the group numbers are sequential:



        select t.*,
        (case when status = 1
        then sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date)
        end) as grp
        from t;


        No subqueries, joins or aggregation.



        However, you probably want the numbers sequential (as in your example). For that, a subquery is needed:



        select t.*,
        (case when status = 1
        then dense_rank() over (partition by customer_id order by grp1)
        end) as grp
        from (select t.*,
        sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date) as grp1
        from t
        ) t





        share|improve this answer


























        • just as FYI, I think there are some syntax error partition by order by customer_id mis_date

          – Avi
          Jan 27 at 18:52













        • @Avi . . . Thank you.

          – Gordon Linoff
          Jan 27 at 21:11



















        0














        You can use the ALTER TABLE statement in SQL Server to add a column to a table.
        Syntax



        The syntax to add a column in a table in SQL Server (Transact-SQL) is:



        ALTER TABLE table_name
        ADD column_name column_definition;


        Let's look at an example that shows how to add a column in an SQL Server table using the ALTER TABLE statement.



        For example:



        ALTER TABLE customer
        ADD group VARCHAR(10);


        This SQL Server ALTER TABLE example will add a column to the customer table called group.






        share|improve this answer
























        • Thank's but you missed understood me. I want to generate the values in the column.

          – Jordan1200
          Jan 27 at 11:42











        • Can't understand, could you please explain more

          – Dumidu Udayanga
          Jan 27 at 11:43











        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54387610%2fgroup-customers-by-status-in-t-sql%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        5 Answers
        5






        active

        oldest

        votes








        5 Answers
        5






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        3














        Something like this should work:



        ;WITH CTE AS (
        SELECT customer_id, mis_date, status,
        ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY mis_date) -
        ROW_NUMBER() OVER (PARTITION BY customer_id, status ORDER BY mis_date) AS grp
        FROM mytable
        ), CTE2 AS (
        SELECT customer_id, status, grp,
        ROW_NUMBER() OVER (ORDER BY MIN(mis_date)) AS rn
        FROM CTE
        WHERE status = 1
        GROUP BY customer_id, status, grp
        )
        SELECT c.customer_id, c.mis_date, c.status, rn
        FROM CTE c
        LEFT JOIN CTE2 c2
        ON c.customer_id = c2.customer_id AND c.status = c2.status AND c.grp = c2.grp
        ORDER BY mis_date


        CTE identifies islands of consecutive records having the same status value. CTE2 enumerates status = 1 subgroups.






        share|improve this answer




























          3














          Something like this should work:



          ;WITH CTE AS (
          SELECT customer_id, mis_date, status,
          ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY mis_date) -
          ROW_NUMBER() OVER (PARTITION BY customer_id, status ORDER BY mis_date) AS grp
          FROM mytable
          ), CTE2 AS (
          SELECT customer_id, status, grp,
          ROW_NUMBER() OVER (ORDER BY MIN(mis_date)) AS rn
          FROM CTE
          WHERE status = 1
          GROUP BY customer_id, status, grp
          )
          SELECT c.customer_id, c.mis_date, c.status, rn
          FROM CTE c
          LEFT JOIN CTE2 c2
          ON c.customer_id = c2.customer_id AND c.status = c2.status AND c.grp = c2.grp
          ORDER BY mis_date


          CTE identifies islands of consecutive records having the same status value. CTE2 enumerates status = 1 subgroups.






          share|improve this answer


























            3












            3








            3







            Something like this should work:



            ;WITH CTE AS (
            SELECT customer_id, mis_date, status,
            ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY mis_date) -
            ROW_NUMBER() OVER (PARTITION BY customer_id, status ORDER BY mis_date) AS grp
            FROM mytable
            ), CTE2 AS (
            SELECT customer_id, status, grp,
            ROW_NUMBER() OVER (ORDER BY MIN(mis_date)) AS rn
            FROM CTE
            WHERE status = 1
            GROUP BY customer_id, status, grp
            )
            SELECT c.customer_id, c.mis_date, c.status, rn
            FROM CTE c
            LEFT JOIN CTE2 c2
            ON c.customer_id = c2.customer_id AND c.status = c2.status AND c.grp = c2.grp
            ORDER BY mis_date


            CTE identifies islands of consecutive records having the same status value. CTE2 enumerates status = 1 subgroups.






            share|improve this answer













            Something like this should work:



            ;WITH CTE AS (
            SELECT customer_id, mis_date, status,
            ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY mis_date) -
            ROW_NUMBER() OVER (PARTITION BY customer_id, status ORDER BY mis_date) AS grp
            FROM mytable
            ), CTE2 AS (
            SELECT customer_id, status, grp,
            ROW_NUMBER() OVER (ORDER BY MIN(mis_date)) AS rn
            FROM CTE
            WHERE status = 1
            GROUP BY customer_id, status, grp
            )
            SELECT c.customer_id, c.mis_date, c.status, rn
            FROM CTE c
            LEFT JOIN CTE2 c2
            ON c.customer_id = c2.customer_id AND c.status = c2.status AND c.grp = c2.grp
            ORDER BY mis_date


            CTE identifies islands of consecutive records having the same status value. CTE2 enumerates status = 1 subgroups.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 27 at 11:45









            Giorgos BetsosGiorgos Betsos

            61.8k73064




            61.8k73064

























                3














                Another approach of doing it without CTE is like following query.



                SELECT customer_id, mis_date, status, 
                CASE WHEN status = 0 THEN NULL ELSE Dense_rank() OVER (ORDER BY rc) END grp
                FROM (SELECT *,
                (SELECT CASE WHEN status = 0 THEN 0
                ELSE (SELECT Count(status) FROM table1 t2
                WHERE t2.mis_date <= t1.mis_date AND status = 0) END grp)rc
                FROM table1 t1) t2
                ORDER BY mis_date


                Output:



                +-------------+-------------------------+--------+------+
                | customer_id | mis_date | status | grp |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-01 00:00:00.000 | 1 | 1 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-02 00:00:00.000 | 1 | 1 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-03 00:00:00.000 | 0 | NULL |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-04 00:00:00.000 | 0 | NULL |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-05 00:00:00.000 | 0 | NULL |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-06 00:00:00.000 | 1 | 2 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-07 00:00:00.000 | 1 | 2 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-08 00:00:00.000 | 1 | 2 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-09 00:00:00.000 | 1 | 2 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-10 00:00:00.000 | 0 | NULL |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-11 00:00:00.000 | 0 | NULL |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-12 00:00:00.000 | 0 | NULL |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-13 00:00:00.000 | 1 | 3 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-14 00:00:00.000 | 1 | 3 |
                +-------------+-------------------------+--------+------+
                | 10003 | 2014-01-15 00:00:00.000 | 1 | 3 |
                +-------------+-------------------------+--------+------+


                Online Demo






                share|improve this answer






























                  3














                  Another approach of doing it without CTE is like following query.



                  SELECT customer_id, mis_date, status, 
                  CASE WHEN status = 0 THEN NULL ELSE Dense_rank() OVER (ORDER BY rc) END grp
                  FROM (SELECT *,
                  (SELECT CASE WHEN status = 0 THEN 0
                  ELSE (SELECT Count(status) FROM table1 t2
                  WHERE t2.mis_date <= t1.mis_date AND status = 0) END grp)rc
                  FROM table1 t1) t2
                  ORDER BY mis_date


                  Output:



                  +-------------+-------------------------+--------+------+
                  | customer_id | mis_date | status | grp |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-01 00:00:00.000 | 1 | 1 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-02 00:00:00.000 | 1 | 1 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-03 00:00:00.000 | 0 | NULL |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-04 00:00:00.000 | 0 | NULL |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-05 00:00:00.000 | 0 | NULL |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-06 00:00:00.000 | 1 | 2 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-07 00:00:00.000 | 1 | 2 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-08 00:00:00.000 | 1 | 2 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-09 00:00:00.000 | 1 | 2 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-10 00:00:00.000 | 0 | NULL |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-11 00:00:00.000 | 0 | NULL |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-12 00:00:00.000 | 0 | NULL |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-13 00:00:00.000 | 1 | 3 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-14 00:00:00.000 | 1 | 3 |
                  +-------------+-------------------------+--------+------+
                  | 10003 | 2014-01-15 00:00:00.000 | 1 | 3 |
                  +-------------+-------------------------+--------+------+


                  Online Demo






                  share|improve this answer




























                    3












                    3








                    3







                    Another approach of doing it without CTE is like following query.



                    SELECT customer_id, mis_date, status, 
                    CASE WHEN status = 0 THEN NULL ELSE Dense_rank() OVER (ORDER BY rc) END grp
                    FROM (SELECT *,
                    (SELECT CASE WHEN status = 0 THEN 0
                    ELSE (SELECT Count(status) FROM table1 t2
                    WHERE t2.mis_date <= t1.mis_date AND status = 0) END grp)rc
                    FROM table1 t1) t2
                    ORDER BY mis_date


                    Output:



                    +-------------+-------------------------+--------+------+
                    | customer_id | mis_date | status | grp |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-01 00:00:00.000 | 1 | 1 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-02 00:00:00.000 | 1 | 1 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-03 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-04 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-05 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-06 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-07 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-08 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-09 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-10 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-11 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-12 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-13 00:00:00.000 | 1 | 3 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-14 00:00:00.000 | 1 | 3 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-15 00:00:00.000 | 1 | 3 |
                    +-------------+-------------------------+--------+------+


                    Online Demo






                    share|improve this answer















                    Another approach of doing it without CTE is like following query.



                    SELECT customer_id, mis_date, status, 
                    CASE WHEN status = 0 THEN NULL ELSE Dense_rank() OVER (ORDER BY rc) END grp
                    FROM (SELECT *,
                    (SELECT CASE WHEN status = 0 THEN 0
                    ELSE (SELECT Count(status) FROM table1 t2
                    WHERE t2.mis_date <= t1.mis_date AND status = 0) END grp)rc
                    FROM table1 t1) t2
                    ORDER BY mis_date


                    Output:



                    +-------------+-------------------------+--------+------+
                    | customer_id | mis_date | status | grp |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-01 00:00:00.000 | 1 | 1 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-02 00:00:00.000 | 1 | 1 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-03 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-04 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-05 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-06 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-07 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-08 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-09 00:00:00.000 | 1 | 2 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-10 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-11 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-12 00:00:00.000 | 0 | NULL |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-13 00:00:00.000 | 1 | 3 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-14 00:00:00.000 | 1 | 3 |
                    +-------------+-------------------------+--------+------+
                    | 10003 | 2014-01-15 00:00:00.000 | 1 | 3 |
                    +-------------+-------------------------+--------+------+


                    Online Demo







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jan 27 at 12:33

























                    answered Jan 27 at 12:11









                    PSKPSK

                    10.4k31532




                    10.4k31532























                        2














                        Check this solution please. This adds grouping as per your need



                         with cte0 as 
                        (
                        select [customer_id], [mis_date], [status],
                        COALESCE(LAG(status) over (order by mis_date), status) oldstatus
                        FRom Table1
                        ),
                        cte1 as (
                        select cte0.*,
                        case when status = 0 then
                        null
                        else
                        COUNT( case when status != oldStatus and status = 0 then 1 else null end) OVER (ORDER BY mis_date)
                        end + 1 grp
                        from cte0
                        )
                        select * from cte1
                        GO




                        customer_id | mis_date | status | oldstatus | grp
                        ----------: | :------------------ | -----: | --------: | ---:
                        10003 | 01/01/2014 00:00:00 | 1 | 1 | 1
                        10003 | 02/01/2014 00:00:00 | 1 | 1 | 1
                        10003 | 03/01/2014 00:00:00 | 0 | 1 | null
                        10003 | 04/01/2014 00:00:00 | 0 | 0 | null
                        10003 | 05/01/2014 00:00:00 | 0 | 0 | null
                        10003 | 06/01/2014 00:00:00 | 1 | 0 | 2
                        10003 | 07/01/2014 00:00:00 | 1 | 1 | 2
                        10003 | 08/01/2014 00:00:00 | 1 | 1 | 2
                        10003 | 09/01/2014 00:00:00 | 1 | 1 | 2
                        10003 | 10/01/2014 00:00:00 | 0 | 1 | null
                        10003 | 11/01/2014 00:00:00 | 0 | 0 | null
                        10003 | 12/01/2014 00:00:00 | 0 | 0 | null
                        10003 | 13/01/2014 00:00:00 | 1 | 0 | 3
                        10003 | 14/01/2014 00:00:00 | 1 | 1 | 3
                        10003 | 15/01/2014 00:00:00 | 1 | 1 | 3


                        Working Fiddle






                        share|improve this answer






























                          2














                          Check this solution please. This adds grouping as per your need



                           with cte0 as 
                          (
                          select [customer_id], [mis_date], [status],
                          COALESCE(LAG(status) over (order by mis_date), status) oldstatus
                          FRom Table1
                          ),
                          cte1 as (
                          select cte0.*,
                          case when status = 0 then
                          null
                          else
                          COUNT( case when status != oldStatus and status = 0 then 1 else null end) OVER (ORDER BY mis_date)
                          end + 1 grp
                          from cte0
                          )
                          select * from cte1
                          GO




                          customer_id | mis_date | status | oldstatus | grp
                          ----------: | :------------------ | -----: | --------: | ---:
                          10003 | 01/01/2014 00:00:00 | 1 | 1 | 1
                          10003 | 02/01/2014 00:00:00 | 1 | 1 | 1
                          10003 | 03/01/2014 00:00:00 | 0 | 1 | null
                          10003 | 04/01/2014 00:00:00 | 0 | 0 | null
                          10003 | 05/01/2014 00:00:00 | 0 | 0 | null
                          10003 | 06/01/2014 00:00:00 | 1 | 0 | 2
                          10003 | 07/01/2014 00:00:00 | 1 | 1 | 2
                          10003 | 08/01/2014 00:00:00 | 1 | 1 | 2
                          10003 | 09/01/2014 00:00:00 | 1 | 1 | 2
                          10003 | 10/01/2014 00:00:00 | 0 | 1 | null
                          10003 | 11/01/2014 00:00:00 | 0 | 0 | null
                          10003 | 12/01/2014 00:00:00 | 0 | 0 | null
                          10003 | 13/01/2014 00:00:00 | 1 | 0 | 3
                          10003 | 14/01/2014 00:00:00 | 1 | 1 | 3
                          10003 | 15/01/2014 00:00:00 | 1 | 1 | 3


                          Working Fiddle






                          share|improve this answer




























                            2












                            2








                            2







                            Check this solution please. This adds grouping as per your need



                             with cte0 as 
                            (
                            select [customer_id], [mis_date], [status],
                            COALESCE(LAG(status) over (order by mis_date), status) oldstatus
                            FRom Table1
                            ),
                            cte1 as (
                            select cte0.*,
                            case when status = 0 then
                            null
                            else
                            COUNT( case when status != oldStatus and status = 0 then 1 else null end) OVER (ORDER BY mis_date)
                            end + 1 grp
                            from cte0
                            )
                            select * from cte1
                            GO




                            customer_id | mis_date | status | oldstatus | grp
                            ----------: | :------------------ | -----: | --------: | ---:
                            10003 | 01/01/2014 00:00:00 | 1 | 1 | 1
                            10003 | 02/01/2014 00:00:00 | 1 | 1 | 1
                            10003 | 03/01/2014 00:00:00 | 0 | 1 | null
                            10003 | 04/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 05/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 06/01/2014 00:00:00 | 1 | 0 | 2
                            10003 | 07/01/2014 00:00:00 | 1 | 1 | 2
                            10003 | 08/01/2014 00:00:00 | 1 | 1 | 2
                            10003 | 09/01/2014 00:00:00 | 1 | 1 | 2
                            10003 | 10/01/2014 00:00:00 | 0 | 1 | null
                            10003 | 11/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 12/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 13/01/2014 00:00:00 | 1 | 0 | 3
                            10003 | 14/01/2014 00:00:00 | 1 | 1 | 3
                            10003 | 15/01/2014 00:00:00 | 1 | 1 | 3


                            Working Fiddle






                            share|improve this answer















                            Check this solution please. This adds grouping as per your need



                             with cte0 as 
                            (
                            select [customer_id], [mis_date], [status],
                            COALESCE(LAG(status) over (order by mis_date), status) oldstatus
                            FRom Table1
                            ),
                            cte1 as (
                            select cte0.*,
                            case when status = 0 then
                            null
                            else
                            COUNT( case when status != oldStatus and status = 0 then 1 else null end) OVER (ORDER BY mis_date)
                            end + 1 grp
                            from cte0
                            )
                            select * from cte1
                            GO




                            customer_id | mis_date | status | oldstatus | grp
                            ----------: | :------------------ | -----: | --------: | ---:
                            10003 | 01/01/2014 00:00:00 | 1 | 1 | 1
                            10003 | 02/01/2014 00:00:00 | 1 | 1 | 1
                            10003 | 03/01/2014 00:00:00 | 0 | 1 | null
                            10003 | 04/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 05/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 06/01/2014 00:00:00 | 1 | 0 | 2
                            10003 | 07/01/2014 00:00:00 | 1 | 1 | 2
                            10003 | 08/01/2014 00:00:00 | 1 | 1 | 2
                            10003 | 09/01/2014 00:00:00 | 1 | 1 | 2
                            10003 | 10/01/2014 00:00:00 | 0 | 1 | null
                            10003 | 11/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 12/01/2014 00:00:00 | 0 | 0 | null
                            10003 | 13/01/2014 00:00:00 | 1 | 0 | 3
                            10003 | 14/01/2014 00:00:00 | 1 | 1 | 3
                            10003 | 15/01/2014 00:00:00 | 1 | 1 | 3


                            Working Fiddle







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Jan 27 at 11:58

























                            answered Jan 27 at 11:53









                            SimonareSimonare

                            13.6k11738




                            13.6k11738























                                1














                                You can identify each group of "1" by the number of non-zero statuses before them. If you don't care that the group numbers are sequential:



                                select t.*,
                                (case when status = 1
                                then sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date)
                                end) as grp
                                from t;


                                No subqueries, joins or aggregation.



                                However, you probably want the numbers sequential (as in your example). For that, a subquery is needed:



                                select t.*,
                                (case when status = 1
                                then dense_rank() over (partition by customer_id order by grp1)
                                end) as grp
                                from (select t.*,
                                sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date) as grp1
                                from t
                                ) t





                                share|improve this answer


























                                • just as FYI, I think there are some syntax error partition by order by customer_id mis_date

                                  – Avi
                                  Jan 27 at 18:52













                                • @Avi . . . Thank you.

                                  – Gordon Linoff
                                  Jan 27 at 21:11
















                                1














                                You can identify each group of "1" by the number of non-zero statuses before them. If you don't care that the group numbers are sequential:



                                select t.*,
                                (case when status = 1
                                then sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date)
                                end) as grp
                                from t;


                                No subqueries, joins or aggregation.



                                However, you probably want the numbers sequential (as in your example). For that, a subquery is needed:



                                select t.*,
                                (case when status = 1
                                then dense_rank() over (partition by customer_id order by grp1)
                                end) as grp
                                from (select t.*,
                                sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date) as grp1
                                from t
                                ) t





                                share|improve this answer


























                                • just as FYI, I think there are some syntax error partition by order by customer_id mis_date

                                  – Avi
                                  Jan 27 at 18:52













                                • @Avi . . . Thank you.

                                  – Gordon Linoff
                                  Jan 27 at 21:11














                                1












                                1








                                1







                                You can identify each group of "1" by the number of non-zero statuses before them. If you don't care that the group numbers are sequential:



                                select t.*,
                                (case when status = 1
                                then sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date)
                                end) as grp
                                from t;


                                No subqueries, joins or aggregation.



                                However, you probably want the numbers sequential (as in your example). For that, a subquery is needed:



                                select t.*,
                                (case when status = 1
                                then dense_rank() over (partition by customer_id order by grp1)
                                end) as grp
                                from (select t.*,
                                sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date) as grp1
                                from t
                                ) t





                                share|improve this answer















                                You can identify each group of "1" by the number of non-zero statuses before them. If you don't care that the group numbers are sequential:



                                select t.*,
                                (case when status = 1
                                then sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date)
                                end) as grp
                                from t;


                                No subqueries, joins or aggregation.



                                However, you probably want the numbers sequential (as in your example). For that, a subquery is needed:



                                select t.*,
                                (case when status = 1
                                then dense_rank() over (partition by customer_id order by grp1)
                                end) as grp
                                from (select t.*,
                                sum(case when status = 0 then 1 else 0 end) over (partition by customer_id order by mis_date) as grp1
                                from t
                                ) t






                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited Jan 27 at 21:10

























                                answered Jan 27 at 14:19









                                Gordon LinoffGordon Linoff

                                776k35306409




                                776k35306409













                                • just as FYI, I think there are some syntax error partition by order by customer_id mis_date

                                  – Avi
                                  Jan 27 at 18:52













                                • @Avi . . . Thank you.

                                  – Gordon Linoff
                                  Jan 27 at 21:11



















                                • just as FYI, I think there are some syntax error partition by order by customer_id mis_date

                                  – Avi
                                  Jan 27 at 18:52













                                • @Avi . . . Thank you.

                                  – Gordon Linoff
                                  Jan 27 at 21:11

















                                just as FYI, I think there are some syntax error partition by order by customer_id mis_date

                                – Avi
                                Jan 27 at 18:52







                                just as FYI, I think there are some syntax error partition by order by customer_id mis_date

                                – Avi
                                Jan 27 at 18:52















                                @Avi . . . Thank you.

                                – Gordon Linoff
                                Jan 27 at 21:11





                                @Avi . . . Thank you.

                                – Gordon Linoff
                                Jan 27 at 21:11











                                0














                                You can use the ALTER TABLE statement in SQL Server to add a column to a table.
                                Syntax



                                The syntax to add a column in a table in SQL Server (Transact-SQL) is:



                                ALTER TABLE table_name
                                ADD column_name column_definition;


                                Let's look at an example that shows how to add a column in an SQL Server table using the ALTER TABLE statement.



                                For example:



                                ALTER TABLE customer
                                ADD group VARCHAR(10);


                                This SQL Server ALTER TABLE example will add a column to the customer table called group.






                                share|improve this answer
























                                • Thank's but you missed understood me. I want to generate the values in the column.

                                  – Jordan1200
                                  Jan 27 at 11:42











                                • Can't understand, could you please explain more

                                  – Dumidu Udayanga
                                  Jan 27 at 11:43
















                                0














                                You can use the ALTER TABLE statement in SQL Server to add a column to a table.
                                Syntax



                                The syntax to add a column in a table in SQL Server (Transact-SQL) is:



                                ALTER TABLE table_name
                                ADD column_name column_definition;


                                Let's look at an example that shows how to add a column in an SQL Server table using the ALTER TABLE statement.



                                For example:



                                ALTER TABLE customer
                                ADD group VARCHAR(10);


                                This SQL Server ALTER TABLE example will add a column to the customer table called group.






                                share|improve this answer
























                                • Thank's but you missed understood me. I want to generate the values in the column.

                                  – Jordan1200
                                  Jan 27 at 11:42











                                • Can't understand, could you please explain more

                                  – Dumidu Udayanga
                                  Jan 27 at 11:43














                                0












                                0








                                0







                                You can use the ALTER TABLE statement in SQL Server to add a column to a table.
                                Syntax



                                The syntax to add a column in a table in SQL Server (Transact-SQL) is:



                                ALTER TABLE table_name
                                ADD column_name column_definition;


                                Let's look at an example that shows how to add a column in an SQL Server table using the ALTER TABLE statement.



                                For example:



                                ALTER TABLE customer
                                ADD group VARCHAR(10);


                                This SQL Server ALTER TABLE example will add a column to the customer table called group.






                                share|improve this answer













                                You can use the ALTER TABLE statement in SQL Server to add a column to a table.
                                Syntax



                                The syntax to add a column in a table in SQL Server (Transact-SQL) is:



                                ALTER TABLE table_name
                                ADD column_name column_definition;


                                Let's look at an example that shows how to add a column in an SQL Server table using the ALTER TABLE statement.



                                For example:



                                ALTER TABLE customer
                                ADD group VARCHAR(10);


                                This SQL Server ALTER TABLE example will add a column to the customer table called group.







                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Jan 27 at 11:40









                                Dumidu UdayangaDumidu Udayanga

                                1528




                                1528













                                • Thank's but you missed understood me. I want to generate the values in the column.

                                  – Jordan1200
                                  Jan 27 at 11:42











                                • Can't understand, could you please explain more

                                  – Dumidu Udayanga
                                  Jan 27 at 11:43



















                                • Thank's but you missed understood me. I want to generate the values in the column.

                                  – Jordan1200
                                  Jan 27 at 11:42











                                • Can't understand, could you please explain more

                                  – Dumidu Udayanga
                                  Jan 27 at 11:43

















                                Thank's but you missed understood me. I want to generate the values in the column.

                                – Jordan1200
                                Jan 27 at 11:42





                                Thank's but you missed understood me. I want to generate the values in the column.

                                – Jordan1200
                                Jan 27 at 11:42













                                Can't understand, could you please explain more

                                – Dumidu Udayanga
                                Jan 27 at 11:43





                                Can't understand, could you please explain more

                                – Dumidu Udayanga
                                Jan 27 at 11:43


















                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54387610%2fgroup-customers-by-status-in-t-sql%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

                                Mangá

                                Eduardo VII do Reino Unido