How to represent a robust birth date modeling-wise? - date

I am considering making a history page which lists people and their "birth dates". The problem is, a birth date can be any of the following:
exact datetime (down to the second)
exact date (down to the day)
only partially known
month is known but not year
year and month is known but not day
etc.
only somewhat accurately known (e.g. +- 5 years)
How can you model all of this in a concise and practical way, ideally for a relational database where you can still query over the dates ("find all people born after x date" or "find all people born between a and b dates" or "find all people born in January").
Can it be done? Is it just a matter of getting clever with queries on this basic table?
table birthdates {
int month
int day
int year
int month_uncertainty
int day_uncertainty
int year_uncertainty
}
If so, what are the reasons why we typically model dates as datetime, is it because of compactness? What are the pros and cons to using a table like this?
select * from birthdates
where year > 1000 and month = 11

Related

Dates don't compare properly - Power Bi

I would like to SUMX my Employees Wages, but without Employees who have any sickness record, in which selected date is. So, if Employee was sick from March 3rd to March 5th and Selected Date is March 4th, we don't take that Employee into an account.
That's How I Get A CurrentDay From Slicer:
That's How I Was Trying To At Least Sum Rows, In Which CurrentDay Is Before EndDate of Sickness Record:
And all I get is... The number of TOTAL rows in my sickness records table:
How can I filter that table, to get a valid result?
The structure of your tables is not clear. So, looking through your code you can try following:
COUNTROWS(
FILTER(
table -- ALL(table) as variant, depends on your report ect.
,table[StartDate] <= SELECTEDVALUE(Calendar[Date]) & table[EndDate] >= SELECTEDVALUE(Calendar[Date])
)

Sum from/to date

I have 3 tables, one with stocktakes conducted last year, one with stocktakes conducted this year and one with sales. All of them are joined by date to one table where I have dates.
Now the question is what can I do to get table with:
store name/ last year stocktake date/ this year stocktake date/ sum of sales from last year stocktake date to this year stocktake date.
If you choose store, than stocktake date from one table, stocktake from second table all looks good, the problem is that I can't get sales to show from/to.
C2Csales = calculate(sum(PP_SalesLessTax[SalesLessTax]),PP_SalesLessTax[date] >= [ly date])
[ly date] is just a measure with last year stocktake date
I have a feeling that this have to be very easy but have no idea how to get this work
thanks
daniel
please see data model. It is a part of bigger model but I have trimmed it so it is clear what is this about.
data model
And here is what I need. Please see picture.
thanks for all responses
result required
You don't need two tables to simulate years. You can have just one. The idea of last year should be calculated by a measure. If you have a complete date table with a day for each row without missing days then you can build time intelligence.
If I get you, you need something like this two measures:
Sales = sum(PP_SalesLessTax[SalesLessTax]
Sales LY = CALCULATE ( sum(PP_SalesLessTax[SalesLessTax] , SAMEPERIODLASTYEAR ( DatesTable[DateColumn] )
With this two measures you can take both of them on same visualizations to compare them.
The idea of having from and to can be solved on visualizations. The slicer with a date type column can create a range filter data that will apply for this two created measures.

Why are these two SQL date functions not providing the same answer

I've actually already solved the problem, but I'm trying to understand why the problem occurred because as far as I can see it has no reason to happen.
I have a rather large query that I run to prepare a table with some often used combinations. Generally, it only contains 2 years of data. Occasionally I will reconstruct it. While doing this I tweaked the query to add more information, but suddenly the result no longer matched up to the old query. Comparing the old to the new I noticed several missing orders. Amazingly, even after removing the tweaked parts the results still didn't match up.
I ultimately tracked the problem down to my WHERE clause, which was different from how I did it last time.
The type of the orderdate column I go over has type (datetime, null)
One of the orders that was omitted had this as date:
2018-12-23 20:58:52.383
An order that was included had this as date:
2019-01-28 15:20:49.107
It looks exactly the same to me.
The entire query is the same, except for the WHERE clause. My original where was:
WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE()-2)
My new where is now:
WHERE tborder.[OrderDate] >= DATEADD(yy, DATEDIFF(yy, 0, GETDATE())-2, 0)
Any help in understanding why the original where clause drops some lines would be greatly appreciated.
Because you are doing two different things. First predicate,
WHERE DATEPART(yyyy,tbOrder.[OrderDate]) >= DATEPART(yyyy,GETDATE()-2)
Take all order dates that are bigger than the year for the day before yesterday or two days before. Notice that, -2 is inside the brackets.
Second predicate,
WHERE tborder.[OrderDate] >= DATEADD( yy, DATEDIFF( yy, 0, GETDATE() ) - 2, 0)
Take all order dates bigger than two years before, i.e., datediff(yy,startdate,enddate) will return the year result of the difference between today and the initial value for date datatype, which is 1900-01-01. Then, add this, -2, to 1900-01-01. The second expression is the form of:
1900 + ( 201X - 1898 )
I simplified 1900 - 2 = 1898.
The two expressions return completely different things, so it shouldn't be a surprise the results are different. The first one returns the current year as a number (or the year of the day before yesterday to be precise). The second one returns January 1st two years ago.
You can put both expressions in a SELECT query to see what they return :
select DATEPART(yyyy,GETDATE()-2), DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) - 2, 0)
The result is :
2019 2017-01-01 00:00:00.000
Both expressions are more complex than they need to be. The first condition will also harm performance because DATEPART(yyyy,tbOrder.[OrderDate]) prevents the server from using any indexes that cover OrderDate.
The question doesn't explain what you actually want to return. If you wanted to return all rows in the current year you can use :
Where
OrderDate >=DATEFROMPARTS( YEAR(GETDATE()) ,1,1) and
OrderDate < DATEFROMPARTS( YEAR(GETDATE()) + 1,1,1)
The same can be used to find rows two years in the past :
Where
OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1) and
OrderDate < DATEFROMPARTS(YEAR(GETDATE()) - 1,1,1)
All rows since January 1st two years ago :
Where OrderDate >= DATEFROMPARTS( YEAR(GETDATE()) -2 ,1,1)
All those queries can take advantage of indexes that cover OrderDate.
Date range queries become a lot easier if you use a Calendar table. A Calendar table is a table that contains eg 50 or 100 years' worth of dates with extra columns for month, month day, week number, day of week, quarter, semester, month and day names, holidays, business reprorint periods, formatted short, long dates etc.
This makes yearly, monthly or weekly queries as easy as joining with the Calendar table and filtering based on the month or period you want.
In this case, retrieving rows two yeas in the past would look like :
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2
That may not looks so impressive but what about Q2 two years ago?
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=2
Two years ago, same quarter
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year=YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
Retrieving totals for the current quarter for the last two years :
SELECT Year,Quarter,SUM(Total) QuarterTotal
From Orders inner Join Calendar on OrderDate=Calendar.Date
Where Calendar.Year > YEAR(GETDATE())-2 and Quarter=DATEPART(q,GETDATE())
GROUP BY Calendar.Year

