Finding lowest two minimum values and finding difference between the two in SQL Server?












0















I have a transaction table where I have to find the first and second date of transaction of every customer. Finding first date is very simple where I can use MIN() func to find the first date but the second and in particular finding the difference between the two is getting very challenging and somehow I am not able to find out any feasible way:



select a.customer_id, a.transaction_date, a.Row_Count2
from ( select
transaction_date as transaction_date,
reference_no as customer_id,
row_number() over (partition by reference_no
ORDER BY reference_no, transaction_date) AS Row_Count2
from transaction_detail
) a
where a.Row_Count2 < 3
ORDER BY a.customer_id, a.transaction_date, a.Row_Count2


Gives me this :



enter image description here



What I want is , following columns:



||CustomerID|| ||FirstDateofPurchase|| ||SecondDateofPuchase|| ||Diff. b/w Second & First Date ||










share|improve this question

























  • Please explain the results that you want. The query seems to answer your question.

    – Gordon Linoff
    Nov 13 '18 at 19:21













  • ||CustomerID|| ||First Date of Purchase || || SubsequentSecond Date of Purchase|| || Diff. b/w Second & First Date ||

    – user9230890
    Nov 13 '18 at 19:24






  • 1





    Are the results not what you want? If not, it seems like you could remove the reference_no from the order by to fix the ordering.

    – scsimon
    Nov 13 '18 at 19:25
















0















I have a transaction table where I have to find the first and second date of transaction of every customer. Finding first date is very simple where I can use MIN() func to find the first date but the second and in particular finding the difference between the two is getting very challenging and somehow I am not able to find out any feasible way:



select a.customer_id, a.transaction_date, a.Row_Count2
from ( select
transaction_date as transaction_date,
reference_no as customer_id,
row_number() over (partition by reference_no
ORDER BY reference_no, transaction_date) AS Row_Count2
from transaction_detail
) a
where a.Row_Count2 < 3
ORDER BY a.customer_id, a.transaction_date, a.Row_Count2


Gives me this :



enter image description here



What I want is , following columns:



||CustomerID|| ||FirstDateofPurchase|| ||SecondDateofPuchase|| ||Diff. b/w Second & First Date ||










share|improve this question

























  • Please explain the results that you want. The query seems to answer your question.

    – Gordon Linoff
    Nov 13 '18 at 19:21













  • ||CustomerID|| ||First Date of Purchase || || SubsequentSecond Date of Purchase|| || Diff. b/w Second & First Date ||

    – user9230890
    Nov 13 '18 at 19:24






  • 1





    Are the results not what you want? If not, it seems like you could remove the reference_no from the order by to fix the ordering.

    – scsimon
    Nov 13 '18 at 19:25














0












0








0








I have a transaction table where I have to find the first and second date of transaction of every customer. Finding first date is very simple where I can use MIN() func to find the first date but the second and in particular finding the difference between the two is getting very challenging and somehow I am not able to find out any feasible way:



select a.customer_id, a.transaction_date, a.Row_Count2
from ( select
transaction_date as transaction_date,
reference_no as customer_id,
row_number() over (partition by reference_no
ORDER BY reference_no, transaction_date) AS Row_Count2
from transaction_detail
) a
where a.Row_Count2 < 3
ORDER BY a.customer_id, a.transaction_date, a.Row_Count2


Gives me this :



enter image description here



What I want is , following columns:



||CustomerID|| ||FirstDateofPurchase|| ||SecondDateofPuchase|| ||Diff. b/w Second & First Date ||










share|improve this question
















I have a transaction table where I have to find the first and second date of transaction of every customer. Finding first date is very simple where I can use MIN() func to find the first date but the second and in particular finding the difference between the two is getting very challenging and somehow I am not able to find out any feasible way:



select a.customer_id, a.transaction_date, a.Row_Count2
from ( select
transaction_date as transaction_date,
reference_no as customer_id,
row_number() over (partition by reference_no
ORDER BY reference_no, transaction_date) AS Row_Count2
from transaction_detail
) a
where a.Row_Count2 < 3
ORDER BY a.customer_id, a.transaction_date, a.Row_Count2


