Unexpected result from CoreData compound fetch with date range - swift

I have a simple data model with visitors (fName and lName) and visits (date, comment) in a 1-m relation. I'm trying to fetch all visitors for a particular day. In order to achieve this, I need to create a predicate to look for all entities having visits between the start of that day and its end. I have tried:
...
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "visitor")
let filter = "ANY visits.date >= %# AND ANY visits.date < %#" // visits is the visitors relation to visits
let startTime = calendar.startOfDay(for: thisDay) as NSDate
let endTime = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: thisDay)! as NSDate
fetchRequest.predicate = NSPredicate(format: filter, startTime, endTime)
The result are all visitors with visit dates at and after this day. Hence the second part of the compound predicate has no effect!
I've also tried to combine the two conditions with the NSCompoundPredicate, but the result is the same. I've experimented with other than date types with the same compound predicate and these all worked well. So despite extensive searches in the Internet, I have no clue how to solve this simple query with predicates.
Any suggestions are most welcome!

Your predicate fetches all visitors which are related to (at least one) visit with visits.date >= startDate and to (at least one) visit with visits.date < endDate. The problem is that those two related objects need not be the same for the predicate to return true.
What you need is a “subquery”: From the (related) NSExpression documentation:
This method creates a sub-expression, evaluation of which returns a
subset of a collection of objects. It allows you to create
sophisticated queries across relationships, such as a search for
multiple correlated values on the destination object of a
relationship.
...
The string format for a subquery expression is:
SUBQUERY(collection_expression, variable_expression, predicate);
where expression is a predicate expression that evaluates to a
collection, variableExpression is an expression which will be used to
contain each individual element of collection, and predicate is the
predicate used to determine whether the element belongs in the result
collection.
In your case it should be (untested):
NSPredicate(format: "SUBQUERY(visits, $v, $v.date >= %# and $v.date < $#).#count > 0",
startTime, endTime)
This fetches all visitors which are related to at least one visit whose date falls into the specified range.

Related

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).

Named query to show results by date (Year, month, day) in Grails 3.2.10

Given this domain:
class Burger{
String description
Date dateCreated
}
Currently, I have this namedQuery
queryOnDateCreated {Date dateArgument ->
eq 'dateCreated', dateArgument
}
I need a query that allows me find all the objects in the domain Burger with a specific dateCreated only taking into accountYear, Month and day (of month), while ignoring hours, minutes, seconds, miliseconds.
After some additional research, I found a solution which I'm going to share in case it helps someone else:
The named query needs to be as follows:
queryOnDateCreated {Date dateArgument ->
def dateArgumentIntervalEnd = DateUtils.addMilliseconds(dateArgument + 1, - 1)
between 'dateCreated', dateArgument, dateArgumentIntervalEnd
}
Explanation:
The "between" criteria returns every object in the domain whose date is between the interval given.
Since dateArgument is a Date created only with Year, Month and Day, it's time should be 00:00:00:000 (the first moment of the day).
Furthermore, "dateArgument + 1" holds the value of the next day (at the same time), which is why the substraction of 1 millisecond is required, that way "dateArgumentIntervalEnd" will hold the value of the same Year, Month and Day of "dateArgument" but the time will be 23:59:59:999 holding an interval of the whole day.

Filter date not between two dates

Using Realm 2.7.0 and Swift 3, my application tries to filter a object based on its date, returning all dates that are NOT between two given dates.
Given a Object called Model, it has an variable called date (type NSDate).
Currently, I am using this code to filter:
realm.objects(Model.self)
.filter("NOT date BETWEEN %#", [today, twoDaysAgo])
But it is returning all data, the filter is not working.
Thank you.
Try this
realm.objects(Model.self)
.filter("NOT (date BETWEEN %#)", [today, twoDaysAgo])
try this predicate query
let predicate = NSPredicate(format: "!(date BETWEEN %# , %#)", today, twoDaysAgo)

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

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.

How do you retrieve the last month's entries from core data

how do I ask core data to fetch me the last 30 elements entered or alternatively the elements entered within a month of today?
To fetch a certain number of records, use qualification like [fetchRequest setFetchLimit:30] in combination with NSPredicate instance you desired.
To retrieve elements within a range of time, you need first calculate the beginning and the end NSDate instances of the period you want, then code your predicate instance like:
NSPredicate *predicate = [NSPredicate predicateWithFormat:
#"(date >= %#) AND (date <= %#)", startDate, endDate];
See this and this.