How to convert 365 days to one year in postgresql? - postgresql

How do I convert 365 days to equal 1 year in PostgreSQL, in a new column within a query?
Let's say we have three columns:
Department
Employee
Days_of_Service
How can I create an extra column where 365 days = 1 year? I would assume this would be a float if the days were over and/or under 365 days. Feel free to explain what this process is called, I would love to better understand it for future queries.
The data in Days_of_Service is just an INT (i.e. 1 day = 1)
We can assume the original code is:
SELECT
Department
, Employee
, Days_of_Service
, SOLUTION AS years_of_service --Basically, 356 days should = 1 year in this column
From employee_list
I cannot find anything about unit conversions for PostgreSQL, for this specific situation.

Since a year does not consist of exactly 356 days, your best bet is to divide the number of days by the length of a tropical year in days:
days_of_service / 365.242189 AS years_of_service

Related

MDX Get Sales starting from 2 years ago to today

I'm trying to make a dynamic report that pull sales starting from the first day of the fiscal year 2 years ago up to today and rolls forward with each new fiscal year. Our fiscal years don't line up with calendar years.
I have little MDX experience and am still learning.
So it should look at todays date, get the current fiscal year, subtract 2 years from it and then pull sales starting from that year up to today.
I had some difficulty just trying to get the date working correctly as I was getting errors however the below query now pulls yesterdays sales for me. I assume I need to reference [Date].[Year] as well, but I don't know how to use it to get my desired results.
SELECT
NON EMPTY
{ [Measures].[Gross Margin Percentage],
[Measures].[Gross Margin Value],
[Measures].[Sales Value],
[Measures].[Sales Units] }
ON COLUMNS
FROM IMR
Where
{StrToMember("[Date].[Date].&" + Format(CDate(now()-1), "[yyyy-MM-ddT00:00:00]"))}
If you'd like the results to be across a range of dates then try StrToSet in your WHERE clause and construct in a similar way to what you are doing.
You currently have this:
Where
{StrToMember("[Date].[Date].&" + Format(CDate(now()-1), "[yyyy-MM-ddT00:00:00]"))}
Here is an example for 2 days which you can adapt to your needs:
Where
{StrToSet(
"[Date].[Date].&" + Format(CDate(now()-3), "[yyyy-MM-ddT00:00:00]")
+ ":"
"[Date].[Date].&" + Format(CDate(now()-1), "[yyyy-MM-ddT00:00:00]")
)}

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

Total today, total yesterday ... total 7 days ago, total last week, average this month -data awareness in Power BI

I want an easy way to have a sum of yesterday, the day before and the day before that total 7 columns (past 7 days)
Then i would like average for L7D, Average LM.
I have made a column in my date that indicate what "today" is and then my idea was to have it sum if today, sum if today-1, sum if today-2 but this does not seem to work
)
Yesterday= CALCULATE(SUM('DanvægtLines'[NAV_Qty]);FILTER('DanvægtLines';'DanvægtLines'[Dato_Anden]>=TODAY()-1)
(It take the sum of quanto, then filters if the 2.date on the order is today)
It is only working with ">=" not if i only use "=" ... witch is ok for yesterday, but the if i want to have only 4 days ago i have to filter yesterday, the day before, and 3 days ago... witch make a very very long code line i dont get why
=(today()-4 wont work)
Ok so after about 15 hours of hair pulling it dawned on me that the table I was referring to was in the date+time format, so fixing that I could use =today()-1

How to calculate average weekly hours between 2 dates covering multiple weeks?

Postgresql 8.4.
I'm new to this concept so if people could teach me I'd appreciate it.
For Obamacare, anyone that works 30 hours per week or more must be offered the same healthcare as is offered to any other worker. We can't afford that so we have to limit work hours for temp and part-timers. This is affecting the whole country.
I need to calculate the hours worked (doesn't matter if overtime,
regular time, double time, etc) between two dates, say Jan 1, 2014,
and Nov 1, 2014 (Saturday) for each custom week (which beings on Sunday), not the week as defined by Postgresql (which begins on Monday).
Each of my custom work weeks begins on Sunday and ends on Saturday.
I don't know if I have to include weeks where
they did not work at all in the average, but let's assume I do. Zero hours that week would draw down the average.
Table name is 'employeetime', date field is 'employeetime.stopdate', hours worked per day is in the field 'employeetime.hours', employeeid field is 'employeetime.empid'.
I'd prefer to do this in one query per employee and I will execute the query once per employee as I loop through employees. If not I'm open to suggestions. But I'd like to understand the SQL presented in the answer.
Currently EXTRACT(week from '2014-01-01') calculates the start of the week as a Monday, so that doesn't work for me. Link here.
How would I do that without doing, say a separate query for each week, per person? We have 200 people to process.
Thank you.
I have set up a table to match your format:
select * from employeetime order by date;
id date hours
1 2014-11-06 10
1 2014-11-07 3
1 2014-11-08 5
1 2014-11-09 3
1 2014-11-10 5
You can get the week starting on Sunday by shifting. Note, here the 9th is a Sunday, so that is where we want the boundary.
select *, extract(week from date + '1 day'::interval) as week
from employeetime
order by week;
id date hours week
1 2014-11-07 3 45
1 2014-11-06 10 45
1 2014-11-08 5 45
1 2014-11-09 3 46
1 2014-11-10 5 46
And now the week shifts on Sunday rather than Monday. From here, the query to get hours by week/employee would be simple:
select id, sum(hours) as hours, extract(week from date + '1 day'::interval) as week
from employeetime
group by id, week
order by id, week;
id hours week
1 18 45
1 8 46