Select all CustomerID's where their last PaymentDate is more than 12 months ago

  • Hi Guys,

    I have the following query:

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(PaymentDate) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    )

    SELECT * from dbo.Customer C

    JOIN CTE_LastOrder LO ON C.CustomerId = LO.CustomerId

    WHERE LO.LastOrderDate > (dateAdd(YEAR,-1, GetDate()))

    That should select all customers from the customers table where they haven't had a Paid Order (ascertained via PaymentDate not being null) in the last 12 months - this could also include customers who don't appear in the Order table at all.

    The query is giving me results but shows a LastOrderDate for date ranges in 2014..

    Any further info needed, just give me a shout.

    Thanks in advanced as always.

    Michael

  • michaeleaton 36224 (9/22/2014)


    Hi Guys,

    I have the following query:

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(PaymentDate) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    )

    SELECT * from dbo.Customer C

    JOIN CTE_LastOrder LO ON C.CustomerId = LO.CustomerId

    WHERE LO.LastOrderDate > (dateAdd(YEAR,-1, GetDate()))

    That should select all customers from the customers table where they haven't had a Paid Order (ascertained via PaymentDate not being null) in the last 12 months - this could also include customers who don't appear in the Order table at all.

    The query is giving me results but shows a LastOrderDate for date ranges in 2014..

    Any further info needed, just give me a shout.

    Thanks in advanced as always.

    Michael

    What you might want to do is find who has paid then left join on that. Your criteria should be on the order table (cte)

  • In the first part you get the last payment date for each customer, from orders table:

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(PaymentDate) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    )

    This looks OK to me.

    But bellow:

    SELECT * from dbo.Customer C

    JOIN CTE_LastOrder LO ON C.CustomerId = LO.CustomerId

    WHERE LO.LastOrderDate > (dateAdd(YEAR,-1, GetDate()))

    there is an inner join of all the customers with the results of the first part. This will get the details only for the customers which are included in the first select, which have an order , I mean the customers who have not ordered yet are not included. Even so the filter in the where clause is meant to return the Customers having the last order paid recently, this year, and not to exclude them.

    So what I would do is:

    1. move the filter in the CTE so that the CTE will return less records and we get a little bit of optimization.

    2. remove the join in the second select

    3. change the filter of the second select

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(LastOrderDate ) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    HAVING MAX(LastOrderDate ) > (dateAdd(YEAR,-1, GetDate())) -- (1)

    )

    SELECT * from dbo.Customer C

    -- (2) JOIN CTE_LastOrder LO ON C.CustomerId = LO.CustomerId

    WHERE -- LO.LastOrderDate > (dateAdd(YEAR,-1, GetDate()))

    -- (3)

    C.CustomerId NOT IN ( SELECT CustomerID FROM CTE_LastOrder )

    I hope this helps

    Cheers ,

    Iulian

  • Thanks djj.

    Also, Martin, thank you very much - that seems to have worked - the only thing that is missing is the LastOrderDate in the result set as I want to see when their last order was.. I don't want to touch the query too much as I don't want to break it! I did try adding an INNER JOIN to the select at the bottom of the query but i got duplicated results - so unsure where to do it..

    Query:

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(PaymentDate ) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    HAVING MAX(PaymentDate ) > (dateAdd(YEAR,-1, GetDate())) -- (1)

    )

    SELECT * from dbo.Customer C

    WHERE

    C.CustomerId NOT IN ( SELECT CustomerID FROM CTE_LastOrder )

  • michaeleaton 36224 (9/22/2014)


    Thanks djj.

    Also, Martin, thank you very much - that seems to have worked - the only thing that is missing is the LastOrderDate in the result set as I want to see when their last order was.. I don't want to touch the query too much as I don't want to break it! I did try adding an INNER JOIN to the select at the bottom of the query but i got duplicated results - so unsure where to do it..

    Query:

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(PaymentDate ) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    HAVING MAX(PaymentDate ) > (dateAdd(YEAR,-1, GetDate())) -- (1)

    )

    SELECT * from dbo.Customer C

    WHERE

    C.CustomerId NOT IN ( SELECT CustomerID FROM CTE_LastOrder )

    In this case is better to leave the CTE not filtered and to make a filter in the second select, like this:

    ;WITH CTE_LastOrder (CustomerID, LastOrderDate) As

    (

    SELECT CustomerID, MAX(PaymentDate ) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    )

    SELECT CTE.LastOrderDateas LastOrderDate

    , *

    from dbo.Customer C LEFT OUTER JOIN CTE_LastOrder AS CTE

    ON C.CustomerID = CTE.CustomerID

    WHERE

    CTE.LastOrderDateIS NULL -- for the customers who never ordered

    OR CTE.LastOrderDate <= (dateAdd(YEAR,-1, GetDate()))-- for the customers who have not paid in the last year

    Cheers,

    Iulian

  • I think this is simpler and will do what you need. You might want to tweak "<" to "<=", depending on exactly what you want the cutoff date to be.

    SELECT CustomerID, MAX(PaymentDate) LastOrderDate

    FROM [Order]

    GROUP By CustomerId

    HAVING MAX(PaymentDate) < DATEADD(YEAR, -1, GETDATE())

    SQL DBA,SQL Server MVP(07, 08, 09) A socialist is someone who will give you the shirt off *someone else's* back.

Viewing 6 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic. Login to reply