Gives me this :



enter image description here



What I want is , following columns:



||CustomerID|| ||FirstDateofPurchase|| ||SecondDateofPuchase|| ||Diff. b/w Second & First Date ||







sql sql-server






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 19:49









paparazzo

37.5k1673137




37.5k1673137










asked Nov 13 '18 at 19:20









user9230890user9230890

3715




3715













  • Please explain the results that you want. The query seems to answer your question.

    – Gordon Linoff
    Nov 13 '18 at 19:21













  • ||CustomerID|| ||First Date of Purchase || || SubsequentSecond Date of Purchase|| || Diff. b/w Second & First Date ||

    – user9230890
    Nov 13 '18 at 19:24






  • 1





    Are the results not what you want? If not, it seems like you could remove the reference_no from the order by to fix the ordering.

    – scsimon
    Nov 13 '18 at 19:25



















  • Please explain the results that you want. The query seems to answer your question.

    – Gordon Linoff
    Nov 13 '18 at 19:21













  • ||CustomerID|| ||First Date of Purchase || || SubsequentSecond Date of Purchase|| || Diff. b/w Second & First Date ||

    – user9230890
    Nov 13 '18 at 19:24






  • 1





    Are the results not what you want? If not, it seems like you could remove the reference_no from the order by to fix the ordering.

    – scsimon
    Nov 13 '18 at 19:25

















Please explain the results that you want. The query seems to answer your question.

– Gordon Linoff
Nov 13 '18 at 19:21







Please explain the results that you want. The query seems to answer your question.

– Gordon Linoff
Nov 13 '18 at 19:21















||CustomerID|| ||First Date of Purchase || || SubsequentSecond Date of Purchase|| || Diff. b/w Second & First Date ||

– user9230890
Nov 13 '18 at 19:24





||CustomerID|| ||First Date of Purchase || || SubsequentSecond Date of Purchase|| || Diff. b/w Second & First Date ||

– user9230890
Nov 13 '18 at 19:24




1




1





Are the results not what you want? If not, it seems like you could remove the reference_no from the order by to fix the ordering.

– scsimon
Nov 13 '18 at 19:25





Are the results not what you want? If not, it seems like you could remove the reference_no from the order by to fix the ordering.

– scsimon
Nov 13 '18 at 19:25












2 Answers
2






active

oldest

votes


















0














You can use window functions LEAD/LAG to return results you are looking for



First try to find all the leading dates by reference number using LEAD, generate row number for each row using your original logic. You can then do difference on dates for row number value 1 row from the result set.



