The Floor

  • Comments posted to this topic are about the item The Floor

  • Nice one to start the week thanks Steve

    ...

  • Nice one to start the week on, thanks Steve

    ____________________________________________
    Space, the final frontier? not any more...
    All limits henceforth are self-imposed.
    “libera tute vulgaris ex”

  • For me (and please remember it's very early on a Monday morning and I haven't had much coffee yet), the code won't do what the question asks.

    You're ignoring the partial dollars for payments (which means rounding down) and doing the same for recharges (rounding down again (ignoring the fact it's a negative figure)).

    Therefore, you've more chance of running out of cash on the card.

    What you should be doing is ignoring the partial dollars on the recharges (so underestimating what you've put on the card) and rounding up the cost of the coffee (so overestimating spend).

    That way, you'll never run out of cash on the card because you've assumed you've paid more and recharged less.

    Do any of that make sense???

  • Hi Steve,
    in your solution the Group by is missing.

    GROUP BY a;

    Instead you could use a solution like that, without showing the functionality of CEILING.

    WITH mycte (a, n)
    AS (SELECT a, n FROM (VALUES ('Coffee', 2.38), ('Coffee', 4.53), ('Recharge card', -15.50), ('Recharge card', -5.25)) a (a, n) )
    , Calculate_Factor as(
    Select a, n, cast(n/ABS(n) as int) as factor
    from mycte)
    SELECT a, SUM(FLOOR(abs(n))*factor) from Calculate_Factor
    GROUP BY a;

    Have a nice day,Christoph

  • richardmgreen1 - Monday, July 31, 2017 1:47 AM

    For me (and please remember it's very early on a Monday morning and I haven't had much coffee yet), the code won't do what the question asks.

    You're ignoring the partial dollars for payments (which means rounding down) and doing the same for recharges (rounding down again (ignoring the fact it's a negative figure)).

    Therefore, you've more chance of running out of cash on the card.

    What you should be doing is ignoring the partial dollars on the recharges (so underestimating what you've put on the card) and rounding up the cost of the coffee (so overestimating spend).

    That way, you'll never run out of cash on the card because you've assumed you've paid more and recharged less.

    Do any of that make sense???

    I tend to agree with you on this - If my coffee costs 2.99 and I round it down to 2 dollars - I've already lost a dollar on my card - so there is no way I'm going to have any money left on my card to buy my Christmas presents!

  • Have to agree with the above. I have to admit I didn't really understand what Steve was trying to achieve, but I still got points because that was the only option that made any sense, given the posted results. "I can't do this with T-SQL." 🙂 As if that ever happens?

    But given the problem, CEILING() would be the correct choice. If you really want to round towards zero, and don't care for decimals, you can simply CAST it to INT instead.


    Just because you're right doesn't mean everybody else is wrong.

  • richardmgreen1 - Monday, July 31, 2017 1:47 AM

    For me (and please remember it's very early on a Monday morning and I haven't had much coffee yet), the code won't do what the question asks.
    You're ignoring the partial dollars for payments (which means rounding down) and doing the same for recharges (rounding down again (ignoring the fact it's a negative figure)).
    Therefore, you've more chance of running out of cash on the card.
    What you should be doing is ignoring the partial dollars on the recharges (so underestimating what you've put on the card) and rounding up the cost of the coffee (so overestimating spend).
    That way, you'll never run out of cash on the card because you've assumed you've paid more and recharged less.
    Do any of that make sense???

    I agree with what you said, however I think the purpose of the example was to point out how FLOOR functions with negative numbers.
    What I did for my solution was to simply CAST the value to an INT within the SUM so I didn't have to determine whether or not to use FLOOR or CEILING.

  • Or we could simply just use ROUND() to get the correct result.

    WITH mycte (a, n)
    AS (SELECT a, n
      FROM ( VALUES
          ('Coffee', 2.38),
          ('Coffee', 4.53),
          ('Recharge card', -15.50),
          ('Recharge card', -5.25)
       ) a (a, n)
     )
    SELECT
      a,SUM(ROUND(n,0,1))
    FROM mycte
    GROUP BY a;

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • WITH mycte (a, n)

    AS (SELECT a,FROM (
     
    SELECT 'Coffee', 2.38 UNION SELECT 'Coffee', 4.53 UNION SELECT 'Recharge card', -15.50 UNION SELECT 'Recharge card', -5.25) a (a, n) )

    SELECT TransactionType=a
    , AccountingAmount=SUM(CEILING(n))
    , ActualAmount=SUM(n)
    , ChristmasSavings =CAST(SUM(CEILING(n)) as money)-SUM(n)
    FROM mycte

    GROUP BY a;
    I agree with richardmgreen1, it should be tracked as $8 spent, $20 loaded, for an "available" balance of $12 and an effective Christmas Savings of $1.84.


    Puto me cogitare, ergo puto me esse.
    I think that I think, therefore I think that I am.

  • Another agreement for @richardgreen1. Not sure how anyone could have thought that floor would be the right choice for this. Ceiling is the only function that works correctly for both the positive and negative values given the problem you want to solve.

  • Christoph Muthmann - Monday, July 31, 2017 2:06 AM

    Hi Steve,
    in your solution the Group by is missing.

    GROUP BY a;

    Instead you could use a solution like that, without showing the functionality of CEILING.

    WITH mycte (a, n)
    AS (SELECT a, n FROM (VALUES ('Coffee', 2.38), ('Coffee', 4.53), ('Recharge card', -15.50), ('Recharge card', -5.25)) a (a, n) )
    , Calculate_Factor as(
    Select a, n, cast(n/ABS(n) as int) as factor
    from mycte)
    SELECT a, SUM(FLOOR(abs(n))*factor) from Calculate_Factor
    GROUP BY a;

    Hi Cristoph,
    You had a creative way of getting the factor. However, you might have just used SIGN() which would return the same value.

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • Christoph Muthmann - Monday, July 31, 2017 2:06 AM

    Hi Steve,
    in your solution the Group by is missing.

    GROUP BY a;

    Instead you could use a solution like that, without showing the functionality of CEILING.

    WITH mycte (a, n)
    AS (SELECT a, n FROM (VALUES ('Coffee', 2.38), ('Coffee', 4.53), ('Recharge card', -15.50), ('Recharge card', -5.25)) a (a, n) )
    , Calculate_Factor as(
    Select a, n, cast(n/ABS(n) as int) as factor
    from mycte)
    SELECT a, SUM(FLOOR(abs(n))*factor) from Calculate_Factor
    GROUP BY a;

    Thank, bad cut/paste.

  • Steve Jones - SSC Editor - Monday, July 31, 2017 9:33 AM

    Christoph Muthmann - Monday, July 31, 2017 2:06 AM

    Hi Steve,
    in your solution the Group by is missing.

    GROUP BY a;

    Instead you could use a solution like that, without showing the functionality of CEILING.

    WITH mycte (a, n)
    AS (SELECT a, n FROM (VALUES ('Coffee', 2.38), ('Coffee', 4.53), ('Recharge card', -15.50), ('Recharge card', -5.25)) a (a, n) )
    , Calculate_Factor as(
    Select a, n, cast(n/ABS(n) as int) as factor
    from mycte)
    SELECT a, SUM(FLOOR(abs(n))*factor) from Calculate_Factor
    GROUP BY a;

    Thank, bad cut/paste.

    You're still not accounting for the floor affecting your Coffee amounts incorrectly. Suppose you spend 14.99 on coffee after your prior purchases:

    WITH mycte (a, n)
    AS (SELECT a, n FROM (VALUES ('Coffee', 2.38), ('Coffee', 4.53), ('Recharge card', -15.50), ('Recharge card', -5.25)), ('Coffee', 14.99)) a (a, n) )
    , Calculate_Factor as(
    Select a, n, cast(n/ABS(n) as int) as factor
    from mycte)
    SELECT a, Actual=SUM(n), Converted=SUM(FLOOR(abs(n))*factor) from Calculate_Factor
    GROUP BY a;

    It will appear that both are at $20, when you have overspent by $1.15.


    Puto me cogitare, ergo puto me esse.
    I think that I think, therefore I think that I am.

  • Rewording the question. Not sure what I was thinking. Kept looking at rounding up, but wrote and used Floor. Changing the scenario a bit.

    Look for the "Ceiling" question in the next month.

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

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