I have data for several years.
I have a problem with February this year when I try to get last year.
I think it's because 2020 is a leap year. But I have no clue how to solve this. I tried a lot of things.
My request is like that :
IIF
(
Iserror
(
Sum
(
YTD
(
ParallelPeriod
(
[Date Facture].[Mensuel].[Année]
,1
,StrToMember
("[Date Facture].[Mensuel].[Date].&["
+
Tail
(
(EXISTING
Descendants
(
[Date Facture].[Mensuel].CurrentMember,
,leaves
))
).Item(0).Member_Key
+ "]"
)
)
)
,[Measures].[Quantité Facturée AEC]
)
)
,null
,Sum
(
YTD
(
ParallelPeriod
(
[Date Facture].[Mensuel].[Année]
,1
,StrToMember
("[Date Facture].[Mensuel].[Date].&["
+
Tail
(
(EXISTING
Descendants
(
[Date Facture].[Mensuel].CurrentMember,
,leaves
))
).Item(0).Member_Key
+ "]"
)
)
)
,[Measures].[Quantité Facturée AEC]
)
)
What can I do to solve this?
Can you not just simplify to use the CURRENTMEMBER function?
IIF
(
Iserror
(
Sum
(
YTD
(
ParallelPeriod
(
[Date Facture].[Mensuel].[Année]
,1
,[Date Facture].[Mensuel].CURRENTMEMBER
)
)
,[Measures].[Quantité Facturée AEC]
)
)
,null
,Sum
(
YTD
(
ParallelPeriod
(
[Date Facture].[Mensuel].[Année]
,1
,[Date Facture].[Mensuel].CURRENTMEMBER
)
)
,[Measures].[Quantité Facturée AEC]
)
)
Related
I have the following code, (based on the community member help):
use [Credible];
WITH DataSource AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY epi.[client_id]) AS [row_id]
,epi.[client_id]
,CONVERT(date, epi.[admission_date]) AS [admission_date]
,CONVERT(date, DATEADD(MONTH, 3, epi.[admission_date])) AS [3Month Date]
,CONVERT(date, ISNULL(epi.[discharge_date], GETDATE())) AS [discharge_date]
FROM
[dbo].[ClientEpisode] epi
WHERE DATEADD(MONTH, 3, [admission_date]) <= ISNULL([discharge_date], GETDATE())
),
RecursiveDataSource AS
(
SELECT
[row_id]
,[client_id]
,[admission_date]
,[3Month Date]
,[discharge_date]
,0 AS [level]
FROM
DataSource
UNION ALL
SELECT
ds.[row_id]
,ds.[client_id]
,ds.[admission_date]
,DATEADD(MONTH, 3, rds.[3Month Date])
,ds.[discharge_date]
,[level] + 1
FROM
RecursiveDataSource rds
INNER JOIN DataSource ds ON
rds.[row_id] = ds.[row_id] AND DATEADD(MONTH, 3, rds.[3Month Date]) < ds.[discharge_date]
)
SELECT *
FROM RecursiveDataSource
ORDER BY [row_id]
,[level]
-- OPTION (MAXRECURSION 32767);
This code works with the speed around 30 sec if there are up to 1 000 records in the table.
But my table is over 14 000 records, and will grow more,
and the code works 10+++ min
Is there way to make its performance in 30 sec or so?
Thank you for help
As here you are looking for performance solution, I will advice to skip using recursive CTE and solve the issue in another way.
For example, a variant of this:
DECLARE #DataSource TABLE
(
[client_id] INT
,[adm_date] DATE
,[disch_date] DATE
);
INSERT INTO #DataSource ([client_id], [adm_date], [disch_date])
VALUES (1002, '3/11/2005 ', '5/2/2005')
,(1002, '8/30/2005 ', '2/16/2007')
,(1002, '3/16/2017 ', NULL);
DROP TABLE IF EXISTS #DataSource;
DROP TABLE IF EXISTS #DataNumers;
CREATE TABLE #DataSource
(
[client_id] INT
,[adm_date] DATE
,[disch_date] DATE
,[diff_in_months] INT
);
CREATE TABLE #DataNumers
(
[number] INT
);
DECLARE #max_diff_in_months INT;
INSERT INTO #DataSource ([client_id], [adm_date], [disch_date], [diff_in_months])
SELECT [client_id]
,[adm_date]
,ISNULL([disch_date], GETUTCDATE()) AS [disch_date]
,CEILING(DATEDIFF(MONTH, [adm_date], ISNULL([disch_date], GETUTCDATE())) * 1.0 / 3.0) - 1
FROM #DataSource
WHERE DATEADD(MONTH, 3, [adm_date]) <= ISNULL([disch_date], GETUTCDATE());
SELECT #max_diff_in_months = MAX([diff_in_months])
FROM #DataSource;
INSERT INTO #DataNumers ([number])
SELECT TOP (#max_diff_in_months) ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM [master]..[spt_values];
SELECT DS.[client_id]
,DS.[adm_date]
,DATEADD(MONTH, DN.[number] * 3, [adm_date]) AS [3Month Date]
,DS.[disch_date]
FROM #DataSource DS
CROSS APPLY #DataNumers DN
WHERE DS.[diff_in_months] >= DN.[number];
The algorithm is the following:
select only the rows we needed
calculate the differences in months/3 for each row
generate numbers in helper table
generate the new rows using cross apply
You can use CROSS JOIN if you have more then 2.5k numbers to generate but I remove it in my example. Also, we are using [master]..[spt_values] to generate the total periods. But it's just one way for generating numbers in T-SQL. You can check the link and use another technique if you like.
The idea is to find the periods between each [adm_date] and [disch_date] - and a period is measure by 3 months - that's why we are using DATEDIFF with MONTH and then dividing by 3. We are using ceiling to get the upper value. Of course, you can generate more periods than needed and exclude them with WHERE clause in the final result.
I would like to know how can I calculate total row counts stratified by day of the week
SELECT
OPERATOR,
[Monday],
[Tuesday] ,
[Wednesday] ,
[Thursday] ,
[Friday]
COUNT(*) AS TOTAL -- i can not do this / HOW TO MAKE ?
FROM (
SELECT DISTINCT ID,
OPERATOR,
Datename(weekday, TAB_DATE) DAY
FROM #TABLES
WHERE
TAB_DATE>=DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
AND TAB_DATE<DATEADD(wk,1,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)) and
OPERATOR_ID IN (111,222,444) GROUP BY ID,OPERATOR,TAB_DATE
) AS p
PIVOT (
COUNT (ID)
FOR DAY IN ( [Monday], [Tuesday], [Wednesday], [Thursday], [Friday])) pvt
Put all you have in subquery and then add each day result to make a total:
SELECT
*,
[Monday] + [Tuesday] + [Wednesday] + [Thursday] + [Friday] AS TOTAL
FROM (
SELECT
OPERATOR,
[Monday], [Tuesday], [Wednesday], [Thursday], [Friday]
FROM (
SELECT DISTINCT
ID, OPERATOR, Datename(weekday, TAB_DATE) DAY
FROM #TABLES
WHERE TAB_DATE>=DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
AND TAB_DATE<DATEADD(wk,1,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0))
AND OPERATOR_ID IN (111,222,444)
GROUP BY ID, OPERATOR, TAB_DATE
) AS p
PIVOT (
COUNT (ID)
FOR DAY IN ([Monday], [Tuesday], [Wednesday], [Thursday], [Friday])
) pvt
) t
I have formatted your code.
If I understand you correctly, you can use OVER Clause for this:
SELECT
OPERATOR,
[Monday],
[Tuesday] ,
[Wednesday] ,
[Thursday] ,
[Friday],
COUNT(*) OVER()
FROM (
SELECT DISTINCT ID,
OPERATOR,
Datename(weekday, TAB_DATE) DAY
FROM #TABLES
WHERE
TAB_DATE>=DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)
AND TAB_DATE<DATEADD(wk,1,DATEADD(wk, DATEDIFF(wk,0,GETDATE()), 0)) and
OPERATOR_ID IN (111,222,444) GROUP BY ID,OPERATOR,TAB_DATE
) AS p
PIVOT (
COUNT (ID)
FOR DAY IN ( [Monday], [Tuesday], [Wednesday], [Thursday], [Friday])) pvt
I am trying to write a query in ssas calculations tab for which should produce the below result. It is like a YTD calculation which i am calculating from 1st Feb 2016 till today. I have written the below query in Management Studio but i need to convert it into SSAS calculations and write it into Calculations tab.
WITH
MEMBER [Measures].[ytd Sales Target 2] AS
Sum
(
StrToMember
(
'[Sales Date].[Date].&[' + Format(Now(),'yyyy-') + '02-01T00:00:00]'
)
:
StrToMember
(
'[Sales Date].[Date].&[' + Format(Now(),'yyyy-') + Format(Now(),'MM-')
+
Format
(
Now()
,'dd'
)
+ 'T00:00:00]'
)
,[Measures].[sales target]
)
SELECT
[Measures].[ytd Sales Target 2] ON 0
FROM [sales];
It should be as simple as:
CREATE MEMBER CURRENTCUBE.[Measures].[ytd Sales Target 2]
AS
Sum
(
StrToMember
(
'[Sales Date].[Date].&[' + Format(Now(),'yyyy') + '-02-01T00:00:00]'
)
:
StrToMember
(
'[Sales Date].[Date].&[' + Format(Now(),'yyyy-MM-dd')+'T00:00:00]'
)
,[Measures].[sales target]
),
VISIBLE = 1;
This way won't take your Date into account. But with a little change it can be "time aware". I added a little check for dates before 1st Feb to be ignored.
CREATE MEMBER CURRENTCUBE.[Measures].[ytd Sales Target 2]
AS
iif(
[Sales Date].[Date].CURRENTMEMBER.MEMBER_KEY < StrToMember('[Sales Date].[Date].&[' + Format(Now(),'yyyy') + '-02-01T00:00:00]').MEMBER_KEY
,NULL
,Sum (
StrToMember
(
'[Sales Date].[Date].&[' + Format(Now(),'yyyy') + '-02-01T00:00:00]'
)
:
StrToMember
(
[Sales Date].[Date].CURRENTMEMBER
)
,[Measures].[sales target]
)
),
VISIBLE = 1;
This is my code below......
SELECT
{
[Measures].[ACPPurchaseValue]
} ON COLUMNS
,(
[Date].[YYYYMMDD].[YYYYMMDD]
) ON ROWS
FROM [Kahuna]
WHERE
(
[Reporting Currency].[reportingCurrency].&[1]
,strToSet(#MdxBOSP)
,strToSet(#MdxVIPType)
,strToSet(#MdxHost)
,strToSet(#MdxOperatorName)
);
How can I say where [Date].[YYYYMMDD].[YYYYMMDD] < getdate()
You need to initially create a member, or a single member set, that corresponds to today.
The following looks a little complex but is actually a fairly standard approach - put forward by Tomislav Piasevoli - it is against the AdvWrks dimension Date:
WITH
MEMBER [Measures].[Key for Today] AS
Format
(
Now()
,'yyyyMMdd'
)
MEMBER [Measures].[Today string] AS
'[Date].[Calendar].[Date].&[' + [Measures].[Key for Today] + ']'
SET [Today] AS
StrToMember
(
[Measures].[Today string]
,constrained
)
...
So applying to your situation:
WITH
MEMBER [Measures].[Key for Today] AS
Format
(
Now()
,'yyyyMMdd'
)
MEMBER [Measures].[Today string] AS
'[Date].[YYYYMMDD].[YYYYMMDD].&[' + [Measures].[Key for Today] + ']'
SET [Today] AS
StrToMember
(
[Measures].[Today string]
,constrained
)
SELECT
[Measures].[ACPPurchaseValue] ON 0
,{null:[Today].item(0).item(0)} ON 1
FROM [Kahuna]
WHERE
(
[Reporting Currency].[reportingCurrency].&[1]
,strToSet(#MdxBOSP)
,strToSet(#MdxVIPType)
,strToSet(#MdxHost)
,strToSet(#MdxOperatorName)
);
Two other better solutions which could simplify life for everyone:
Do not materialize future dates in your cube
Leave future dates in, but add a custom set called [Today] and a calculated member called today as a child to Date's All member.
I am stucking by calculating the timestamp,how can i calculate/sum on different timestamp, example as below
Time (Timestamp in one column)
***********************
0:00:01
0:00:08
0:00:12
0:00:38
0:01:04
2:04:49
15:48:38
23:30:59
7:05:52
8:17:29
I want to show the sum(timestamp) in hh:mi.Any help?
i can tel you in postgresql you can do like
postgres=# select time '05:00' - time '03:00';
?column?
----------
02:00:00
(1 row)
dont know how much this can help you
This example works on DB2 when the values being added are TIME columns (as shown in original question). The trick is to convert the times to elapsed seconds, which are much easier to add up.
WITH origTbl (origTime) AS (VALUES
( TIME( '0:00:01' ) ),
( TIME( '0:00:08' ) ),
( TIME( '0:00:12' ) ),
( TIME( '0:00:38' ) ),
( TIME( '0:01:04' ) ),
( TIME( '2:04:49' ) ),
( TIME( '15:48:38' ) ),
( TIME( '23:30:59' ) ),
( TIME( '7:05:52' ) ),
( TIME( '8:17:29' ) )
)
,
totSeconds( secs ) AS (
SELECT SUM( MIDNIGHT_SECONDS( origTime ) )
FROM origTbl
)
SELECT RTRIM( CHAR( secs/3600 ) ) || ':' ||
LPAD( RTRIM( CHAR( MOD(secs, 3600)/60 ) ), 2, '0' ) || ':' ||
LPAD( RTRIM( CHAR( MOD(secs, 60) ) ), 2, '0' ) AS totHMMSS FROM totSeconds
;
TOTHMMSS
-----------------
56:49:50
1 record(s) selected.