- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
This may be a silly comment and not what the wtf is suppoed to be about...but why on earth is the DateDiff command repeated dozens of times?!?! Surely you would want to do that once, put the result into a variable called, lets say, "dateDiff", and then just that in the rest of the code!
(Or is this some kind of special reporting tool that doesn't allow variables)
Admin
Additionally: Why not use DATEDIFF(month...) in the frist place?
Captcha: saluto to all the other poor guys who had to switch from PL/SQL to T-SQL
Admin
Silly you, DATEDIFF is obviously memoized!
Admin
...and both codes are wrong, one of them just a little less wrong than the other. Since February 28, 1899 all five year periods until now have had more than 1825 days. The next five year period with 1825 days will start on March 1, 2096.
Admin
Is it not obvious what happened? She calculated a year with 356 days instead of 365.
Admin
Not to be an ass, but if she used "month" as a parameter in DATEDIFF instead of "day", there wouldn't be any leap year issues either. I too moved from PL/SQL to T-SQL and suffered, but this is the work of a mad(man|woman).
Oh, and to spark the discussion: although SQL Server isn't as kick ass, it does have some pretty nice features lacking in Oracle. As with life, it all depends on your situation.
Admin
The real WTF is that both reports are wrong! There are 365 days in a year, but leap years have 366. Also "0-6month" is not the same as "half a year", because February only has 28 days instead of 30 or 31. So the correct caluclation can only be done by getting the month of the start date and the month of the end date and subtracting both. Also Anastasia reported '2-5y' whereas now '2-3y', '3-4y' or '4-5y' will be reported, which is a (maybe unwanted) design change.
I can imagine how Anastasia got her 'errorneous' day numbers: transposed digits: typing 356 instead of 365. This happens to many programmers, because they learned, 1 byte holds 256 numbers. All other numbers are then calculated by multiplying or dividing this number 356.
Admin
Might want to either calculate the difference in months. Either by using 'month' for datepart in date part or using a more complicated expression.
Admin
the problem is that Datediff function can compute month and year differences by it self. There's no need to compute days and calculate months or years by your self
Admin
I'm not really familiar with TSQL but a difference in months is a very non-trivial concept. So I checked the documentation on DATEDIFF and sure enough - that's not really what it calculates if you give it "month" as parameter. E.g. it will give you 1 as difference in months between 2013-01-31 and 2013-02-01 - one month boundary crossed. In other words, 2013-01-31 to 2013-07-01 (151 days) and 2013-01-01 to 2013-07-31 (211 days) are both "six months intervals" according to that function. That's significantly worse than "Anastasia Time".
Admin
Admin
'f.filedate' in this instance is referring to a column, so it cannot be stored into a variable given that it will be different for every row.
It may have made more sense to pull a set of results into a temptable and include one column containing the result of the datediff against each row, and then run the outer query with CASE statements comparing it that way however.
Admin
Because what every SQL statement needs is a nested SELECT with a complicated switch statement just to remove the repetition of a DATEDIFF call ;)
I don't buy that this was a typo: I can see you typing it wrong, but not calculating all your other dates from the typo wrong - surely at some point you're going to look back and say "so, five years is five times... hang on: 356? Nooooo" then doing over. No, it looks to me like Anastasia genuinely thought there were 356 days in a year.
Admin
Pfft... everyone knows that years have 256 days, each of which is 123268.5 seconds long.
Admin
That's right. From what it looks like I'd assume the "6 months difference" they want to have is something like "number of month boundaries crossed minus one, if the current day of month is smaller than the reference date's day of month", so my proposal would be something like:
This gives: 2013-01-31 to 2013-02-01 => 0 2013-01-31 to 2013-02-28 => 0 2013-01-31 to 2013-03-01 => 1 2013-01-31 to 2013-03-31 => 2
And we get leap years, the different month lengths and all the other problems correct and do not end up with 2013-01-01 being "0-6m" before 2013-07-02.
Did I miss something?
Admin
However, then you need their age, and that is something that you don't calculate by the means of crossed months boundaries. A baby born on the 30th of June is not one month old come the 1st of July.
So in theory, calculating the days between the date in the database (probably the dob) and the date on which the report is generated is the way to do it.
There is a catch however: the number of days each age group encompasses is not static, due to the fact that different months have different lengths and leap years also have to come into the equation.
It is probably excusable not to calculate the age groups to the needed precision as this looks like it was meant for some statistical report; but it is completely unexcusable for Anastasia to work on the assumption that a year has 356 days instead of the more generally accepted number of 365 days (excluding leap years).
And that the 356 days are not a one-off typo with accidentally mixed up digits can be seen from the 178 days Anastasia uses for a six month period.
Admin
Might want to read the logic in the first example again. Hint.... >
Admin
You're assuming we're using T-SQL in a stored procedure. But there's no way to tell from the OP. This could be a column calculation in a view (in fact as this is part of a report I'd be inclined to say it's likely to be part of a view). So you need to refactor your example to work without using holding variables ;)
Admin
Not that big a problem. I'd actually try a user created function for it, passing in the two dates. If this does not work performance-wise - I've been told that user defined functions are evil in T-SQL, although I have not yet made any tests myself - you'd have to include everything in the CASE part (similar to the OP). This of course would be quite cumbersome to read, but at least we don't get a result where 2012-01-01 to 2016-12-31 is "5y+" and the like.
Admin
Admin
Reminds me of a daycare nearby that claims they'll care for kids "0.3 - 1 years old".
I THINK they meant "3 month old", and not 3.6 months old. "This month has 31 days. Is your child exactly 3 months and 18 days and 14 hours and 24 minutes old?"
Really, anyone trying to measure months by count of days is TRWTF.
Admin
It's a simple case of "good enough". The code is condensing number of days into number of months with (at best) a 6 month granularity. Miscategorizing a date due to a leap day off-by-one error is unlikely to cause any significant incorrectness. If you really need to know to the day then you don't dick around with 6-month wide buckets in the first place.
Don't they teach kids the concept of significant digits anymore? It's not just for trick questions on maths tests. It really should be applied in real-life story problems.
Admin
TRWTFs: 1) the copy and paste "solution", 2) calculating values on the fly rather than a one-time calculation for every date for the next 20 years, putting the result in a table named 'Calendar'.
Admin
Oh, those age groups are okay. In fact if you say "age of three months", in most cases, you really mean "age of 365.25/4 days". If you do the calculations by calendar rules, your statistics will always be noticeably off for February (and we're talking reports, i.e. statistics, here).
Using different periods in different queries - well, the usual WTFery in production I guess.
Captcha: facilisi - I made it simpler (when talking Lipsum-garbled Latin)
Admin
Indeed, I wonder if the bug would even have been noticed if both of them had been the same.
Admin
Anastasia?
We've found the President's... I mean, Tsar's daughter!
Admin
Ah, well. Who knows what planet she comes from.
Admin
What's the problem? Anastasia used a lunar year, rather than your boring solar year.
Maybe she just really likes Islamic Leap Years.
Admin
If the statistics are for measurement with exactness needed, then do age by days and be transparent of that. If the statistics are for pricing, then use the conventional expectations. A kid is x months old, where
months old = ((current month's day > birth day of month or current month's day is max for month) ? 1 : 0) + (current month + current year * 12) - (birth month + birth year * 12) - 1;
That's how the average person determines age in months.
Admin
Admin
TRWTF is someone who finds the DATEDIFF function but then doesn't think to try putting 'month' instead of 'day' and solving all their problems in one go...
Admin
TRWTF is someone who thinks that the DATEDIFF function is the solution to all their problems :p
(hint: read the rest of the comments to find out why it isn't)
Admin
(current month's day > birth day of month) yes if you count time of day.
So, no, it won't be -1.
Admin
But seriously, you're giving too much credit on how people do calculations. They type (and sometimes typo) numbers into their calculator or spreadsheet and happily copy the results from them without any sanity checking. The result may be off by orders of magnitude, they don't notice or care because "the machine said so".
That's why some people consider using calculators too much (esp. in school) dangerous.
Admin
Doesn't this freaking language have "else", or are Glidder and Anastasia (AKA Gliddero and Anastasiao) just shy of such newfangled stuff and prefer to write everything twice?
Admin
TRWTF is hard coding your ranges rather than, I don't know, storing them in the database one time and just joining that table whenever you needed.
Admin
You must be using some strange definition of the word day that I wasn't previous aware of.
or do you contend that (in my case) 4 > 4?
Admin
This is a T-SQL CASE statement, so no, it doesn't (or at least, not the way you mean: ELSE in this context actually means DEFAULT). But it does shortcut, so in fact every line is making on unnecessary comparison. Or, to put it another way, the ELSE is implicit: each WHEN statement is only evaluated if the previous one was false.
Admin
I know nothing about database coding, but in the client world we have well thought out libraries for date/time calculations.
Because date/time calculations are very hard, and not something that should be attempted by someone not willing to devote a lot of time to design and testing of her code.
Is every TSQL programmer expected to reinvent the date/time wheel? If so, that would explain a lot of (bad) things.
Admin
"half a year in months" != "half a year in days"
granularity...
Admin
And I thought that health care signup web sites were really wacky. Maybe Anastasia was involved there.
Then again, given that the health care project was a "known problem" bunches of years ago, I kinda doubt it. Those monkeys are WTFs all themselves.
When will we get stories from that project??
Admin
Admin
It depends how you determine you want to count "months", i'll use decades as an analogy. I'm 24 and I've lived in 4 different decades. The decades are predetermined lengths of time (10 years). I was born in 89 (80's), lived through 90's and 0's, And now i'm living through the 10's.
I've lived in four decades.
Now back to the topic, if the creators are intending for the calculations to be end of month based, or actual day based thats two different calculations. equivalent to how many months have I accumulated, versus how many months i've lived.
Born on Jan 31st, on Feb 1st depending on how you want to quantify its either one month obtained (end of month) or 0 months obtained (by day)
Admin
Apparently she was working on a calendar with 29 day months.
Maybe she is banking the extra days for a big vacation.
Admin
The real WTF is that they had a DBA writing code. From "How To Be A Real DBA For Dummy's And Coder's Who Only Wish They Were"...
Admin
You're probably right, though. She probably thought that a year was 356 days long.
Admin
Optimization is for anal-retentive geeks and assembler weenies! If the compiler is stupid enough to generate a pile of individual function calls - well, I guess we need to write a new compiler!
Admin
Born this morning? Let's see...
(current month's day > birth day of month or current month's day is max for month) ? 1 : 0 - evaluates to 0 (current month + current year * 12) = 11 + 2013 * 12 = 24167 (birth month + birth year * 12) = 11 + 2013 * 12 = 24167
So 0 + 24167 - 24167 = (drum roll.........) ZERO!
So this formula gives a value of zero months old. Seems right enough.
But tomorrow the kid will be reported as being one month old, because tomorrow the "current month's day" will be greater than birth day of month (today). Oh, the shame! Oh, the humanity...!!!!!
YMMV.
Admin
Admin
At least she doesn't appear to have believed that there are 21 months per year.