SQL ALchemy: Constuct or_ with dynamic list of conditionals - sql

I am building a sports web app. I want a query that takes a list of players, and checks whether their game for that week has started yet.
The following query works for me, but I need to explicitly type out each player in the list. If I want my list to be dynamically sized, this will not work. Is there anything I can construct this query in a smarter way?
SQL Alchemy query:
db.session.query(Game.start).filter(Game.week_id == self.week_id).filter(or_(Game.home_team == self.players[1].team, Game.away_team == self.players[1].team, Game.home_team == self.players[0].team, Game.away_team == self.players[0].team)).all()
The query then looks like this:
SELECT game.start AS game_start
FROM game
WHERE game.week_id = %(week_id_1)s
AND (%(param_1)s = game.home_team_name OR
%(param_2)s = game.away_team_name OR
%(param_3)s = game.home_team_name OR
%(param_4)s = game.away_team_name)

Got it using in_
db.session.query(Game).filter(Game.week_id == self.week_id, Game.start==True).filter(or_(Game.home_team_name.in_([p.team_name for p in self.players]), Game.away_team_name.in_([p.team_name for p in self.players]))).all()

Related

peewee: building a query programmatically

Is it possible (how?) to build a select query programmatically in peewee? The point is to add .where() clauses as needed.
query = SomeThing.select()
if foo:
query = query.where(SomeThing.value == 'foo')
else:
query = query.where(...)

Advanced search on multiple associations in Rails

Im trying to build advanced search finder for my Candidate model.
Lets imagine it has couple fields + multiple associations like has_many: languages & has_many: skills. Now I'm building query like this:
query = Candidate.select("*")
if position_name
query = query.where('position_name LIKE ? OR position_name IS NULL',"%#{position_name}%")
end
if salary
query = query.where('salary <= ? OR salary IS NULL',salary)
end
and so on...
Now I want to add more advanced conditions like to find users who only have such skills like PHP and Java (so return only those users who have both skills)
This works but only when I insert OR
query = query.joins(:skills)
query = query.where('`skills`.`name` = ? OR `skills`.`name` = ?',"Java","PHP")
Additionally I'd like the same also for languages (plus, language have language.name & language.level)
Can someone points me in which direction to look? And also how to build such condition where I can multiple skills or multiple languages?
Have a look at the various search gems like Ransack, Metawhere or Searchlogic
http://rubygems.org/gems/ransack
https://github.com/railsdog/searchlogic
Both Ransack and Searchlogic allow searching on associated models and you can use scopes to restrict the search parameters.
Example Search params for Searchlogic.
[search][admitted_gte]
[search][admitted_lte]
[search][aetiology_like_any][] VIRUS
[search][at_risk_gte]
[search][at_risk_lte]
[search][died_gte]
[search][died_lte]
[search][gezi_reference_like]
[search][id]
[search][incidents_location_encrypted_postcode_like]
[search][lab_confirmed_gte]
[search][lab_confirmed_lte]
[search][onset_first_after]
[search][onset_first_before]
[search][onset_last_after]
[search][onset_last_before]
[search][outbreak_type_equals_any][] FOODBORNE
[search][point_source_date_after]
[search][point_source_date_before]
[search][total_affected_gte]
[search][total_affected_lte]
[search][user_reference_like]
[search][year_equals_any][] 2010
search[order] descend_by_id
Outbreak_Controller.rb Index action returns the results of the Search query. From 17 Search params only a single searchlogic call is required #search = Outbreak.search(params[:search]). The params are whitelisted against a list of allowed search params - code not shown.
def index
#set the default index order to be descending Outbreak id
if !params[:search][:order]
params[:search][:order] = "descend_by_id"
end
if params[:search][:bacterial_agents_bacterium_name_like_any] != nil && !params[:search][:bacterial_agents_bacterium_name_like_any].empty?
params[:search][:bacterial_agents_category_like] = "CAUSATIVE"
end
if params[:search][:viral_agents_virus_name_like_any] != nil && !params[:search][:viral_agents_virus_name_like_any].empty?
params[:search][:viral_agents_category_like] = "CAUSATIVE"
end
if params[:search][:protozoal_agents_protozoa_name_like_any] != nil && !params[:search][:protozoal_agents_protozoa_name_like_any].empty?
params[:search][:protozoal_agents_category_like] = "CAUSATIVE"
end
if params[:search][:toxic_agents_toxin_name_like_any] != nil && !params[:search][:toxic_agents_toxin_name_like_any].empty?
params[:search][:toxic_agents_category_like] = "CAUSATIVE"
end
#Outbreak.search takes all of the given params and runs it against the Outbreak model and it's associated models
#search = Outbreak.search(params[:search])
end

