calcutate membership duration, until now or until end date - mysql

I have a MySQL table with (among others) the following columns:
[name] [member_since_date] [member_until_date]
When somebody's membership ends, the [member_until_date] field is populated, otherwise it contains NULL.
I need a purely SQL based solution for the following:
I want to calculate how long someone is a member: when [member_until_date] is filled, I need it to calculate [member_until_date] - [member_since_date].
When somebody is still a member, the field [member_until_date] is NULL, so then I need it to calculate [NOW] - [member_since_date].
I hope I'm clear enough on this, and I hope somebody has an answer for me.

To get the difference between dates, in days, use DATEDIFF(). To take one value based on a condition, or another, use IF, though in this case I am using the similar IFNULL().
SELECT DATEDIFF(IFNULL(member_until_date, NOW()), member_since_date) AS days_member
FROM ...
IFNULL() says use the first argument, unless it's null, then use the second argument.
DATEDIFF() expects the larger date first in order to get a positive result.
COALESCE() provides similar functionality to IFNULL() and would be the ANSI SQL way of doing this.

Here's a solution using DATEDIFF().
SELECT name, DATEDIFF(IF(member_until_date,member_until_date,NOW()),
member_since_date) AS membership_duration
FROM members;
First, we check if member_until_date is null. If it is, we use NOW(), otherwise we use member_until_date.
IF(member_until_date,member_until_date,NOW())
Now we calculate the date difference between the above and the beginning of the membership, member_since_date, and return is as membership_duration.
DATEDIFF(IF(member_until_date,member_until_date,NOW()),
member_since_date) AS membership_duration

Related

Maximum of column and zero

I would like to know how to get computed field in MS Access that shows maximum of a number or zero. I mean the function that is similar to the one in Excel Max(A1,0). How do I get this in Access expression builder?
I suppose the only problem you could face, is that if the field has a null value. To be safe, wrap the field with the Nz() function which replaces null to the given argument.
Max(Nz([YourFieldName],0))
When the field is numeric, the zero can be omitted.
Max(Nz([YourFieldName]))
SELECT IIf(YourField > 0, YourField, 0)
FROM YourTable;
This is what I had done, but i thought there was another way
Thank you very much for your quick responses

Access query using calculation

I'm trying to make a query using a calculation with Date().
I have a field named [Currentordue] and a field named [duedate]. What I'm trying to accomplish is making a query to limit the results by "if [currentordue] equals "due" or if [duedate] minus today's date is less than 30 days."
I've tried a few different ways but always seem to end with either an error or with no results showing (which would be an error as well since I know there are fields that are due).
Any and all help would be appreciated.
Here is a way to use two different date conditions:
SELECT Table1.Currentordue, Table1.duedate, DateDiff("d",[duedate],Date()) AS Expr1
FROM Table1
WHERE (((DateDiff("d",[duedate],Date()))<30)) OR (((Table1.Currentordue)=[duedate]));

Rails Show Age in View based Born Date

