SQL: Error using DATEFROMPARTS to add day from another date variable - sql

everyone:
I am trying to compare two dates, but they are given in two different formats:
[Open Date] given YYYY-MM-DD
[Monthly Fee Year] given in YYYY as int
[Monthly Fee Month] given in MM as int
I need to add the Day from Open Date to Monthly Fee. I just found out about DATEFROMPARTS, so I tried this:
SELECT [OPEN DATE]
,[Monthly Fee Year]
,[Monthly Fee Month]
,DATEFROMPARTS([Monthly Fee Year], [Monthly Fee Month], DAY([OPEN DATE]))
FROM [#temptable]
I know that the parameters for DATEFROMPARTS should all be int, and I believe all the parameters I put in are int, but I got this error even after I use CAST():
"Cannot construct data type date, some of the arguments have values which are not valid."
Here is some sample data:
OPEN DATE Monthly Fee Year Monthly Fee Month
2021-06-08 2021 8
2019-12-17 2020 3
2019-05-30 2020 3
2020-10-08 2021 2
2021-05-28 2022 3
And I want to add a column with:
Monthly Fee Date
2021-08-08
2020-03-17
2020-03-30
2021-02-08
2022-03-28
UPDATE: It turns out that Monthly Fee Year and Monthly Fee Month are nvarchar, so I tried to CAST or CONVERT them as int:
,DATEFROMPARTS(CAST([Monthly Fee Year] AS int), (CAST([Monthly Fee Month] AS int), DAY([OPEN DATE]))
,DATEFROMPARTS(CONVERT(int, [Monthly Fee Year]), CONVERT(int, [Monthly Fee Month]), DAY([OPEN DATE])
But I still get the same error.
What am I missing?
Thank you.

Your sample data is fine, which is throwing us off. DATEFROMPARTS() will also implicitly convert your NVARCHAR types to INT, so that's not your issue. Your problem is likely that you are trying to create invalid dates. For example, if the Open Date is 2021-05-31 and the Monthly Fee Year is 2021 and the Monthly Fee Month is 9, you are trying to create a date of '2021-09-31', which isn't valid.
You'll need to come up with some logic or a rule to deal with dates like that.
Edit:
If you get the first of the month for each date you are trying to build and find out how many months away from the Open Date that is, you can add that many months to Open Date and get what you are trying to accomplish, but the invalid dates would be handled properly.
, DATEADD(MONTH, DATEDIFF(MONTH, [Open Date], DATEFROMPARTS([Monthly Fee Year], [Monthly Fee Month], 1)), [Open Date])

This should work, not very elegant but will stop it from trying to create invalid dates:
IIF(DAY(EOMONTH(DATEFROMPARTS([Monthly Fee Year], [Monthly Fee Month], 1))) < DAY([OPEN DATE]),DATEFROMPARTS([Monthly Fee Year], [Monthly Fee Month],DAY(EOMONTH(DATEFROMPARTS([Monthly Fee Year], [Monthly Fee Month],1)))),DATEFROMPARTS([Monthly Fee Year], [Monthly Fee Month], DAY([OPEN DATE])))
First check if the last day in the month is less than the day of the open date
If it is then use the last day in month as the day
If not then use the day of the Open Date

Related

Converting MDX query into SSAS cube expression [Calculations]

How can I go around to amending this MDX query
WITH MEMBER [Measures].[PanelSoldMonthsPre]
AS ' [In Charge Date].[In Charge Date Days in Month].CURRENTMEMBER.membervalue'
MEMBER [Measures].PanelSoldMonths
AS [Measures].[Panel Sold Days] / [Measures].[PanelSoldMonthsPre]
SELECT
[Measures].[Panel Sold Days], [Measures].PanelSoldMonths} ON COLUMNS,
NON EMPTY
([In Charge Date].[In Charge Year].Children, [In Charge Date].[In Charge Date Days in Month].Children) ON ROWS
FROM [Cube]
to..
a) bring back Year Month and corresponding number of days in month. At the moment its returning just the unique [In Charge Date Days In Months].
I want it to return the [In Charge Date Days In Months] for all 12 months for each [In Charge Date].[In Charge Year]
b) placing it as an expression in the calculations (calculated measures) section of the cube project. I decided to create them as 2 separate members. Clearly does not work since I get a return of [Measures].[PanelSoldMonthsPre] '#VALUE!' on the cube (excel workbook)

