problema en la creación de un rango de fechas

I have been creating a date range, but in some cases a have a problem:

This is what I have: TABLE_1

date          customer_id      status      total
----         -------------    --------    -------
20120201         1                a         10
20120202         1                a         20
20120203         1                b         20
20120204         1                b         20
20120205         1                a         20
20120206         1                a         20
20120201         2                d         30
20120202         2                e         40

After the execution of my procedure, I have this: TABLE_2

customer_id      status      start_date       end_date
-------------    --------    -----------      ---------
     1              a         20120201        NULL
     1              b         20120203        20120131
     2              d         20120201        20120201
     2              e         20120202        NULL

But this is what i want, a table with date ranges based on customer_id and status (end_date represents register with most recent date): TABLE_3

customer_id      status      start_date       end_date
-------------    --------    -----------      ---------
     1              a         20120201        20120202
     1              b         20120203        20120204
     1              a         20120205        NULL
     2              d         20120201        20120201
     2              e         20120202        NULL

My store procedure look like this:

;WITH TEMP AS (
SELECT
    Date
    customer_id
    status
FROM table_1
GROUP BY
    date,
    customer_id,
    status
)
,TEMP2 AS (
  SELECT 
        ID  = ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY MAX(date) DESC),
        start_date  = MIN(date),
        end_date    = MAX(date),
        [customer_id],
        [status]
  FROM TEMP 
  GROUP BY 
        [customer_id],
        [status]
)
SELECT 
  A.customer_id,
  A.status,
  A.start_date,
  end_date      = DATEADD(DAY,-1,B.start_date)
FROM TEMP2 A
LEFT JOIN TEMP2 B
    ON A.customer_id = B.customer_id
    AND A.ID = B.ID + 1

I know my error is in the creation of CTE TEMP2, because this code can´t discriminate for a customer_id with a status with two occurrences in different ranges of time, based on the 'group by' sentence

I can´t figure out how to do that...

preguntado el 09 de marzo de 12 a las 15:03

In your "what I want" column, why does the row where customer id =1 status = a start date= 20120205 not have a 20120206 as end date? How can you tell when one record that has the same customer and status "goes with" each other? Again, in results you want, Why does customer 2 status d get an end date, adn cusotmer 2 status e not get an end date? Does the "total" column have any relevance to the results you want? -

These are the answer of your questions in the order that you put above: -----1. Because is the last register for the customer_id = 1, so this represents most recent status fot that customer_id, the meaning of NULL equals to a getdate() expression if you want to see like that -----2.The idea is represents the changes in time of status for different customers_id -----3. total have not any relevance -

1 Respuestas

Try this. Hope it works now.

DECLARE @table_1 TABLE ( 
    date DATETIME, 
    customer_id INT, 
    status CHAR(1), 
    total INT 
) 

INSERT @table_1 (date, customer_id, status, total) 
VALUES   
('20120201', 1, 'a', 10), 
('20120202', 1, 'a', 20),  
('20120203', 1, 'b', 20),  
('20120204', 1, 'b', 20),  
('20120205', 1, 'a', 20),  
('20120206', 1, 'a', 20),  
('20120201', 2, 'd', 30),  
('20120202', 2, 'e', 40) 



;WITH CTE_1 AS ( 
    SELECT  
        customer_id,  
        status, 
        date, 
        ROW_NUMBER() OVER(PARTITION BY customer_id ORDER BY date ASC) AS seq 
    FROM @table_1    
),
CTE_2 AS (
    SELECT  
        customer_id,  
        status, 
        date, 
        seq,
        1 AS flg,
        1 AS seq2
    FROM CTE_1 
    WHERE 
        seq = 1

    UNION ALL 

    SELECT  
        CTE_1.customer_id,  
        CTE_1.status, 
        CTE_1.date, 
        CTE_1.seq,
        CASE WHEN CTE_2.status = CTE_1.status THEN 0 ELSE 1 END,
        CASE WHEN CTE_2.status = CTE_1.status THEN CTE_2.seq2 ELSE CTE_2.seq2 + 1 END
    FROM CTE_1   
    INNER JOIN CTE_2
        ON CTE_1.customer_id = CTE_2.customer_id
            AND CTE_1.seq = CTE_2.seq + 1   
)
SELECT 
    st.customer_id, 
    st.status, 
    st.date AS start_date, 
    DATEADD(DAY, -1, en.date) AS end_date  
FROM CTE_2 AS st
LEFT JOIN CTE_2 AS en
    ON st.customer_id = en.customer_id
        AND st.seq2 = en.seq2 - 1
        AND en.flg = 1
WHERE
    st.flg = 1
ORDER BY 
    st.customer_id,
    st.seq2

respondido 13 mar '12, 17:03

For this particular case, the answer is near to the correct, but it don't represents what I need. I'm going totry to explain with more details. @table_1 is a table with continious date ranges for each customer_id, but the status field can change in this continious range. I need to create a table based in table_1 that show the chages of status in time, with a start_date and an end_date. Thank you! - mr_primate

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.