I have 2 models: Task and TaskLimit. Task belongs to TaskLimit. But task_limit_id might be Nil, so I need to use LEFT JOIN to preload existing TaskLimit's.
The only way I can do join is this:
query = query.join(:task_limit).preload(:task_limit)
But It doesn't select Tasks without TaskLimit.
There is a method in source code of Query class, where I can specify String for my JOIN:
def self.join(join_string : String)
self.new.join(join_string)
end
But When I try to use it:
query.join("LEFT JOIN task_limits ON tasks.task_limit_id = task_limits.id").preload(:task_limit)
I get an error that the method doesn't exist:
in tmp/1537794230627_console.cr:2: no overload matches 'Crecto::Repo::Query#join' with type String
Overloads are:
- Crecto::Repo::Query#join(join_associations : Array(Symbol))
- Crecto::Repo::Query#join(join_association : Symbol)
query = query.join("LEFT JOIN task_limits ON tasks.task_limit_id = task_limits.id").preload(:task_limit).where(id: [43, 46])
How can I preload association with LEFT JOIN?
Related
The challenge is to update a table by scanning that same table for information. In this case, I want to find how many entries I received in an Upload dataset that have the same key (effectively duplicate instructions).
I tried the obvious code:
UPDATE Base AS TAR
INNER JOIN (select cdKey, count(*) as ct FROM Base GROUP BY cdKey) AS CHK
ON TAR.cdKey = CHK.cdKey
SET ctReferences = CHK.ct
This resulted in a non-updateable complaint. Some workarounds talked about adding DISTINCTROW, but that made no difference.
I tried creating a view (query in Ms/Access parlance); same failure.
Then I projected the set (SELECT cdKey, count(*) INTO TEMP FROM Base GROUP BY cdKey), and substituted TEMP for the INNER JOIN which worked.
Conclusion: reflexive updates are also non-updateable.
An initial thought was to embed a sub-select in the update, for example:
UPDATE Base TAR SET TAR.ctReferences = (select count(*) from Base CHK where CHK.cd = TAR.cd)
This also failed.
As this is part of a job I am calling, this SQL (like the other statements) are all strings executed by CurrentDb.Execute statements. I thought maybe I could make this a DLookup, I found that as cd is a string, I had a gaggle of double- and triple-quoted elements that was too messy to read (and maintain).
Best solution was to write a function so I could avoid having to do any sort of string manipulation. Hence, in a module there's a function:
Public Function PassHelperCtOccurs(ByRef cdX As String) As Long
PassHelperCtOccurs = DLookup("count(*)", "Base", "cd='" & cdX & "'")
End Function
And the call is:
CurrentDb().Execute ("UPDATE Base SET ctOccursCd =PassHelperCtOccurs(cd)")
I have 3 models Product,Photo,ProductLikeDislike. I am left joining all the three. For that I wrote this query:
x=Product.objects.values_list('name','photo','productlikedislike')
Through this I am getting correct left join I printed and checked like this:
Note: olx is the name of my Django app.
print(x.query)
SELECT "olx_product"."name", "olx_photo"."id", "olx_productlikedislike"."id"
FROM "olx_product" LEFT OUTER JOIN "olx_photo" ON ("olx_product"."id" =
"olx_photo"."reference_id_id") LEFT OUTER JOIN "olx_productlikedislike" ON
("olx_product"."id" = "olx_productlikedislike"."product_id_id") ORDER BY
"olx_product"."created" DESC
Now I want to add extra and condition along with ON statement like this:
ON ("olx_product"."id" =
"olx_productlikedislike"."product_id_id"
and "olx_productlikedislike"."product_liked_by_id"=2)
So for this somebody suggested me that use Django's FilteredRelation. I used but it is not adding extra and condition along with ON
I used FilteredRelation like this:
x=Product.objects.annotate(
productlikedislike_product_liked_by_id=FilteredRelation('productlikedislike',
condition=Q(productlikedislike__product_liked_by_id=2))).values_list('name',
'photo','productlikedislike')
but getting the same sql query no extra and condition. I am using Django 2.1.5
I got the answer by adding 'productlikedislike_product_liked_by_id' to the values_list(...) that I am using along with FilteredRelation.
So the final query is:
x=Product.objects.filter(Q(photo__cover_photo_flag="yes")|Q(photo__file=None)).annotate(
productlikedislike_product_liked_by_id=FilteredRelation('productlikedislike',condition=Q(pr
oductlikedislike__product_liked_by_id=2))).values_list('name','photo','productlikedislike_p
roduct_liked_by_id')
I printed it it is giving me this resul which I wanted to get:
SELECT "olx_product"."name", "olx_photo"."id",
productlikedislike_product_liked_by_id."id" FROM "olx_product" LEFT OUTER JOIN
"olx_photo" ON ("olx_product"."id" = "olx_photo"."reference_id_id") LEFT OUTER JOIN
"olx_productlikedislike" productlikedislike_product_liked_by_id ON ("olx_product"."id" =
productlikedislike_product_liked_by_id."product_id_id" AND
(productlikedislike_product_liked_by_id."product_liked_by_id_id" = 2)) WHERE
("olx_photo"."cover_photo_flag" = yes OR "olx_photo"."file" IS NULL) ORDER BY
"olx_product"."created" DESC
I am using Java DB (Java DB is Oracle's supported version of Apache Derby and contains the same binaries as Apache Derby. source: http://www.oracle.com/technetwork/java/javadb/overview/faqs-jsp-156714.html#1q2).
I am trying to update a column in one table, however I need to join that table with 2 other tables within the same database to get accurate results (not my design, nor my choice).
Below are my three tables, ADSID is a key linking Vehicles and Customers and ADDRESS and ZIP in Salesresp are used to link it to Customers. (Other fields left out for the sake of brevity.)
Salesresp(address, zip, prevsale)
Customers(adsid, address, zipcode)
Vehicles(adsid, selldate)
The goal is to find customers in the SalesResp table that have previously purchased a vehicle before the given date. They are identified by address and adsid in Customers and Vechiles respectively.
I have seen updates to a column with a single join and in fact asked a question about one of my own update/joins here (UPDATE with INNER JOIN). But now I need to take it that one step further and use both tables to get all the information.
I can get a multi-JOIN SELECT statement to work:
SELECT * FROM salesresp
INNER JOIN customers ON (SALESRESP.ZIP = customers.ZIPCODE) AND
(SALESRESP.ADDRESS = customers.ADDRESS)
INNER JOIN vehicles ON (Vehicles.ADSId =Customers.ADSId )
WHERE (VEHICLES.SELLDATE<'2013-09-24');
However I cannot get a multi-JOIN UPDATE statement to work.
I have attempted to try the update like this:
UPDATE salesresp SET PREVSALE = (SELECT SALESRESP.address FROM SALESRESP
WHERE SALESRESP.address IN (SELECT customers.address FROM customers
WHERE customers.adsid IN (SELECT vehicles.adsid FROM vehicles
WHERE vehicles.SELLDATE < '2013-09-24')));
And I am given this error: "Error code 30000, SQL state 21000: Scalar subquery is only allowed to return a single row".
But if I change that first "=" to a "IN" it gives me a syntax error for having encountered "IN" (Error code 30000, SQL state 42X01).
I also attempted to do more blatant inner joins, but upon attempting to execute this code I got the the same error as above: "Error code 30000, SQL state 42X01" with it complaining about my use of the "FROM" keyword.
update salesresp set prevsale = vehicles.selldate
from salesresp sr
inner join vehicles v
on sr.prevsale = v.selldate
inner join customers c
on v.adsid = c.adsid
where v.selldate < '2013-09-24';
And in a different configuration:
update salesresp
inner join customer on salesresp.address = customer.address
inner join vehicles on customer.adsid = vehicles.ADSID
set salesresp.SELLDATE = vehicles.selldate where vehicles.selldate < '2013-09-24';
Where it finds the "INNER" distasteful: Error code 30000, SQL state 42X01: Syntax error: Encountered "inner" at line 3, column 1.
What do I need to do to get this multi-join update query to work? Or is it simply not possible with this database?
Any advice is appreciated.
If I were you I would:
1) Turn off autocommit (if you haven't already)
2) Craft a select/join which returns a set of columns that identifies the record you want to update E.g. select c1, c2, ... from A join B join C... WHERE ...
3) Issue the update. E.g. update salesrep SET CX = cx where C1 = c1 AND C2 = c2 AND...
(Having an index on C1, C2, ... will boost performance)
4) Commit.
That way you don't have worry about mixing the update and the join, and doing it within a txn ensures that nothing can change the result of the join before your update goes through.
I have two tables I would like to call, but I am not sure if it is possible to combine them into one query or I have to some how call 2 different queries.
Basically I have 2 tables:
1) item_table: name/id etc. + category ID
2) category_table: categoryID, categoryName, categoryParentID.
The parent categories are also inside the same table with their own name.
I would like to call on my details from item_table, as well as getting the name of the category, as well as the NAME of the parent category.
I know how to get the item_table data, plus the categoryName through an INNER JOIN. But can I use the same query to get the categoryParent's name?
If not, what would be the mist efficient way to do it? The rest of the code is in C++.
SELECT item_table.item_name, c1.name AS CatName, c2.name AS ParentCatName
FROM item_table join category_table c1 on item_table.categoryID=c1.categoryID
LEFT OUTER JOIN category_table c2 ON c2.categoryID = c1.categoryParentID
SQL Fiddle: here
I've used answer from this question:
Django: making raw SQL query, passing multiple/repeated params?
but have some problems.
I have params:
params = {'film_id_string': 'core_film.parent_id', 'tags_params': 'comedy', 'order_by': 'core_film.title', 'content_type': '18', 'language_code': 'en'}
for SQL query:
query = 'SELECT DISTINCT "core_object".*, "core_film".* FROM "core_film" INNER JOIN "core_object" ON ("core_film"."parent_id" = "core_object"."id") LEFT OUTER JOIN "core_objectlocalized" ON ("core_objectlocalized"."parent_id" = %(film_id_string)s) LEFT OUTER JOIN "tagging_taggeditem" ON ("tagging_taggeditem"."object_id" = "core_objectlocalized"."id") LEFT OUTER JOIN "tagging_tag" ON ("tagging_tag"."id" = "tagging_taggeditem"."tag_id") WHERE "tagging_tag"."name" IN (%(tags_params)s) AND "core_objectlocalized"."LANG"=%(language_code)s AND content_type_id=%(content_type)s ORDER BY %(order_by)s'
When I tried to use RawQuerySet
films = Film.objects.raw(query, params)
I get:
SELECT DISTINCT "core_object".*, "core_film".*
FROM "core_film"
INNER JOIN "core_object" ON ("core_film"."parent_id" = "core_object"."id")
LEFT OUTER JOIN "core_objectlocalized" ON ("core_objectlocalized"."parent_id" = E\'core_film.parent_id\')
LEFT OUTER JOIN "tagging_taggeditem" ON ("tagging_taggeditem"."object_id" = "core_objectlocalized"."id")
LEFT OUTER JOIN "tagging_tag" ON ("tagging_tag"."id" = "tagging_taggeditem"."tag_id")
WHERE "tagging_tag"."name" IN (E\'comedy\')
AND "core_objectlocalized"."LANG"=E\'en\'
AND content_type_id=E\'18\'
ORDER BY E\'core_film.title\'
Problem is, that every place with 'E\' generate error similar to this:
DatabaseError: invalid input syntax for integer: "core_film.parent_id"
LINE 1: ...calized" ON ("core_objectlocalized"."parent_id" = E'core_fil...
How can I fix this?
Django version 1.2.3.
edit
I can't remove quotes, because I work with string:
result = self.function(result, tag, "core_film.parent_id")
def function(self, objects, tags, film_id_string):
My params for RawQuerySet look like this:
params = {'film_id_string': film_id_string}
When I try to parse this I get:
LEFT OUTER JOIN "core_objectlocalized" ON ("core_objectlocalized"."parent_id" = E\'core_film.parent_id\')
and then I have problems with
DatabaseError: invalid input syntax for integer: "core_film.parent_id"
LINE 1: ...calized" ON ("core_objectlocalized"."parent_id" = E'core_fil...
but, when I use string formatting
LEFT OUTER JOIN "core_objectlocalized" ON ("core_objectlocalized"."parent_id" = %s)' % film_id_string
it works:
LEFT OUTER JOIN "core_objectlocalized" ON ("core_objectlocalized"."parent_id" = core_film.parent_id)
I want to ommit posibility of SQL injection, so basing on Django docs I don't want to pass params with string formatting.
What can I else do?
Django prevents SQL interjection by escaping parameters. This is an SQL statement, therefore the fact that it does not work is a good thing - Django is doing it's job. Unless the users of the system will be setting the value for "film_id_string" what you did to get it to work should be ok. If not, then you would have to still used the "...%s)' % film_id_string..." method but create your own custom filter to validate that it is one of the correct allowed values.