Simple division in MDX

Trying to achieve the PanelSoldMonths rate using PanelSoldDays and DateDaysInMonth. However, I am getting a return of nulls when doing this simple division.
PanelSoldMonths = PanelSoldDays / DateDaysInMonth
WITH MEMBER [Measures].PanelSoldMonths AS
IIF ([In Charge Date].[In Charge Date Days in Month]= 0, NULL,
([Measures].[Panel Sold Days] / [In Charge Date].[In Charge Date Days in Month].Children))
SELECT
{[Measures].[Total Net Net Revenue], [Measures].[Panel Sold Days], [Measures].PanelSoldMonths}
ON COLUMNS,
NON EMPTY
([In Charge Date].[In Charge Year].Children, [In Charge Date].[In Charge Date Days in Month].Children)
ON ROWS
FROM [Combined Sales]
WHERE [Asset Info].[Format Group L2].&[Digital]
Replace
[In Charge Date].[In Charge Date Days in Month]= 0
with
[In Charge Date].[In Charge Date Days in Month].currentmember.Properties ("Member_Value",TYPED)=0

Calculated member in SSAS based on custom Last Year Date (Retail calendar)

I have spent a lot of time solving this issue, but no success yet.
I have a Date dimension called [Dim Date] and in this table I have a [Date Key] which contains all the dates from '2013-07-01' to '2016-12-31'. I also have a measure called [Retail Revenue] which is a decimal number for that date. So far so easy!
We are a retail Calendar and all our calculations/comparisons are based on a retail calendar (which is a customized table in DW).
The date hierarchy in this calendar is as below (please see the screenshot):
-- retail year (e.g. 2017)
---- retail half year (e.g. 2017-H1)
------ retail quarter year (e.g. 2017-Q1)
-------- retail month (e.g. 201702) (months from 201701 to 201712)
---------- retail week (e.g. 201708) (weeks from 201701 to 201752)
------------ date key (e.g. 2016-08-22)
SCREENSHOT
We also have an attribute called "Retail Last Year Date" which shows the equivalent date of last calendar date (e.g. 2015-08-24 in the screenshot).
I need to have a calculated member showing the "Retail Revenue" for last year (based on the attribute "Retail Last Year Date"), next to the regular "Retail Revenue" for [date key].
I tried to use ParallelPeriod and Scope, and could not get the numbers properly. Probably an easy task but I am not a hero in mdx unfortunately!
Will be more than thankful if anyone please can help me out with this.
Thanks
Rez
Hopefully this helps.
This is against AdvWrks. I've created a query scoped custom measure that gets the internet sales from the year before:
WITH
MEMBER [Measures].[Internet Sales Amount LastYear] AS
(
ParallelPeriod
(
[Date].[Calendar].[Calendar Year]
,1
,[Date].[Calendar].CurrentMember
)
,[Measures].[Internet Sales Amount]
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[Internet Sales Amount LastYear]
} ON 0
,
[Date].[Calendar].[Date].&[20070121]
:
[Date].[Calendar].[Date].&[20070127] ON 1
FROM [Adventure Works];
Here are the results:
Thanks for your response, but I didn't get how it uses the dimension property? because my calendar is customized and I cannot assume the last year calendar date is the same as this year. I have to read it from the dimension property "Retail Last Year Date").
Thanks

SSAS DAX time intelligence previous year and calculation gives wrong value

