between is not working the way I would think?

  • Can someone tell me why this does not pull any data?

    Data consists of

    fcinvoice, finvdate, fcstatus

    0000071053, 2016-05-02 00:00:00.000, F

    0000071894, 2016-09-13 00:00:00.000, F

    0000081833, 2022-03-04 00:00:00.000, F

    0000082570, 2022-08-22 00:00:00.000, F

    When I run this select statement it does not pull any data but ith I remove either of the last finvdate between lines it pulls the correct data. What I would expect this to pull is the last 2 lines.

    select fcustno, fnamount, finvdate 
    from armast where (finvdate Not Between '01/01/2017' and '01/01/2022') and
    (finvdate between '01/01/2022' and '09/01/2022') and
    (finvdate between '01/01/2006' and '01/01/2017') and
    (fcstatus <> 'V' and fcstatus = 'F') and
    fcustno = '004861'

     

     

  • If a date is between '01/01/2022' and '09/01/2022', it cannot also be between '01/01/2006' and '01/01/2017'. You need to rethink your logic, as this will never produce any results.

    The absence of evidence is not evidence of absence
    - Martin Rees
    The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
    - Phil Parkin

  • OR  Crap, sorry, thanks.

  • I wouldn't write dates as '09/01/2022'

    What does it mean? Is it 1st September or 9th January?

    Better to write dates in ISO format so for 9th January 2022 write it as '20220109'

  • OK, but I still can not figure this out. OR does not work. What I need to find out is to gather data for customers who had invoices before a date and after a date but not between dates. Any help on that would be much appreciated, Thanks

  • bswhipp wrote:

    OK, but I still can not figure this out. OR does not work. What I need to find out is to gather data for customers who had invoices before a date and after a date but not between dates. Any help on that would be much appreciated, Thanks

    use not between, I'm not sure what you want but maybe something like this:

    select fcustno, fnamount, finvdate 
    from armast
    where (finvdate Not Between '01/01/2017' and '01/01/2022')
    and (finvdate not between '01/01/2022' and '09/01/2022')
    and (finvdate not between '01/01/2006' and '01/01/2017')
    and (fcstatus <> 'V' and fcstatus = 'F')
    and fcustno = '004861'

    However, I can't see that's what you want as:

    where (finvdate Not Between '01/01/2017' and '01/01/2022') 
    and (finvdate not between '01/01/2022' and '09/01/2022')

    Is the same as:

    where (finvdate Not Between '01/01/2017' and '09/01/2022')
  • I finally got it. Here is the select statement.

    Select cust.fcustno, fcompany, fcreated, cust.fsalespn, Sum(fnamount) as Sales from slcdpmx cust
    inner join (select fcustno, fnamount, finvdate
    from armast where
    fcustno in (Select fcustno from armast where finvdate < Str(year(current_timestamp)-5)+'0101') --5 years ago
    and fcustno in (Select fcustno from armast where finvdate > Case when month(current_timestamp) < 4 then str(year(current_timestamp)-1) + '1231'
    when month(current_timestamp) > 3 and month(current_timestamp) < 7 then str(year(current_timestamp)) + '0331'
    when month(current_timestamp) > 6 and month(current_timestamp) < 10 then str(year(current_timestamp)) + '0630'
    else str(year(current_timestamp)) + '0930'
    End) -- current quarter
    and fcustno not in (Select fcustno from armast where finvdate > Str(year(current_timestamp)-5)+'0101'
    and finvdate < Case when month(current_timestamp) < 4 then str(year(current_timestamp)-1) + '1231'
    when month(current_timestamp) > 3 and month(current_timestamp) < 7 then str(year(current_timestamp)) + '0331'
    when month(current_timestamp) > 6 and month(current_timestamp) < 10 then str(year(current_timestamp)) + '0630'
    else str(year(current_timestamp)) + '0930'
    End) -- Not between time
    ) ar
    on ar.fcustno = cust.fcustno and finvdate > Case when month(current_timestamp) < 4 then str(year(current_timestamp)-1) + '1231'
    when month(current_timestamp) > 3 and month(current_timestamp) < 7 then str(year(current_timestamp)) + '0331'
    when month(current_timestamp) > 6 and month(current_timestamp) < 10 then str(year(current_timestamp)) + '0630'
    else str(year(current_timestamp)) + '0930'
    End
    where fcreated < Str(year(current_timestamp)-5)+'0101' and ftype = 'C' --and cust.fcustno = '004861'
    Group by cust.fcustno, fcompany, fcreated, cust.fsalespn
    order by fcreated
  • You should read the following article on the performance and other issues having to do with the STR() function.

    And to those that say "Sometimes performance doesn't matter"... It always does... you just don't know it because you're only looking at the one query.  You're not considering the "Death by a Thousand Cuts" because everyone says the same thing.  Just imagine if your servers rant just 3 times faster.  In order to do that, every has to stop writing code that's automatically 3 times slower.

     

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • SELECT  fcustno,
    fnamount,
    finvdate
    FROM dbo.armast
    WHERE fcustno = '004861'
    AND fcstatus = 'F'
    AND (
    finvdate between '01/01/2022' and '09/01/2022'
    OR finvdate between '01/01/2006' and '01/01/2017'
    );


    N 56°04'39.16"
    E 12°55'05.25"

  • Quick question, can you post the DDL (create table) for the tables, sample data as an insert statement and the expected result set. This problem is trivial but in order to provide a proper solution, one needs the sample setup and data.

    😎

     

  • Would like to post the data but I have a solution now. This will run once a quarter at night so it is not a huge hit on processing. I need to move on to other things but thanks all for your insights. I am a novice at this stuff. Not formally trained so I learn as I read your comments. Again, Thanks.

  • bswhipp wrote:

    Would like to post the data but I have a solution now. This will run once a quarter at night so it is not a huge hit on processing. I need to move on to other things but thanks all for your insights. I am a novice at this stuff. Not formally trained so I learn as I read your comments. Again, Thanks.

    I was an "accidental DBA" so I have a grand appreciation for all that.  So do most of the people on this forum and that's why they ask for the DDL and some test data.  And consider that while you may have a working solution for something that runs "once a quarter at night", that won't always be so.  You've just shortcut yourself from a bit more of learning that might prove beneficial when that happens. 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Point noted and you are correct.

  • First, whenever you use date/time intervals, you should always use half-closed intervals (one side includes '=' and the other does not).  This is required for DATE data, but it's good practice to use it for all time data.  Your calculations are mishandling any dates that fall on the last day of the previous quarter.  How it is being mishandled depends on the datatype of your finvdate field.

    Second, your horribly complex case expression to calculate the beginning of the current quarter (replacing the end of the previous quarter to use half-closed intervals) can be done with a much simpler formula:

    DATEADD(QUARTER, DATEDIFF(QUARTER, '19000101', CURRENT_TIMESTAMP), '19000101')

    Finally, your different date/time interval requirements should be handled with a CASE expression and GROUP BY clause rather than multiple calls to the same table.

    A partial rewrite using all of the above (and not having any sample data to work with) looks like follows:

    SELECT  fcustno,
    SUM(CASE WHEN finvdate < d.historical_dt THEN fnamount
    WHEN finvdatte >= d.begin_qtr_dt THEN fnamount
    ELSE 0
    END) AS fnamount,
    finvdate
    FROM dbo.armast
    CROSS APPLY (VALUES(DATEADD(YEAR, DATEDIFF(YEAR, '19000101', CURRENT_TIMESTAMP)-5, '19000101'), DATEADD(QUARTER, DATEDIFF(QUARTER, '19000101', CURRENT_TIMESTAMP), '19000101'))) d(historical_dt, begin_qtr_dt)
    WHERE fcstatus = 'F'
    GROUP BY fcustno
    HAVING SUM(CASE WHEN finvdate < d.historical_dt THEN fnamount
    WHEN finvdatte >= d.begin_qtr_dt THEN fnamount
    ELSE 0
    END) > 0
    AND SUM(CASE WHEN finvdate >= d.historical_dt AND finvdatte < d.begin_qtr_dt THEN fnamount
    ELSE 0
    END) = 0 -- recent historical amount

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • Yes, I got the date issue when looking at it some more. But the problem is when selecting the data, for new customers its is easy but for the older customers not so easy. This is a commission think where the person is getting commission on new customers and then on older customers who have not ordered with us in 5 years. Some more things were added so I went through the code and updated it accordingly based on quarters and the code running on the first day of the quarter. I was not aware of the QUARTER part of DateAdd so I will now update my code to use that. Thanks.

Viewing 15 posts - 1 through 15 (of 23 total)

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