crystal reports - active employee formula

I am trying to make a report that gives an 'active snapshot' for a past month. For example - how many active women are employed in October?
The date (a particular month) I am going for the active snapshot will change. I am using the following fields in my formula employee.hire_date is the date the employee started with our organization, employee.term_date is the date employment ended.
I am then grouping employees by gender and using the employee.gender and then the employee.name
What do you guys think about this logic?
The employee.hire_date can be anytime during that month, minus the last day? The employee.term_date can be anytime during that month, minus the last day? I am saying minus the last day because the employee had to have worked at least 1 day during the month. I am stumped....
Then make a formula, and set the parameters to the first and last of the month?
I think you are in the right direction and it might help if i tell that i think you need to approach 6 different situations for a given month. The point is if there is an intersection between the employee working period and the given month.
Suppose:
h is the hire_date
T is the term_date
m is the fist day of a given month
M is the last day of a given month
See these "timelines": (sorry, a little bit confusing)
h..T..m........M...... (1- start and end before the month, no intersection)
......m..h..T..M...... (2- start and end inside the month, there is intersection)
......m........M..h..T (3- start and end after the month, no intersection)
h.....m........M.....T (4- start before the month, end after the month, intersection)
h.....m....T...M...... (5- start before the month, end inside the month, intersection)
......m...h....M.....T (6- start inside the month, end after the month, intersection)
So, there is intersection if h <= M and T >= m (hurray, karnaugh map!).
To ignore the last day, as you said, maybe it would be: h < M and T > m.
Create a running total field that count the employees by gender if there is intersection.
EDIT: Maybe the full formula should be:
{EMPLOYEE.Hire_Date}<={?Last of Month} and (
isnull({EMPLOYEE.Termination_Date}) OR
{EMPLOYEE.Termination_Date}>={?First of Month}
)

Get month from date parameter in MDX

I'm currently building reports using Reporting Services (and MDX language).
I get a date thanks to a parameter:
MEMBER [Measures].[retail sales amount] AS (
STRTOMEMBER(#TimecalendarTimecalendarmonthhierarchy)
, [Measures].[Retail sales amount invoiced including tax])
STRTOMEMBER(#TimecalendarTimecalendarmonthhierarchy) could be something like that [Time calendar].[Time calendar month hierarchy].[Time calendar date].&[2011-03-18T00:00:00]
I would like to only get the month of this parameter. When I use:
MTD([Time calendar].[Time calendar month hierarchy].[Time calendar date].&[2011-03-18T00:00:00]
, [Measures].[Retail sales amount invoiced including tax])
it works fine but that's not the case for
MTD(STRTOMEMBER(#TimecalendarTimecalendarmonthhierarchy)
, [Measures].[Retail sales amount invoiced including tax])
Try :
MTD( STRTOMEMBER(#TimecalendarTimecalendarmonthhierarchy) ) * {[Measures].[Retail sales amount invoiced including tax]}
If it does not work, what is the result of :
STRTOMEMBER(#TimecalendarTimecalendarmonthhierarchy).name
MTD will give you the set of dates from the first date of the month to the date specified. If you want to get the month, you can either use ANCESTOR or PARENT. Parent will work if Month is directly above Date in your hierarchy. The difference between SUM(MTD(date), measure) and (date.parent, measure) is obvious when you think about previous months - if you go to a month which is in the past MTD will give you partial results as opposed to the month member itself (for dates other than the last date of the month).
StrToMember essentially translates a string to a member expression in MDX. There is no difference (functionally) between writing:
([Time].[Month].&[201001], [Measures].[SomeMeasure])
and
(StrToMember("[Time].[Month].&[201001]"), [Measures].[SomeMeasure])
It would be interesting to hear what exactly the error is when you execute your non-working expression in order to debug.
If you just want to get the month amount for the measure, you should write:
(StrToMember(#param).Parent, [Measures].[Retail sales amount...])
or (if you have more levels in between):
(Ancestor(StrToMember(#param),
[Time calendar].[<hierarchy>].[<month level>]),
[Measures].[Retail sales amount...])
Also, when using MTD you want to write:
SUM(MTD(<date member>), [Measure].[Some Measure])
instead of
MTD(<date member>, [Measure].[Some Measure])
have a look at BOL's definition of MTD