We want to show current periods sales versus previous period sales.
To show the previous period we make use of a date dimenion table and the following calculation:
CALCULATE(SalesValueGross; DATEADD(Date[Date]; -1; YEAR))
Unfortunately somehow it shows minor (decimal) differences when comparing years.
The difference get's bigger when we slice to months.
Another issue we have is that this calculation does not seem to work when comparing (for example) week 1 - 2015 with week 1 - 2014.
Any help is greatly appreciated!
When I want to get prior calendar year sales, I use the a formula such as the following:
Cal Prior Yr Sales:=if(HASONEVALUE('Sale Date'[Calendar Year]),
Calculate([Total Sales],
PREVIOUSYEAR('Sale Date'[Date])),BLANK())
The HASONEVALUE just ensures that there is only one year selected so it will know the correct previous year to retrieve.
You can make a series of calculations that will let you use one calc that determines what level of the date hierarchy you are in (assuming you have the fields available in your date table). Here is something I've used in the past, with a fiscal calendar that was different from the normal calendar.
First, the base calculations:
Sales Same Week Prior Year:=
CALCULATE([Total Sales],Filter(All('Sale Date'),
'Sale Date'[Week Key] = max('Sale Date'[Same Week Last Year])))
Sales Same Month Prior Year:=CALCULATE([Total Sales], Filter(All('Sale Date'),
'Sale Date'[Month Seq] = max('Sale Date'[Month Seq])-12))
Sales Same Quarter Prior Year:=CALCULATE([Total Sales], Filter(All('Sale Date'),
'Sale Date'[Quarter Seq] = max('Sale Date'[Quarter Seq])-4))
Sales Prior Year:=CALCULATE([Total Sales], Filter(All('Sale Date'),
'Sale Date'[Fiscal Year] = max('Sale Date'[Fiscal Year])-1))
You can hide all of those calculations and then create one last calculation and leave it visible:
Sales Same Period Last Year:=
if(HASONEVALUE('Sale Date'[Week Key]), [Sales Same Week Prior Year],
if(HASONEVALUE('Sale Date'[Month Key]),[Sales Same Month Prior Year],
if(HASONEVALUE('Sale Date'[Quarter Key]),[Sales Same Quarter Prior Year],
if(HASONEVALUE('Sale Date'[Fiscal Year]), [Sales Prior Year], BLANK()))))
You may need to add a couple of calculated fields to your date table to make it work. I have fields for: [Same Week Last Year], [Month Seq], [Quarter Seq]. Same week last year is an integer field that is yyyyww. Month Seq and Quarter Seq are just autoincrementing integers in chronological order that do not repeat.
My formula for same week last year is
=if('Sale Date'[Week Nbr] = 53, (('Sale Date'[Fiscal Year]-1) * 100) + ([Week Nbr]-1),
(('Sale Date'[Fiscal Year]-1) * 100) + ([Week Nbr]))
I did the sequence numbers in my SQL view, which is the source for the date date. As an example, if my date table starts at 1/1/2010, the month seq for Jan 2010 is 1 and the month seq for Jan 2011 is 13. The quarter seq for Q1 2010 is 1 and the quarter seq for Q1 2012 is 9.
http://www.daxpatterns.com/time-patterns/ is a good read for this topic.

Selecting records where 'ActualLiveDate' is between today and X days in to the future with SQL Server

I'm trying to get the syntax to show a list of records where the Actual Live Date is equal to or greater than today by 7 days and ideally show how many per day (thursday = 7 records).
i was thinking something along the lines of:
SELECT [PW Number]
,[status]
,[install Date]
,[ICL Client Code]
,[Actual Live Date]
FROM
[QuoteBase].[dbo].[Circuits]
WHERE
[Actual Live Date] BETWEEN today and 7 days time (this is where I am a little stuck as im fairly new)
If you need "today" to start at 00:01 this morning, then you need to remove the time portion from e.g. GETDATE(). I'm also using explicit functions to show that I'm adding days:
SELECT [PW Number]
,[status]
,[install Date]
,[ICL Client Code]
,[Actual Live Date]
FROM
[QuoteBase].[dbo].[Circuits]
WHERE
[Actual Live Date] BETWEEN
DATEADD(day,DATEDIFF(day,0,GETDATE(),0) AND
DATEADD(day,DATEDIFF(day,0,GETDATE()+7,0)
If Actual Live Date contains a time component, you may want to adjust the +7 to +8, depending on exactly which rows should be included in the result or not.
you can use the BETWEEN and GETDATE() functions for this, the GETDATE() + 7 will add 7 days onto todays date
SELECT [PW Number]
,[status]
,[install Date]
,[ICL Client Code]
,[Actual Live Date]
FROM
[QuoteBase].[dbo].[Circuits]
WHERE
[Actual Live Date] BETWEEN GETDATE() AND GETDATE() + 7
If the column is actually a date, you need to be a bit careful:
[Actual Live Date] BETWEEN cast(GETDATE() as date) and cast(GETDATE() + 6 as date)
This would include today. If today is a Monday, it would include seven days up to next Sunday. If you would want next Monday too, then the -6 would be -7.
When the column is a date, The comparison [Actual Live Date] >= getdate() will always be false for dates today because of the time component.
Between works as expected for datetime values but not for date values.