checking if all the items in list occur in another list using linq

I am stuck with a problem here. I am trying to compare items in a list to another list with much more items using linq.
For example:
list 1: 10,15,20
list 2: 10,13,14,15,20,30,45,54,67,87
I should get TRUE if all the items in list 1 occur in list 2. So the example above should return TRUE
Like you can see I can't use sequenceEquals
Any ideas?
EDIT:
list2 is actually not a list it is a column in sql thas has following values:
<id>673</id><id>698</id><id>735</id><id>1118</id><id>1120</id><id>25353</id>.
in linq I did the following queries thanks to Jon Skeets help:
var query = from e in db
where e.taxonomy_parent_id == 722
select e.taxonomy_item_id;
query is IQueryable of longs at this moment
var query2 = from e in db
where query.Contains(e.taxonomy_item_id)
where !lsTaxIDstring.Except(e.taxonomy_ids.Replace("<id>", "")
.Replace("</id>", "")
.Split(',').ToList())
.Any()
select e.taxonomy_item_id;
But now I am getting the error Local sequence cannot be used in LINQ to SQL implementation of query operators except the Contains() operator.
How about:
if (!list1.Except(list2).Any())
That's about the simplest approach I can think of. You could explicitly create sets etc if you want:
HashSet<int> set2 = new HashSet<int>(list2);
if (!list1.Any(x => set2.Contains(x)))
but I'd expect that to pretty much be the implementation of Except anyway.
This should be what you want:
!list1.Except(list2).Any()
var result = list1.All(i => list2.Any(i2 => i2 == i));

Linq to sql constantly returns null

I have the following SQL query:
SELECT DISTINCT
Participant.BackgroundTrainingID,
Location.TrainingSite
FROM Registration, ProgramLocation, Participant, Program, Location
WHERE ProgramLocation.LocationID = Location.LocationID
AND ProgramLocation.ProgramID=Registration.ProgramID
AND Registration.ParticipantID=Participant.ParticipantId
I wrote the following LINQ to SQL to match the query above:
var trainingsiteinfo = (from c in db.ProgramLocations
from n in db.Registrations
from l in db.Participants
from h in db.Locations
where c.LocationID == h.LocationID
&& c.ProgramID == n.ProgramID
&& n.ParticipantID == l.ParticipantId
select new {
h.TrainingSite,
l.BackgroundTrainingID }).Distinct();
The SQL query works fine but LINQ constantly returns null.
I use Linqer http://www.sqltolinq.com/ when i get out of ideas :-) Aswell it speeds up conversion jobs.
Make sure your db context isn't going out of scope before you have bound your results. You can test this by adding .ToList() after your .Distinct() to force eager loading of the results.
Your linq code has an unclosed } bracket in the select statement

Having problems converting conditional where clause in LINQ back over to SQL

I've got myself in a bit of a pickle!
I've done a snazzy LINQ statement that does the job in my web app, but now I'd like to use this in a stored procedure:
var r = (from p in getautocompleteweightsproducts.tblWeights
where p.MemberId == memberid &&
p.LocationId == locationid
select p);
if (level != "0")
r = r.Where(p => p.MaterialLevel == level);
if (column == "UnitUserField1")
r = r.Where(p => p.UnitUserField1 == acitem);
if (column == "UnitUserField2")
r = r.Where(p => p.UnitUserField2 == acitem);
return r.OrderBy(p => p.LevelNo).ToList();
However, I can't for the life of me get the conditional where clause to work!!
If someone can point me in the right direction, I'd be most grateful.
Kind regards
Maybe something like this?
SELECT *
FROM dbo.weights
WHERE member_id = #memberid
AND location_id = #locationid
AND material_level = CASE WHEN #level = '0' THEN material_level
ELSE #level END
AND #acitem = CASE #column WHEN 'UnitUserField1' THEN unit_user_field_1
WHEN 'UnitUserField2' THEN unit_user_field_2
ELSE #acitem END
ORDER BY level_no
Have you tried LinqPAD, I'm pretty sure last time I played with that you could enter "LINQ to SQL" code and see the resulting SQL that produced. Failing that, place a SQL trace/profiler on your code running the LinqTOSQL and find the query being executed in the trace.
LukeH's answer will give you the correct rows, but there is something lost when you try to replace a query-generating-machine with a single query. There are parts of that query that are opaque to the optimizer.
If you need the original queries as-would-have-been-generated-by-linq, there are two options.
Generate every possible query and control which one runs by IF ELSE.
Use Dynamic sql to construct each query (although this trades away many of the benefits of using a stored procedure).
If you do decide to use dynamic sql, you should be aware of the curse and blessings of it.