I have a problem to show age in a view with rails
i think this to solve:
show.html.slim
`=#people.date_born - Date.today / 365,25`
`end`
What i need to do?
It's probably just an order of operations thing, but your syntax was displayed funny. Ignoring the unnecessary quotes:
= ((Date.today - #person.date_born) / 365).to_i
First, since today is a greater date than the date of birth, you want it first to avoid a negative number. You need to wrap it in parens to do the subtraction first, and then divide, and for legibility, change it back to an integer.

DATEDIFF function in SQL Server - executes differently in different cases

I am using SQL Server and just identify one problem in my case.
I have used the DATEDIFF function as:
select datediff(dd,'1935-12-07','2010-03-02')/365.00 ---> 74.28
select datediff(dd,'1935-12-07','2010-03-02')/365 ---> 74
select datediff(yy,'1935-12-07','2010-03-02') ---> 75
If you can observe that If I try DATEDIFF with 'dd' then I get the difference as 74/74.28.
But If I use it with 'yy' I get the diference as 75.
Why this is so? Means Why the difference came as 75 as it nearly approximate to 74.
I need this both function in different cases. But as it is behaving differently I am facing a lot of problems.
Suggest me some solution to this.
Thanks.
First case = You're implicitly casting to a float, shows the correct result
Second case = You're implictly casting to an int, which rounds down as part of the conversion (Floor value)
Third case = You're not casting anything at all, and DATEDIFF() returns a signed int, which rounds up (Ceiling value)
Solution: Do whatever you want, but keep it consistent throughout your code.
The datediff function checks for the difference of the date part you have specified, so it is correct in saying the difference in the year part of the two dates is 75.
Or to word it as the folks at microsoft do, it counts the number of boundaries crossed of that datepart. There are 75 year-boundaries crossed between the two dates in your example.
Have a look at this msdn page, it explains how it is supposed to work.

How to store approximate dates in MySQL?

I need to store dates such as 'Summer 1878' or 'Early June 1923', or even 'Mid-afternoon on a Tuesday in August'. How would you suggest I do this?
I have considered breaking the date and time up into separate (integer) columns, and giving each column an ancillary (integer) column containing a range (0 if exact; NULL if unknown). But I'm sure there's other ways...
Thanks!
Since 'Mid-afternoon on a Tuesday in August' ("A Sunday Afternoon on the Island of La Grande Jatte"?) doesn't specify a year, the only real solution is your table of all date and time components, all nullable.
Other wise, you're conflating your data.
You have two (admittedly related) things here: a human readable string, the date_description, and a range of possible dates.
If you can specify at least a range, you can do this:
create table artwork {
artwork_id int not null primary key,
name varchar(80),
... other columns
date_description varchar(80),
earliest_possible_creation_date datetime
latest_possible_creation_date datetime
}
insert into artwork(
name,
date_description,
earliest_possible_creation_date,
latest_possible_creation_date
) values (
'A Sunday Afternoon on the Island of La Grande Jatte',
'Mid-afternoon on a Tuesday in August'
'1884-01-01',
'1886-12-31'
), (
'Blonde Woman with Bare Breasts',
'Summer 1878'
'1878-05-01',
'1878-08-31'
), (
'Paulo on a Donkey',
'Early June 1923',
'1923-06-01'
'1923-06-15'
);
This allows you to display whatever you want, and search for:
select * from artwork
where #some_date between
earliest_possible_creation_date and latest_possible_creation_date;
And obviously, "creation date" (the date the artist created the work) is entirely differnet from "date depicted in work", if the latter can be determined at all.
I'm using Postgres, and I wanted to do the same thing. Perhaps you can do it the same way as I did it, if MySQL has some similar geometric types: http://www.electricwords.org/2008/11/fuzzy-date-matching-in-postgresql/
Almost no matter what you do, you almost certainly won't be able to get the database to do the heavy lifting for you. So you are left with two options:
1 - Use natural strings as you have described
2 - Store a precise data as well as the precision of that date
For example, you could store "5:10:23pm on Sep 23,1975", "plus or minus 6 months", and when someone wants to search for records that occured in that timeframe this could pop up.
This doesn't help with queries, because to the best of my knowledge MySQL doesn't provide any support for tolerances ( nor do any others I know of ). You have to basically query it all and then filter out yourself.
I don't think any native MySQL date representation is going to work for you. Your two-column solution would work well if paired with a Unix time stamp (generated with the UNIX_TIMESTAMP() function with a MySQL date as the argument). Use the second column (the range width) for an upper and lower bound in your selects, and make sure the date column is indexed.
In the end I decided upon: a column for each of the date components (year, month, day, hour, minute, second), and accompanying columns for the range of each of these (year_range, month_range, day_range, hour_range, minute_range, second_range), mainly because this method allows me to specify that I know for sure that a particular photo was taken in August (for instance) in the late '60s (year=1868, year_range=2, month=8, month_range=0).
Thank you all for your help!
create a table with a list of values that you could want, like "Early" or "Summer". then whatever you have setting up the data could have an algorithm that sets a foreign key depending on the date.
Going with Chris Arguin's answer, in the second column just have another datetime column that you can use to store the +/-, then you should be able to write a query that uses both columns to get an approximate datetime.
Use two dates and determine the start and end date of the fuzzy region. For stuff like Summer 1878, enter 18780621 to 18780920. For Early June 1923 you have to decide when early ends, maybe 19230601 to 19230610. This makes it possible to select against the values. You might still want to filter afterward but this will get you close.
For the ones without years, you'll have to find a different system.