Aggregating date data with entity framework grouped by day, month, qtr, year, etc - entity-framework

I have a table that records activities. All activities have an activitydate. I want to count how many activities for a given period of time (day, month, qtr, etc.). I want to include all dates even those that have zero activities. I could do this in the Data Tier with a DateDimension table where the date table has a single column called day containing one row for each calendar day and a outer join, group by query:
DateDimension Table
| Day |
|1/1/2013 00:00:00 |
|1/1/2013 00:00:00 |
|1/1/2013 00:00:00 |
Query
SELECT CAST(Day AS DATE), COUNT() AS CountOfActivities
FROM DateDimension dd LEFT OUTER JOIN Activities a
ON CAST(dd.Day AS DATE) = CAST(a.ActivityDate AS DATE)
WHERE Day BETWEEN MyStartDate AND MyEndDate
GROUP BY CAST(Day AS DATE)
ORDER BY CAST(Day AS DATE)
I'm using EntityFramework so I'd like to execute this query using Linq. The DateDimension table has no business value residing in the database. It exists only to support these aggregate queries by providing a list of dates so I can ensure a row is returned if no activities exist for a given day.
I have the idea that I could manufacture a list of days in memory and weave them in to the results of a much simpler database query at runtime. By perhaps Concatenating the results from 2 IEnumerables - 1 from the in memory enemurable of dates and the other from the database results. How could I do that? Should I do that?

How about something like this:
Example date range:
var from = DateTime.Today.AddDays(-30);
var to = DateTime.Today;
Dictionary to hold your tally of activities per day:
var activityCounts = new Dictionary<DateTime, int>();
Seed with a zero count for each day in the range (this is equivalent to setting up your date dimensions table):
Enumerable.Range(0, (to - from).Days + 1)
.ToList()
.ForEach(x => activityCounts[from.AddDays(x)] = 0);
Add in the real activity counts for each day in the range:
context.Activities.Where(a => a.DateTime >= from && a.DateTime <= to)
.GroupBy(a => a.DateTime)
.ToList()
.ForEach(x => activityCounts[x.Key] = x.Count());
In this way, you only hit the database for the aggregation of activities for dates with activities. The padding out of the resultset with contiguous dates within the date range is then performed on the app server.
Just need to be careful how your dates are stored in the database. This code example is expecting to be able to match keys in the activity dictionary based on the the format of the calls to DateTime.Today. You will need to shape your dates in your database query accordingly.

Related

DAX Calculate Billing Days Between Two Variable Dates

I have a dimdate table that is represented below. I have each day flagged as BusinessDay Y/N. I also have a DimSalesRep table that has a daily goal for each rep. I want to be able to allow users to input a StartDt and EndDt with filters on the report and have a calculated column look at the business days between those dates. I can calculate daysbetween with defined dates but I am unsure how I would use DAX with variable dates that are applied through Report filters.
I should also note I am not sure how best to handle a startdt and enddt filter based of the column, TheDate
Cheers!
Reference your dimdate table twice
StartDate = 'dimdate'
EndDate = 'dimdate'
and use this measure:
Num BusinessDays =
CALCULATE(
COUNTROWS('dimdate'),
'dimdate'[BusinessDay] = "Y",
'dimdate'[Date] >= SELECTEDVALUE(StartDate[Date]),
'dimdate'[Date] <= SELECTEDVALUE(EndDate[Date])
)

Get months names between two dates Ms-Access

I have this query
SELECT TblSales.ProductCode, TblSales.ProductName, TblSales.QtySold, Right([Zdate],7) AS [Mn/Yr]
FROM TblSales
WHERE (((TblSales.zDate) Between [Forms]![FrmSales]![From] And [Forms]![FrmSales]![FinalTo]))
GROUP BY TblSales.ProductCode, TblSales.ProductName, TblSales.QtySold, Right([Zdate],7);
I need this result to be like these columns (ProductCode-ProductName-Sum Of QtySold in First month from the given date - Second month - Third month - and so on)
Example : If the two dates were #1-1-2018# To #31-3-2018# -These dates can be changed due to [Forms]![FrmSales]![From] And [Forms]![FrmSales]![FinalTo]-
Columns:
ProductCode -ProductName -Jan-2018 -Feb-2018- March-2018
Rows:
A1-Computer-2000-2500-3000
Previous Qty is the SumOfQtySold in every month between the two dates,Thanks in advance.
Edit #1 :
I couldn’t make a crosstab query and this message popup Crosstab Error
You can use a crosstab query to transpose row data into columns. Something like this:
PARAMETERS StartDate DateTime, EndDate DateTime;
TRANSFORM NZ(Sum(tblSales.QtySold), 0) AS SumOfQtySold
SELECT tblSales.ProductCode, tblSales.ProductName
FROM tblSales
WHERE (((tblSales.zDate) Between [StartDate] And [EndDate]))
GROUP BY tblSales.ProductCode, tblSales.ProductName
PIVOT Format([tblSales].zDate,"mmm-yyyy");

