How to select mondays with sqlite/sequel? - ruby

In my SQLite-DB I want to select all entries on a monday.
How can I do it with Sequel?
A test example:
require 'sequel'
DB = Sequel.sqlite()#'test.db')
DB.create_table(:days) do
String :text
Date :start
end
Date.today.upto(Date.today + 30){|d|
DB[:days].insert( :text => d.strftime("%Y-%m-%d day %w in week %W"), :start => d)
}
How can I select all mondays?
In native SQL I can do:
select * from days where strftime("%w", start) = "1"
Using this, I can define a view and select for it:
DB.run('create view mondays as select * from days where strftime("%w", start) = "1"')
p DB[:mondays].all
But I would like to use it from Sequel.
I tried
sel = DB[:days].filter{ start.strftime("%w", :start) == '1' }
#NoMethodError
sel = DB[:days].filter{ Sequel::SQL::Function.new(:strftime, "%w", :start) == '1' }
#SELECT * FROM `days` WHERE (1 = 0)
but without success.
Are there any other solutions?
I'm looking also for a possibility to select items by hour of day (all items with a timestamp, and then from 12:00-13:00 ...) I think this is the same problem and a solution for the day of week-selection will also solve my other problem.

Here are the problems with your examples:
sel = DB[:days].filter{ start.strftime("%w", :start) == '1' }
#NoMethodError
This uses a virtual row, so calling start returns a Sequel::SQL::Identifier. The Sequel::SQL::Identifier#strftime method does not exist, hence the NoMethodError.
sel = DB[:days].filter{ Sequel::SQL::Function.new(:strftime, "%w", :start) == '1' }
#SELECT * FROM `days` WHERE (1 = 0)
This fails because you are using ==. Sequel doesn't override ==, and ruby's default == returns false. On SQLite, Sequel represents false as (1 = 0).
This should work:
sel = DB[:days].filter{{strftime("%w", :start) => '1'}}
# SELECT * FROM `days` WHERE (strftime('%w', `start`) = '1')
This uses a hash (the inner {}) inside a virtual row block (the outer {}). In Sequel, equality is represented by hashes.

Related

How do I select a range of keys from tarantool, like with SELECT BETWEEN in SQL?

Since this is on of the most common questions in https://t.me/tarantool and https://t.me/tarantoolru, I post the answer here.
space:pairs(from, 'GE'):
take_while(function(x) return x.field <= to end)
-- :totable() or use the result in the for-loop
For multipart keys see https://stackoverflow.com/a/57766656/1135874
You can do it using Lua as well as SQL.
1) Use a stored procedure in Lua, like this one:
function select_between(space_name, index_name, field_name, from, to)
local obj = index_name == nil and box.space[space_name] or box.space[space_name].index[index_name]
local result = {}
for _, tuple in obj:pairs(from, {iterator = 'GE'}) do
if (tuple[field_name] <= to) then
table.insert(result, tuple)
else
break
end
end
return result
end
select_between('test', nil, 'id', 1, 3)
2) Starting with Tarantool 2.0, you can use SQL (provided that you have space format):
box.execute('select * from "test" where "id" between 1 and 3;')

LINQ - how to get next three business days excluding dates in table?

I need to find the next three available business days for a scheduling application. What is available depends upon excluded dates in a table. So...as long as the date is not in my table and not a Saturday or Sunday, I want the next three. I'd like to find an efficient way of doing this.
I need to return a List<DateTime>. The table is simple - ExcludedDates has an ID and a DateTime with the excluded date.
I'd like to have a single LINQ query expression but can't figure it out...thanks to all in advance and I apologize if this is trivial or obvious - it isn't to me.
Try this...
DateTime start = DateTime.Now.Date;
var result = Enumerable.Range(1, 10) // make this '10' higher if necessary (I assume you only exclude non-workingdays like Christmas and Easter)
.Select(offset => start.AddDays(offset))
.Where(date => !( date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek== DayOfWeek.Sunday))
.Where(d=> !exceptionTable.Any(date => date == d))
.Take(3).ToList();
List<DateTime> result = (from i in Enumerable.Range(1, excludeTable.Rows.Count + 6)
let date = inputDate.AddDays(i)
where date.DayOfWeek != DayOfWeek.Saturday &&
date.DayOfWeek != DayOfWeek.Sunday &&
!excludeTable.Rows.Cast<DataRow>().Select(r => (DateTime) r["ExcludeDate"]).Contains(date)
select date).Take(3).ToList();
excludeTable.Rows.Count + 6 is to cover the worst case where you skip over every thing in the excludeTable and then you have to skip over another weekend.
This assumes that a month will be reasonable depending on your excluded dates.
DateTime date = DateTime.Today;
// first generate all dates in the month of 'date'
var dates = Enumerable.Range(1, DateTime.DaysInMonth(date.Year, date.Month)).Select(n => new DateTime(date.Year, date.Month, n));
// then filter the only the start of weeks
var results = (from d in dates
where d.DayOfWeek != DayOfWeek.Saturday && d.DayOfWeek != DayOfWeek.Saturday && !excludes.Any(i => i.DateTime.Date == d.Date) && date < d
select d).Take(3);
var excludedList = new List<long>() { DateTime.Parse("2011-07-27").Ticks };
var week = new List<long>(){
DateTime.Now.Date.Ticks,
DateTime.Now.Date.AddDays(1).Ticks,
DateTime.Now.Date.AddDays(2).Ticks,
DateTime.Now.Date.AddDays(3).Ticks,
DateTime.Now.Date.AddDays(4).Ticks,
DateTime.Now.Date.AddDays(5).Ticks,
DateTime.Now.Date.AddDays(6).Ticks,
DateTime.Now.Date.AddDays(7).Ticks,
DateTime.Now.Date.AddDays(8).Ticks
};
var available = (from d in week.Except(excludedList)
where new DateTime(d).DayOfWeek != DayOfWeek.Saturday && new DateTime(d).DayOfWeek != DayOfWeek.Sunday
select new DateTime(d)).Take(3);
foreach (var a in available)
Console.WriteLine(a.ToString());

