doctrine2 addSelect subquery to return multiple rows - doctrine-orm

I have a subquery and need to return multiple rows, but I am getting this error:
SQLSTATE[21000]: Cardinality violation: 1242 Subquery returns more than 1 row
And Doctrine puts my subquery as scalar:
(SELECT m2_.id FROM movie_genres m2_ LEFT JOIN moviesgenres_movies m4_ ON m2_.id = m4_.moviesgenres_id LEFT JOIN movies m3_ ON m3_.id = m4_.movies_id WHERE m3_.id = m0_.id) AS sclr_7
I need multiple rows to be returned - is it possible?

Related

Queryset for a sql query

See Filtering unique values for the problem description, sample data and postgres query. I'd like to convert the SQL to a queryset. I feel like I'm close but not quite.
SELECT Column_A, Column_B, Column_C, 0 as RN
FROM TABLE
WHERE COLUMN_C is null and Column_B in (UserA, UserB, UserC)
UNION ALL
SELECT Column_A, Column_B, Column_C, RN
FROM (
SELECT A.*, ROW_NUMBER() over (partition by A.column_C Order by case A.column_B when 'UserA' then 0 else 1 end, U.Time_Created) rn
FROM Table A
INNER JOIN user U
on U.Column_B = A.Column_B
WHERE A.Column_C is not null and ColumnB in (userA, userB, UserC)) B
WHERE RN = 1
This is what I have so far:
qs1 = Table.objects.filter(Column_C__isnull=True).annotate(rn=Value(0))
qs2 = Table.objects.annotate(rn=Window(
expression=RowNumber(),
partition_by=[Column_C],
order_by=[Case(When(Column_B=UserA, then=0), default=1), 'Table_for_Column_B__time_created']
)).filter(Column_C__isnull=False, rn=1)
return qs2.union(qs1)
This doesn't quite work.
django.db.utils.NotSupportedError: Window is disallowed in the filter clause.
Next, I tried pulling the intermediate result in a subquery, to allow for filtering in the outer query, since I only really need rows with row number = 1.
qs1 = Table.objects.filter(Column_C__isnull=True).annotate(rn=Value(0))
qs2 = Table.objects.annotate(rn=Window(
expression=RowNumber(),
partition_by=[Column_C],
order_by=[Case(When(Column_B=UserA, then=0), default=1), 'Table_for_Column_B__time_created']
)).filter(pk=OuterRef('pk'))
qs3 = Table.objects.annotate(rn=Subquery(qs2.values('rn'))).filter(Column_C__isnull=False, rn=1)
return qs3.union(q1)
No exceptions this time, but this doesn't work. Every row in the table gets row_number=1 annotated. From the original example, the queryset returns all 7 rows instead of filtering to 5.
Is it possible to filter on window expressions?
What's the best practices to keep in mind when converting window queries to subqueries?
Is there a better way to structure the queryset?
You should be able to do this without a window expression, using a SubQuery
First create a queryset for the subquery that orders by the Column_B=UserA match and then time_created
from django.db.models import Case, When, Q, Subquery, OuterRef
tables_ordered = Table.objects.filter(
Column_C=OuterRef('Column_C')
).annotate(
user_match=Case(When(Column_B=UserA, then=0), default=1)
).order_by('user_match', 'time_created')
Then this subquery returns the first pk for the matched Column_C from the OuterRef, similar to selecting the first row from your window function
first_pk_for_each_column_c = Subquery(tables_ordered.values('pk')[:1])
Then use two Q objects to create an OR that selects the row if Column_C is NULL or the pk matches the first pk from the subquery
Table.objects.filter(
Q(Column_C__isnull=True) | Q(pk=first_pk_for_each_column_c)
)

Compare the rows of 2 tables in 2 different databases