Calculate a Reference Date in DAX

Trying to nail down the syntax for a pretty straightforward problem.
I have a table called Events and a full-feature DATES table with a relationship between the Dates[Date] field.
Using the event name as a slicer, I trying to create a [First Monday] measure that will return the date of the first Monday of the month.
So for example, if my event date was 2/14/19, [First Monday] would return 2/4/19.
Your Date table needs to contain 2 columns:
Year-Month: for example, "2018-01"
Weekday Number: for example, 1 (for Monday); or Weekday Name (i.e, "Monday")
Then:
First Monday =
CALCULATE( MIN('Date'[Date]),
ALL('Date'),
VALUES('Date'[Year-Month]),
'Date'[Weekday Name] = "Monday")
How it works:
First, we need to access all dates in the Date table, so we use ALL()
Second, we need to see only dates for the current context year and month, for which we can use VALUES()
Third, for each month we only want Mondays, hence Date[Weekday] = "Monday"
All this unfiltering/filtering generates a set of Mondays for the Year-Month visible in the current filter context. All we need to do now is to find the earliest of the Mondays using Min(Date).

Create a measure to return the maximum date about the order in a fact table. (SSAS Multidimensional)

I want to create a measure which return the maximum date about Orders but before the actual day
I will write an example :
My tables here
(In my table Calendar i have the year 2016,2017,2019, and in my Order table, i have an order for 2016 and 2019,
I want the last date order but before the actual day (18/05/2017), so i want the Date 01/01/2016).
I have 2 table, a dimension Calendar and a fact table Order.
I was thinking about the function filter, so i search how to use filter in
google, and all the solutions i found use 'With' and 'Select'.
(I can't use 'With' and 'Select' when i create a measure in SSAS multidimensional).
Hope i will see your advice.
Just like this similar case in adv cube?
[max order date] return the maximum date about [Internet Sales Amount]
with member [max order date] AS
tail(NONEMPTY([Date].[Date].[Date],[Measures].[Internet Sales Amount])).item(0).item(0).PROPERTIES( "name" )
select {[max order date] } on 0 from [Adventure Works]
if yes, then you can create a measure in your cube like this:
Create Member CurrentCube.[Measures].[max order date]
As tail(NONEMPTY([Date].[Date].[Date],[Measures].[Internet Sales
Amount])).item(0).item(0).PROPERTIES( "name" );
if only till current day, then(following is refer to adv cube, you need do some code changes per your cube):
Create Member CurrentCube.[max order date] AS
Tail
(
NonEmpty
(
{
Head([Date].[Date].[Date]).Item(0).Item(0)--the first day in your Date dim
:
StrToMember("[Date].[Date].&[" + Format(Now(),"yyyyMMdd") + "]")-- as of current day
}
,[Measures].[Internet Sales Amount]
)
).Item(0).Item(0).Properties("name")
IDE to Write, Analyze, Tuning, Debug MDX efficiently (www.mdx-helper.com)

Soft coding dates in HIVE

I am having a difficult time soft coding dates in HIVE.
I want to do a count of unique ID's the appear in each week of my data.
e.g.
SELECT
Count(distinct ID)
From Database.Table
Where filter1 = "Thing1" And filter2 = "Thing2"
AND TO_DATE(timestamp_utc) between TO_DATE("2016-04-10") AND TO_DATE("2016-04-16")
But I want this not just for one week but for each week so far this year, without having to run it 20 times with different dates manually typed in.
Any suggestions? Thank you.
Filter the data for the year,get the week number, group by id,week number
select count(distinct id) as id_count,weekofyear(TO_DATE(timestamp_utc)) as weeks
from Table
where filter1 = "Thing1" and filter2 = "Thing2" and TO_DATE(timestamp_utc) > '2016-01-01'
group by id,weeks