How can I have the date just before the max/last Date and repeat the process on the whole table? - qlikview

I'm trying to calculate the delta between two values in different dates : the firt is the date Max(COD)
( Sum({<COD={"$(=Max(COD))"}>*<Contrat={'PRESTA'}>} if([FMonth.autoCalendar.Num]<>[COD.autoCalendar.Num], CapaPresta)) * 130/Hours +(sum( {<COD={"$(=Max(COD))"} >} if(Contrat = 'PRESTA' , Actual)) + sum( {<COD={"$(=Max(COD))"}>} if(Contrat = 'PRESTA' , Actual_hors_site)))* 130/Hours
Now i'm trying to calculate the same value for the date before the max(COD) so I tried this: I replaced the Max(COD) by :
{<COD={"$(=monthend(addmonths(Max(COD), -1)))
But it doesn't work.

Related

Unable to divide to counts of two separate lists in SQL, keeps returning 1

I have one list of events. One event name is creating an account and another is creating an account with Facebook. I am trying to see what percentage of accounts created use Facebook.
The code below will give me an accurate count of the number of facebook accounts and total accounts, but when I try to divide the two numbers it just gives me the number 1.
I am very new to SQL, and have spent hours trying to figure out why it is doing that to no avail.
with
fb_act as (
select *
from raw_event
where name = 'onboard_fb_success'
and event_ts::date >= current_date - 30
),
total_act as (
select *
from raw_event
where name ='create_account'
and event_ts::date >= current_date - 30
)
select count(fb_act)/count(total_act), total_act.event_ts::date as day
from total_act, fb_act
group by day
order by day
I expect the output to be about ~.3, but the actual output is always exactly 1.
Conditional aggregation is a much simpler way to write the query. You appear to be using Postgres, so something like this:
select re.event_ts::date as day,
(sum( (name = 'onboard_fb_success' and event_ts::date >= current_date - 30):: int) /
sum( name = 'create_account' and event_ts::date >= current_date - 30)::int)
) as ratio
from raw_event re
group by re.event_ts::date
order by day;

SSRS Report Multi Parameters (start date,end date, MeterId, Displayby)

In my SSRS report there are 4 parameters StartDate, EndDate, MeterId, & DisplayBy
Start Date: datetime datatype
EndDate : datetime datatype
MeterId : is a drop down list and this will populate based on SQL query
DisplayBy: is a drop down list and this has the following values (Hour,day,Month & year)
The Database that stores hourly values for Meters, the following are the DB table columns: (MeterId,ReadingDate,Hours,Quantity,Price)
When I select the startdate, end date and the meter Id and display i want to show report based on the startdate & enddate and then by display values.
If the display is hour, the we got display all the 24 hour values for the MeterId,Quantity, Price for the date range.
If the display is day, we got display total quantity and total price for the MeterId for that date range.
If the display is Month, we got display total quantity and total price for the MeterId for that date range.
If the display is Year, we got display total quantity and total price for the MeterId for that date range. Say for example If i select start date as 1-1-2016 and end date as 12-31-2016. My result should show 12 rows for each month with their total Quantity, Total price for that particular MeterID.
my DB table stores all the hourly values i know how to show the values on screen if the user selects the display dropdown as hour. But, dont know how to show the result for day/month/year or how to group it. Do I need to use "case" statement and if so what should i need to give on display parameters.
Please suggest your idea...
Row Grouping:
SELECT I.CustomerName, I.ReadingDate, I.IntegratedHour, I.IntegratedUsage, I.IntegratedGeneration, DATEPART(dd, I.ReadingDate) AS [Reading Day], DATEPART(mm,
I.ReadingDate) AS [Reading Month], DATEPART(yyyy, I.ReadingDate) AS [Reading Year]
FROM IntegratedHour_MV90 AS I INNER JOIN
CustRptMeterExtract AS CT ON CT.CustomerName = I.CustomerName
WHERE (I.ReadingDate >= #StartDate) AND (I.ReadingDate <= #EndDate) AND (I.CustomerName IN (#FacilityName))
Expected Result:
SSRS Current Output: Doesnot match
Depending on your layout you could set row grouping to an expression something like this
=SWITCH
(
Parameters!ReportBy.Value=1, Fields!Hour.Value,
Parameters!ReportBy.Value=2, Fields!Day.Value,
Parameters!ReportBy.Value=3, Fields!Month.Value,
Parameters!ReportBy.Value=4, Fields!Year.Value,
True, 0)
This assumes you have already have the hours/days/months/years in your dataset, if not then you would have to replace the field references with expressions to return the relevant month etc.
Based on what I can see above you'll need to add a grouping level for Customer before the group expression. Also, you Quantity expression should be a sum something like this
=SUM(FIelds!IntegratedGeneration.Value)
You may still have a problem though. I'm assuming Price is a unit price, so it does not make sense to sum that too. To get round this, you should calculate the LineValue (Qty * Price) in your dataset then change the price expression to be something like
=(SUM(FIelds!LineValue.Value)/SUM(Fields!IntegratedGeneratio‌​n.Value))
and this will give you the average price.
However, this may be slow and personally I would do the work in your dataset. Again assuming you have the months, years in your table then you could do something like this.
--DECLARE #ReportBy int = 1 -- uncomment for testing
select
MeterID, Price
, CASE #ReportBy
WHEN 1 THEN [Month]
WHEN 2 THEN [Year]
ELSE NULL
END AS GroupByColumn
INTO #t
from dbo.MyDataTable
SELECT
GroupByColumn
, SUM(Price) as Price
FROM #t
Group BY GroupByColumn
Order by GroupByColumn
This assumes your report parameter is called ReportBy, if not just swap the name out.

Calculate one hour difference between two dates

dataset = LOAD '/user/cloudera/project/answers.txt' USING PigStorage('\t') AS ( qid:chararray , i:chararray , qs:int, qt:long, tags:chararray, qvc:chararray , qac:int , aid:chararray, j:chararray, as:int, at:long);
onedate = FOREACH dataset GENERATE ToDate(qt*1000) as qstntime , ToDate(at*1000) as anstime,tags;
difftime = FILTER onedate by GetHour(qstntime)-GetHour(anstime)==1;
dump difftime;
Output
(2009-02-18T17:37:11.000-08:00,2009-04-17T16:22:01.000-07:00,"ctags")
(2009-02-18T20:31:17.000-08:00,2009-02-19T19:29:40.000-08:00,"iphone")
(2009-02-18T22:11:11.000-08:00,2009-03-20T21:58:21.000-07:00,"php")
(2009-02-18T23:36:58.000-08:00,2009-02-19T22:18:10.000-08:00,"sqlserver")
(2009-02-19T01:05:39.000-08:00,2009-02-20T00:44:53.000-08:00,"python")
which is wrong output. it is calculating subtraction only for hours. While subtracting it has to consider month and year also.
Since you are using GetHours, you are only comparing hours and hence the incorrect result. Instead use HoursBetween which compares the entire datetime object.It returns the number of hours between two DateTime objects.
difftime = FILTER onedate by (HoursBetween(qstntime,anstime) == 1);

DAX running total based on 3 columns, one of which is a repeating integer running total

Very new to DAX/PowerPivot, and faced with devilishly tricky question on day one.
I have some data (90,000 rows) I'm trying to use to calculate a cumulative fatigue score for folk working shifts(using PowerPivot/Excel 2016). As per the below screenshot, the dataset is shift data for multiple employees, that has a cumulative count of days worked vs. days off that resets back to 1 whenever they switch from one state to the other, and a 'Score' column that in my production data contains a measure of how fatigued they are.
I would like to cumulatively sum that fatigue score, and reset it whenever they move between the 'Days worked' and 'Days off' states. My desired output is in the 'Desired' column far right, and I've used green highlighting to show days worked vs. days off as well as put a bold border around separate Emp_ID blocks to help demonstrate the data.
There is some similarity between my question and the SO post at DAX running total (or count) across 2 groups except that one of my columns (i.e. the Cumulative Days one) is in a repeating sequence from 1 to x. And Javier Guillén's post would probably make a good starting point if I'd had a couple of months of DAX under my belt, rather than the couple of hours I've gained today.
I can barely begin to conceptualize what the DAX would need to look like, given I'm a DAX newbie (my background is VBA, SQL, and Excel formulas). But lest someone berate me for not even providing a starting point, I tried to tweak the following DAX without really having a clue what I was doing:
Cumulative:=CALCULATE(
SUM( Shifts[Score] ) ,
FILTER(Shifts,Shifts[Cumulative Days] <= VALUES(Shifts[Cumulative Days] )) ,
ALLEXCEPT( shifts, Shifts[Workday],Shifts[EMP_ID] ) )
Now I'll be the first to admit that this code is DAX equivelant of the Infinite Monkey Theorem. And alas, I have no bananas today, and my only hope is that someone finds this problem suitably a-peeling.
The problem with this table is there is no way to determine when stop summing while performing the cumulative total.
I think one way to achive it could be calculating the next first date where continuous workday status changes.
For example the workday status in the first three rows for EMP_ID 70073 are the same, until the fourth row, date 04-May which is the date the workday status changes. My idea is to create a calculated column that find the status change date for each workday serie. That column lets us implement the cumulative sum.
Below is the expression for the calculated column I named Helper.
Helper =
IF (
ISBLANK (
CALCULATE (
MIN ( [Date] ),
FILTER (
'Shifts',
'Shifts'[EMP_ID] = EARLIER ( 'Shifts'[EMP_ID] )
&& 'Shifts'[Workday] <> EARLIER ( 'Shifts'[Workday] )
&& [Date] > EARLIER ( 'Shifts'[Date] )
)
)
),
CALCULATE (
MAX ( [Date] ),
FILTER (
Shifts,
Shifts[Date] >= EARLIER ( Shifts[Date] )
&& Shifts[EMP_ID] = EARLIER ( Shifts[EMP_ID] )
)
)
+ 1,
CALCULATE (
MIN ( [Date] ),
FILTER (
'Shifts',
'Shifts'[EMP_ID] = EARLIER ( 'Shifts'[EMP_ID] )
&& 'Shifts'[Workday] <> EARLIER ( 'Shifts'[Workday] )
&& [Date] > EARLIER ( 'Shifts'[Date] )
)
)
)
In short, the expression says if the date calculation for the current workday series change returns a blank use the last date for that EMP_ID ading one date.
Note there is no way to calculate the change date for the last workday serie, in this case 08-May rows, so if the the calculation returns blank it means it is being evaluated in the last serie then my expression should return the max date for that EMP_ID adding one day.
Once the calculated column is in the table you can use the following expression to create a measure for the cumulative value:
Cumulative Score =
CALCULATE (
SUM ( 'Shifts'[Score] ),
FILTER ( ALL ( 'Shifts'[Helper] ), [Helper] = MAX ( [Helper] ) ),
FILTER ( ALL ( 'Shifts'[Date] ), [Date] <= MAX ( [Date] ) )
)
In a table in Power BI (I have no access to PowerPivot at least eight hours) the result is this:
I think there is an easier solution, my first thought was using a variable, but that is only supported in DAX 2015, it is quite possible you are not using Excel 2016.
UPDATE: Leaving only one filter in the measure calculation. FILTER are iterators through the entire table, so using only one filter and logic operators could be more performant.
Cumulative Score =
CALCULATE (
SUM ( 'Shifts'[Score] ),
FILTER (
ALL ( 'Shifts'[Helper], Shifts[Date] ),
[Helper] = MAX ( [Helper] )
&& [Date] <= MAX ( [Date] )
)
)
UPDATE 2: Solution for pivot tables (matrix), since previous expression worked only for a tabular visualization. Also measure expression was optimized to implement only one filter.
This should be the final expression for pivot table:
Cumulative Score =
CALCULATE (
SUM ( 'Shifts'[Score] ),
FILTER (
ALLSELECTED ( Shifts ),
[Helper] = MAX ( [Helper] )
&& [EMP_ID] = MAX ( Shifts[EMP_ID] )
&& [Date] <= MAX ( Shifts[Date] )
)
)
Note: If you want to ignore filters use ALL instead of
ALLSELECTED.
Results in Power BI Matrix:
Results in PowerPivot Pivot Table:
Let me know if this helps.

IN Clause issue

I have one SQL output table like this
ITEM,LOC,PERIOD,QUANTITY
101,US,07/22/2015,500
101,US,07/02/2015,0
102,LON,07/22/2015,0
102,LON,07/02/2015,1000
But I want the output table as follows,
ITEM LOC 07/22/2015 07/02/2015
101 US 500 0
102 LON 0 1000
Please find the code which I have used below,
select * from
(
select item, loc, period, quantity
from example
)
pivot
(
sum (quantity) for period in ('22/JUL/2015','02/JUL/2015'));
If it is for 2 dates, then no issue in mentionning the 'IN' clause
If it is 1000 dates like weekly, monthly and daily. Then how ?
Below command is not working in 'IN' clause.
SELECT PERIOD FROM EXAMPLE WHERE PERIOD < TO_DATE(22/JUL/2015);
Can you please help me to solve this issue ?
Thanks for your time.
Your issue may be incompatible data types. If the period column on your table is DATE type, you are trying to compare strings/VARCHAR with DATE type.
If period column is a DATE try changing your IN to
SELECT period FROM example WHERE period < DATE '2015-07-22';
or
SELECT period FROM example WHERE period < TO_DATE('22/JUL/2015', 'DD/MON/YYYY');