Ex (I'm not excluding same day transactions and treating them as separate and generating row number based on result set from your query above, you can easily change the sql below to consider these as one and remove them so that you get next date as second date):



declare @tbl table(reference_no int, transaction_date datetime)
insert into @tbl
select 1000, '2018-07-11'
UNION ALL
select 1001, '2018-07-12'
UNION ALL
select 1001, '2018-07-12'
UNIOn ALL
select 1001, '2018-07-13'
UNIOn ALL
select 1002, '2018-07-11'
UNIOn ALL
select 1002, '2018-07-15'

select customer_id, transaction_date as firstdate,
transaction_date_next seconddate,
datediff(day, transaction_date, transaction_date_next) diff_in_days
from
(
select reference_no as customer_id, transaction_date,
lead(transaction_date) over (partition by reference_no
order by transaction_date) transaction_date_next,
row_number() over (partition by reference_no ORDER BY transaction_date) AS Row_Count
from @tbl
) src
where Row_Count = 1





share|improve this answer
























  • I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

    – user9230890
    Nov 13 '18 at 21:27



















0














You can do this with CROSS APPLY.



SELECT td.customer_id, MIN(ca.transaction_date), MAX(ca.transaction_date),
DATEDIFF(day, MIN(ca.transaction_date), MAX(ca.transaction_date))
FROM transaction_detail td
CROSS APPLY (SELECT TOP 2 *
FROM transaction_detail
WHERE customer_id = td.customer_id
ORDER BY transaction_date) ca
GROUP BY td.customer_id





share|improve this answer

























    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%2f53288098%2ffinding-lowest-two-minimum-values-and-finding-difference-between-the-two-in-sql%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    You can use window functions LEAD/LAG to return results you are looking for



    First try to find all the leading dates by reference number using LEAD, generate row number for each row using your original logic. You can then do difference on dates for row number value 1 row from the result set.



    Ex (I'm not excluding same day transactions and treating them as separate and generating row number based on result set from your query above, you can easily change the sql below to consider these as one and remove them so that you get next date as second date):



    declare @tbl table(reference_no int, transaction_date datetime)
    insert into @tbl
    select 1000, '2018-07-11'
    UNION ALL
    select 1001, '2018-07-12'
    UNION ALL
    select 1001, '2018-07-12'
    UNIOn ALL
    select 1001, '2018-07-13'
    UNIOn ALL
    select 1002, '2018-07-11'
    UNIOn ALL
    select 1002, '2018-07-15'

    select customer_id, transaction_date as firstdate,
    transaction_date_next seconddate,
    datediff(day, transaction_date, transaction_date_next) diff_in_days
    from
    (
    select reference_no as customer_id, transaction_date,
    lead(transaction_date) over (partition by reference_no
    order by transaction_date) transaction_date_next,
    row_number() over (partition by reference_no ORDER BY transaction_date) AS Row_Count
    from @tbl
    ) src
    where Row_Count = 1





    share|improve this answer
























    • I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

      – user9230890
      Nov 13 '18 at 21:27
















    0














    You can use window functions LEAD/LAG to return results you are looking for



    First try to find all the leading dates by reference number using LEAD, generate row number for each row using your original logic. You can then do difference on dates for row number value 1 row from the result set.



    Ex (I'm not excluding same day transactions and treating them as separate and generating row number based on result set from your query above, you can easily change the sql below to consider these as one and remove them so that you get next date as second date):



    declare @tbl table(reference_no int, transaction_date datetime)
    insert into @tbl
    select 1000, '2018-07-11'
    UNION ALL
    select 1001, '2018-07-12'
    UNION ALL
    select 1001, '2018-07-12'
    UNIOn ALL
    select 1001, '2018-07-13'
    UNIOn ALL
    select 1002, '2018-07-11'
    UNIOn ALL
    select 1002, '2018-07-15'

    select customer_id, transaction_date as firstdate,
    transaction_date_next seconddate,
    datediff(day, transaction_date, transaction_date_next) diff_in_days
    from
    (
    select reference_no as customer_id, transaction_date,
    lead(transaction_date) over (partition by reference_no
    order by transaction_date) transaction_date_next,
    row_number() over (partition by reference_no ORDER BY transaction_date) AS Row_Count
    from @tbl
    ) src
    where Row_Count = 1





    share|improve this answer
























    • I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

      – user9230890
      Nov 13 '18 at 21:27














    0












    0








    0







    You can use window functions LEAD/LAG to return results you are looking for



    First try to find all the leading dates by reference number using LEAD, generate row number for each row using your original logic. You can then do difference on dates for row number value 1 row from the result set.



    Ex (I'm not excluding same day transactions and treating them as separate and generating row number based on result set from your query above, you can easily change the sql below to consider these as one and remove them so that you get next date as second date):



    declare @tbl table(reference_no int, transaction_date datetime)
    insert into @tbl
    select 1000, '2018-07-11'
    UNION ALL
    select 1001, '2018-07-12'
    UNION ALL
    select 1001, '2018-07-12'
    UNIOn ALL
    select 1001, '2018-07-13'
    UNIOn ALL
    select 1002, '2018-07-11'
    UNIOn ALL
    select 1002, '2018-07-15'

    select customer_id, transaction_date as firstdate,
    transaction_date_next seconddate,
    datediff(day, transaction_date, transaction_date_next) diff_in_days
    from
    (
    select reference_no as customer_id, transaction_date,
    lead(transaction_date) over (partition by reference_no
    order by transaction_date) transaction_date_next,
    row_number() over (partition by reference_no ORDER BY transaction_date) AS Row_Count
    from @tbl
    ) src
    where Row_Count = 1





    share|improve this answer













    You can use window functions LEAD/LAG to return results you are looking for



    First try to find all the leading dates by reference number using LEAD, generate row number for each row using your original logic. You can then do difference on dates for row number value 1 row from the result set.



    Ex (I'm not excluding same day transactions and treating them as separate and generating row number based on result set from your query above, you can easily change the sql below to consider these as one and remove them so that you get next date as second date):



    declare @tbl table(reference_no int, transaction_date datetime)
    insert into @tbl
    select 1000, '2018-07-11'
    UNION ALL
    select 1001, '2018-07-12'
    UNION ALL
    select 1001, '2018-07-12'
    UNIOn ALL
    select 1001, '2018-07-13'
    UNIOn ALL
    select 1002, '2018-07-11'
    UNIOn ALL
    select 1002, '2018-07-15'

    select customer_id, transaction_date as firstdate,
    transaction_date_next seconddate,
    datediff(day, transaction_date, transaction_date_next) diff_in_days
    from
    (
    select reference_no as customer_id, transaction_date,
    lead(transaction_date) over (partition by reference_no
    order by transaction_date) transaction_date_next,
    row_number() over (partition by reference_no ORDER BY transaction_date) AS Row_Count
    from @tbl
    ) src
    where Row_Count = 1






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 13 '18 at 19:36









    rs.rs.

    20.3k75280




    20.3k75280













    • I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

      – user9230890
      Nov 13 '18 at 21:27



















    • I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

      – user9230890
      Nov 13 '18 at 21:27

















    I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

    – user9230890
    Nov 13 '18 at 21:27





    I am not aware of Lead/Lag func in SQL and still do not understand them but somehow your solution worked. Thank You.

    – user9230890
    Nov 13 '18 at 21:27













    0














    You can do this with CROSS APPLY.



    SELECT td.customer_id, MIN(ca.transaction_date), MAX(ca.transaction_date),
    DATEDIFF(day, MIN(ca.transaction_date), MAX(ca.transaction_date))
    FROM transaction_detail td
    CROSS APPLY (SELECT TOP 2 *
    FROM transaction_detail
    WHERE customer_id = td.customer_id
    ORDER BY transaction_date) ca
    GROUP BY td.customer_id





    share|improve this answer






























      0














      You can do this with CROSS APPLY.



      SELECT td.customer_id, MIN(ca.transaction_date), MAX(ca.transaction_date),
      DATEDIFF(day, MIN(ca.transaction_date), MAX(ca.transaction_date))
      FROM transaction_detail td
      CROSS APPLY (SELECT TOP 2 *
      FROM transaction_detail
      WHERE customer_id = td.customer_id
      ORDER BY transaction_date) ca
      GROUP BY td.customer_id





      share|improve this answer




























        0












        0








        0







        You can do this with CROSS APPLY.



        SELECT td.customer_id, MIN(ca.transaction_date), MAX(ca.transaction_date),
        DATEDIFF(day, MIN(ca.transaction_date), MAX(ca.transaction_date))
        FROM transaction_detail td
        CROSS APPLY (SELECT TOP 2 *
        FROM transaction_detail
        WHERE customer_id = td.customer_id
        ORDER BY transaction_date) ca
        GROUP BY td.customer_id





        share|improve this answer















        You can do this with CROSS APPLY.



        SELECT td.customer_id, MIN(ca.transaction_date), MAX(ca.transaction_date),
        DATEDIFF(day, MIN(ca.transaction_date), MAX(ca.transaction_date))
        FROM transaction_detail td
        CROSS APPLY (SELECT TOP 2 *
        FROM transaction_detail
        WHERE customer_id = td.customer_id
        ORDER BY transaction_date) ca
        GROUP BY td.customer_id






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 13 '18 at 19:49

























        answered Nov 13 '18 at 19:44









        Derrick MoellerDerrick Moeller

        2,59821433




        2,59821433






























            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%2f53288098%2ffinding-lowest-two-minimum-values-and-finding-difference-between-the-two-in-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







            這個網誌中的熱門文章

            Academy of Television Arts & Sciences

            L'Équipe

            1995 France bombings