find_by_sql fails with exception: wrong number of parameters - sql

In the following code find_by_sql fails with exception: wrong number of parameters (0 for 1).
Any idea what's going on?
def filter_new_unfollowers(unfollower_ids)
relationships = TwitterRelationship.find_by_sql["SELECT * FROM twitter_relationships
INNER JOIN twitter_identities ON (twitter_identities.twitter_id=twitter_relationships.source_twitter_id)
INNER JOIN member_twitter_identities ON (member_twitter_identities.twitter_identity_id = twitter_identities.id)
WHERE member_twitter_identities.member_id IN (?)", unfollower_ids]
end

The way you wrote it, you are trying to execute find_by_sql with no arguments, and then call the [] operator on the result (but it failed before you got that far).
You need a space before the "[". To be even more clear, I would put parentheses around the array argument "...find_by_sql([...])".

Try adding brackets:
relationships = TwitterRelationship.find_by_sql(["SELECT * FROM twitter_relationships
INNER JOIN twitter_identities ON (twitter_identities.twitter_id=twitter_relationships.source_twitter_id)
INNER JOIN member_twitter_identities ON (member_twitter_identities.twitter_identity_id = twitter_identities.id)
WHERE member_twitter_identities.member_id IN (?)", unfollower_ids])

Related

CodeIgniter query from sql

How can I transform this sql to codeigniter query? I have screenshot of an EER diagram to help you understand better. So there are three tables to join. I guess, one is "pjesma", then "izvodjac", and "izvodi_pjesmu". This sql works when I run it and gives me results I want. I am also using pagination so I need limit and offset somehow included.
SELECT pjesma_id, naslov, naziv
FROM pjesma p, izvodjac i, izvodi_pjesmu ip
WHERE p.pjesma_id = ip.pjesma_pjesma_id
AND i.izvodjac_id = ip.izvodjac_izvodjac_id
in model:
public function paginacija_pjesme($limit, $offset) {
$this->db->select('pjesma_id', 'naslov', 'naziv');
$this->db->from('pjesma p');
$this->db->join('izvodi_pjesmu ip', 'p.pjesma_id=ip.pjesma_pjesma_id');
$this->db->join('izvodjac i', 'i.izvodjac_id=ip.izvodjac_izvodjac_id');
$this->db->limit($limit, $offset);
$query = $this->db->get();
return $query->result();
}
EDIT:
So in select I used wrong syntax, this line:
$this->db->select('pjesma_id', 'naslov', 'naziv');
should be like this:
$this->db->select('pjesma_id, naslov, naziv');
A few things, as you are dealing with objects within the query builder class, you can method-chain and make things a little less cluttered.
You are maybe getting an ambiguous column error, joining and not prefixing your select. Hard to tell without the error being posted you are facing.
Always best to (just in case) set defaults to your method arguments as well, in case you pass a blank variable (or don't need to for whatever reason).
When you are using multiple tables in the FROM statement you are actually doing a CROSS JOIN, and your new code is giving INNER JOIN,trying the join syntax direct to your SQL server might help as you are not actually doing the same thing between your first written query, and the codeigniter one..
Try the below with LEFT join just to see... If there are NULL joins using INNER they will be omitted
public function paginacija_pjesme($limit = 10, $offset = 0) {
$query = $this->db->select('p.pjesma_id, p.naslov, i.naziv')
->from('pjesma p')
->join('izvodi_pjesmu ip', 'p.pjesma_id = ip.pjesma_pjesma_id', 'left')
->join('izvodjac i', 'i.izvodjac_id = ip.izvodjac_izvodjac_id', 'left')
->limit($limit, $offset)
->get();
return $query->result();
}
Are you getting any errors? what do you see if you print_r($query->result()) ?
try also spitting out $this->db->last_query() - this will output the SQL codeigniter has build. Then running this directly to your database, and see the results from there. You might even see the issue without needing to run it.
This is an example of what your current codeigniter code is generating (as you can see, different to your original query):
SELECT pjesma_id, naslov, naziv
FROM pjesma p
INNER JOIN izvodi_pjesmu ip ON p.pjesma_id = ip.pjesma_pjesma_id
INNER JOIN izvodjac i ON i.izvodjac_id = ip.izvodjac_izvodjac_id
# LIMIT 10,0

Concatenate variable and string with Arel on join

I try to join two tables using Arel to generate some SQL like this:
[...]
INNER JOIN "nodes" ON "nodes"."id" LIKE "jobs"."ancestry" || '%'
[...]
to match any job that starts with one of the node IDs. When I run the plain SQL this works, now I try to build this with Arel:
node = Node.arel_table
job = Job.arel_table
node.join(job).on(node[:id].matches("_______%"))
Now I can't find anything how to get the right string for matches, even if I try:
"\"nodes\".\"ancesty\" || %"
the full string will be escaped. Is there any way to pass raw SQL the the Arel matches method that will not be escaped or any other way to get this working with Arel?
It seems Arel::Nodes::SqlLiteral does the job:
node = Node.arel_table
job = Job.arel_table
lit = Arel::Nodes::SqlLiteral.new("_______%")
node.join(job).on(node[:id].matches(lit))

Using 'LIKE' in SQL Statement doesn't seem to work

I seem to be able to do a simple query that uses the equal sign, but am unable to find any results when I use the 'LIKE' function. Am I missing something here?
SELECT ISARPapers.*, AuthorList.FirstName, AuthorList.LastName
FROM AuthorList INNER JOIN (ISARPapers INNER JOIN PaperAuthor
ON ISARPapers.PaperID = PaperAuthor.PaperID)
ON AuthorList.AuthorID = PaperAuthor.AuthorID
WHERE ISARPapers.PaperTitle LIKE '%Mianzi%'
be carrefuly with capital letters
... WHERE ISARPapers.PaperTitle LIKE '%Mianzi%'
maybe Mianzi does not exists but mianzi does.
if you do not care about capitals, try:
... WHERE lower(ISARPapers.PaperTitle) LIKE '%mianzi%'

using Date.today in joins part of named scope

For some reason, the Date class is recognized when I use in the where
scope :with_active_subthing, joins("left outer join thing_subthing on thing_subthing.patient_id = thing.id").where("thing_subthing.start_date <= ? AND ( thing_subthing.end_date > ? OR thing_subthing.end_date IS NULL ) ", Date.today, Date.today)
but doesn't recognize it when I use it in joins
scope :with_active_subthing, joins("left outer join thing_subthing on thing_subthing.patient_id = thing.id AND (thing_subthing.start_date <= ? AND ( thing_subthing.end_date > ? OR thing_subthing.end_date IS NULL )) ", Date.today, Date.today)
I get:
RuntimeError: unknown class: Date
If you look at the underlying code that builds the join portion, you can see that it is looking for specific object types, and Date is not one of them. The error is sort of confusing, but what it's saying is that a Date cannot be used as an argument for joins. It's not really clear from your question why you want to do this, but you should absolutely be using both joins and where together as you've done in your first example.
Here's the code that is causing the issue because it's falling through to the "raise" line:
def build_joins(manager, joins)
buckets = joins.group_by do |join|
case join
when String
'string_join'
when Hash, Symbol, Array
'association_join'
when ActiveRecord::Associations::JoinDependency::JoinAssociation
'stashed_join'
when Arel::Nodes::Join
'join_node'
else
raise 'unknown class: %s' % join.class.name
end
end

SQL Update on joined tables with calculated fields

First of all, I know there are already questions and answers about it, this thread being the one that is closest to what I need:
SQL Update to the SUM of its joined values
However, I get a syntax error (operator missing) that seems to occur close to the FROM clause. However I can't see it. Does it not like the FROM itself ? I am not used to using FROM in an update statement but it seems like it's valid from the QA I just linked :|
Any idea why there would be a syntax error there ?
I am using Access 2007 SP3.
Edit:
Wow, I forgot to post the query...
UPDATE r
SET
r.tempsmoy_requete_min = tmm.moy_mob_requete
FROM
rapports AS r INNER JOIN
(SELECT
id_fichier,
Round(Sum(temps_requete_min)/3,0) As moy_mob_requete,
Round(Sum(temps_analyse_min)/3,0) As moy_mob_analyse,
Round(Sum(temps_maj_min)/3,0) As moy_mob_maj,
Round(Sum(temps_rap_min)/3,0) As moy_mob_rap,
Round(Sum(temps_ddc_min)/3,0) As moy_mob_ddc
FROM maintenances
WHERE
periode In (10,9,8) And
annee=2011
GROUP BY id_fichier) AS tmm ON rapports.id_rapport = tmm.id_fichier
WHERE
1=0
The WHERE 1=0 part is because I want to test further the subquery before running it.
Edit: This is some simpler query I am trying. I get a different error this time. It now tells me that tempsmoy_requete_min (and probably all other left operands) are not part of an aggregate function... which is the point of my query. Any idea ?
UPDATE
rapports INNER JOIN maintenances ON rapports.id_rapport = maintenances.id_fichier
SET
rapports.tempsmoy_requete_min = Round(Sum(temps_requete_min)/3,0),
rapports.tempsmoy_analyse_min = Round(Sum(temps_analyse_min)/3,0),
rapports.tempsmoy_maj_min = Round(Sum(temps_maj_min)/3,0),
rapports.tempsmoy_rap_min = Round(Sum(temps_rap_min)/3,0),
rapports.tempsmoy_ddc_min = Round(Sum(temps_ddc_min)/3,0)
WHERE
maintenances.periode In (10,9,8) And
maintenances.annee=2011 AND
1=0
I tried adapting your first query sample, and was able to make your error go away. However then I encountered a different error ('Operation must use an updateable query').
It may be possible to overcome that error, too. However, I found it easier to use a domain function instead of a join to retrieve the replacement value.
UPDATE rapports
SET tempsmoy_requete_min = Round(DSum("temps_requete_min",
"maintenances",
"periode In (10,9,8) AND annee=2011 "
& "AND id_fichier='" & id_rapport
& "'")/3, 0);
If this suggestion works for tempsmoy_requete_min with your data, you will have to extend it to the other fields you want to replace. That won't be pretty. You could make it less ugly with a saved query which you then use as the "Domain" parameter for DSum() ... that could allow you to use a simpler "Criteria" parameter.
UPDATE r
should be
UPDATE rapports
You can't reliably use an alias in the update target.