I have 2 different databases. In both there is a table called fruit. Now I want to update the second database with respect to the first database. For this I compare each row by all column values (except the ID column) in the first database to each row in the second database and get those rows in which there is a difference. the query i am using is
SELECT A.* FROM db1.Fruit A
Left Outer Join Fruit B ON
(A.Ratings = B.Ratings AND A.Name = B.Name AND A.Color = B.Color)
where B.Ratings IS NULL OR B.Name IS NULL OR B.Color IS NULL
Table in the first databaseTable in the second database.
Now in the result it should show the the row with ID 3 where the name is Kiwi and the color is green. But it also shows the row with ID 4 with name Banana as the other columns is null and in my query I am writing that return the row if B.Ratings IS NULL or B.Color IS NULL.
So is there any other way to compare 1 row of table one to 1 row of table 2 by all columns (except ID column) and return those rows in which there is a mismatch in any of the column values?
I have been confused :)
Edited:
I getting back to my initial response
SELECT A.*
FROM db1.Fruit as A JOIN db2.Fruit as B ON
(A.Name = B.Name AND A.Color = B.Color )
WHERE A.Rating <> B.Rating
The LEFT OUTER JOIN would gives the rows with Nulls on the left side (and you will see the right part of it); which is not what you want to do (at least that's my current understanding).
This statement will give you: the information on the db1 which have the same Name and Color as in the db2 but the Rating is different (which I thought is what you want to get).
If you want to change the combination of columns you have to change the join.

Joining 2 results in Doctrine throws error

I am trying to JOIN 2 queries in DQL but I am getting an error which says,
[Semantical Error] line 0, col 114 near '(select u.email': Error: Class '(' is not defined.
I have gone through https://stackoverflow.com/questions/24600439/error-in-nested-subquery-in-dql-class-is-not-defined. But I could not figure out. Please help.
My Query is as follows:
$filterQuery = "SELECT tempResult1.email as email,tempResult1.name as name , tempResult1.id as user
FROM (select u.email as email,a.name as name , u.id as user
FROM
Application\Entity\Userhasrole uhr
INNER JOIN
Application\Entity\Oauthrole r with uhr.applicationrole = r.id
INNER JOIN
Application\Entity\Application a with r.application = a.id
INNER JOIN
Application\Entity\Oauthusers u
) tempResult1
LEFT JOIN
(SELECT uhr1.user as user FROM Application\Entity\Userhasrole uhr1 where
a.id = :applicationId
) tempResult2
with tempResult1.user = tempResult2.user";
$queryObject = $this->getEntityManager()
->createQuery($filterQuery);
$queryObject->setParameter('applicationId', $applicationId);
$result = $queryObject->getResult();
You mix 2 concepts of Doctrine2 :
using SQL
using DQL
If you want to achieve that you want, build tables selections, and not entities selections, you should use EntityManager::createNativeQuery() method and set an SQL query as parameter.
EntityManager::createQuery() is used only for DQL queries

some order by in doctrine query language

I have a query as below :
SELECT t.id, t.name, count(i.id) FROM Acme\TestBundle\Entity\Tags t
LEFT JOIN t.items i WITH i.status=1 AND (SELECT count(img.id) FROM Acme\TestBundle\Entity\ItemsImages img WHERE img.item=i.id) > 0
GROUP BY t.id
ORDER BY COUNT (i.id) DESC
This query works fine without ORDER BY clause. Whenever I add this clause it gives me error :
[Syntax Error] line 0, col 297: Error: Expected end of string, got '('
ORDER BY works with column names but with columns like count(i.id) is not working
To order by an aggregated value, you need to SELECT it first and then use it to ORDER BY:
SELECT
t.id,
t.name,
count(i.id) AS tags_count
FROM
Acme\TestBundle\Entity\Tags t
...
ORDER BY
tags_count DESC

Identifying Sybase tables, fields, keys, constraints

I'm trying to set up a Sybase query that will give me the following output:
Table KeyType KeyNumber Column
table1 PK 1 table1_id
table1 FK 2 table2_id
table1 FK 3 table3_id
table1 FK 4 table4_id
table1 Unique 5 table1_abc
table1 Unique 5 table1_def
In other words, I need the PK for each table, and every foreign key it has, as well as every unique key (not where a key has more than one element, such as the unique key above, this is identified by having the same KeyNumber).
I'm guessing I need to use sysobject, syscolumns, syskeys and sysconstraints but I can't seem to figure out how they interlink.
Thanks
Karl
This is a start:
SELECT
t.name,
CASE k.type
WHEN 1 THEN 'PK'
WHEN 2 THEN 'FK'
WHEN 3 THEN 'Common'
END,
c.name
FROM
sysobjects t INNER JOIN
syscolumns c ON c.id = t.id INNER JOIN
syskeys k ON k.id = t.id AND c.colid IN (k.key1, k.key2, k.key3, k.key4, k.key5, k.key6, k.key7, k.key8)
WHERE
t.type = 'U' AND k.type in (1,2)
It does not include the key ID, for that I guess you could somehow hash the non-null table ID and keyN columns to produce a unique ID for the key.
It also does not include unique indexes. For that you would want to UNION with something along the lines of:
SELECT
t.name,
'Unique',
c.name
FROM
sysobjects t INNER JOIN
syscolumns c ON c.id = t.id INNER JOIN
sysindexes i ON i.id = t.id
WHERE t.type = 'U'
Check out the Sybase manual page for sysindexes on how to filter it.