In Operator in Linq

I tried to use the suggestion provided here for using In operator in linq but, i am not able to convert my requirement into LINQ statement.
Below is the SQL query which i need to convert to Linq
select *
from navigator_user_field_property
where user_id = 'albert'
and field_id in (
select field_id
from navigator_entity_field_master
where entity_id = 1
and use_type = 0)
order by field_id
I want this to be converted to a Efficient Linq.
Most of the answers deal with the predetermined list of string array which is not working in my case.
Thanks
Looks like a join to me:
var query = from navigator in db.NavigatorUserFieldProperties
where navigator.UserId == "albert"
join field in db.NavigatorEntityFieldMasters
.Where(f => f.EntityId == 1 && f.UseType == 0)
on navigator.FieldId equals field.FieldId
select navigator;
Note that this will return the same value multiple times if there are multiple fields with the same ID - but I suspect that's not the case.
You could do a more literal translation like this:
var query = from navigator in db.NavigatorUserFieldProperties
where navigator.UserId == "albert" &&
db.NavigatorEntityFieldMasters
.Where(f => f.EntityId == 1 && f.UseType == 0)
.select(f => f.FieldId)
.Contains(navigator.FieldId)
select navigator;
... and that may end up translating to the same SQL... but I'd personally go with the join.
Here is an efficient and readable LINQ query:
var fields =
from field in db.navigator_entity_field_masters
where field.entity_id == 1 && field.user_type == 0
select field;
var properties =
from property in db.navigator_user_field_properties
where property.user_id == "albert"
where fields.Contains(property.field)
select property;
Look mama!! Without joins ;-)

BETWEEN EQUIVALENT in LINQ

I am looking LINQ equivalent for the following query
Select * from ct_rate
WHERE
'2010-10-01 00:00:00'
BETWEEN start_date and end_date;
ANY IDEA?
You need to use two comparison operations:
DateTime date = new DateTime(2010, 10, 1);
var results = from rate in ct_rates
where rate.StartDate <= date && rate.EndDate >= date
select rate;
Just use ordinary comparison operators
var result = ct_rates
.Where(x => x.start_date <= myDate && x => x.endDate >= myDate);
In our case, Robert's answer was close to what I was looking for. In our data model, our 'end' or 'through' date columns are nullable.
Something like the following was needed:
Category.Where(
w => w.ValidFrom <= now &&
(w.ValidThru == null ? DateTime.MaxValue : w.ValidThru) >= now).Select(s => s).Dump();
I found this works when wanting only to compare the data part.
var results = from rate in ct_rates
where rate.StartDate.Date <= date && rate.EndDate.Date >= date
select rate;
something like this?
var result = from context.ct_rate.Where(d => d.start_date >= "2010-10-01 00:00:00" && d.end_date <= "2010-10-01 00:00:00")

LINQ - Return Value From Field With A Max Value if No Rows Found

I have a table like this...
ID Description LowThreshold HighThreshold
1 BAD 0.0 .69
2 MEETS .70 .89
3 GOOD .90 2
The object here is to write a LINQ query that will select the right Description based on a given decimal. For instance .75 is between .70 and .89, so it would return “MEETS”. BUT, the kicker is, if the Number is higher than all the ranges, automatically return the Description for the record with the highest HighThreshold. So, if I pass in 5, I should get “GOOD” returned.
I have this so far, but it errors out with scores higher than 2, obviously:
private string GetEvaluationDescription (decimal score)
{
string evaluationText = myContext.PerformanceRanges.Where
(e =>
e.LowThreshold <= score
&&
e.HighThreshold >= score
)
.Select(eval => eval.Description).First().ToString();
}
I'd like to accomplish this with just this one query, but my imagination isn't getting me there. I attempted what I found in this post but couldn't get it to work
What about this:
var range = myContext.PerformanceRanges
.SingleOrDefault(e=>e.LowThreshold <= score && e.HighThreshold >= score)??
PerformanceRanges.Single(
e=>e.HighThreshold == PerformanceRanges
.Max(p=> p.HighThreshold)
);
string evaluationText = range.Description;
The range query will select the element that matches with the Thereshold ranges, and if the value is greater (the first query will return null), it will select the greatest range.
What about this:
string evaluationText = myContext.PerformanceRanges.Where
(e =>
(e.LowThreshold <= score
&&
e.HighThreshold >= score) ||
(e.HighThreshold ==
myContext.PerformanceRanges.Max (
x => x.HighThreshold)
&& score > e.HighThreshold )
)
.Select(eval => eval.Description).First().ToString();

Resources