querydsl using parent query entitypath in subquery - subquery

I am trying to represent the following query in querydsl:
select a1.agreement_id, ad1.agreement_detail_id
from agreement a1
inner join agreement_details ad1 on a1.agreement_id=ad1.agreement_id
where ad1.transaction_id in (
select max(ad2.transaction_id)
from agreement_details ad2
inner join agreement a2 on ad2.agreement_id=a2.agreement_id
where
ad2.transaction_id<=1234
and a2.agreement_id=a1.agreement_id
and a2.entity_split_id=5678
)
order by a1.agreement_id asc
However, I'm having trouble getting querydsl to use a table from the parent query in the where clause of the subquery. For example, if I write code like the following:
QAgreement a1 = QAgreement.agreement;
QAgreementDetails ad1 = QAgreementDetails.agreementDetails;
QAgreement a2 = QAgreement.agreement;
QAgreementDetails ad2 = QAgreementDetails.agreementDetails;
HibernateQuery query = getHibernateQuery();
query.from(a1)
.innerJoin(a1.agreementDetailsesByAgreementId, ad1)
.fetch()
.where(ad1.transactionId.in(
new JPASubQuery().from(ad2)
.innerJoin(ad2.agreementByAgreementId, a2)
.where(ad2.transactionId.loe(maxTransactionId))
.where(a1.agreementId.eq(a2.agreementId))
.where(a2.entitySplitByEntitySplitId.entitySplitId.eq(entitySplitId))
.list(ad2.transactionId.max())))
.orderBy(a1.agreementId.asc());
and execute it, the resulting SQL looks like
select -- Some columns removed for brevity
agreement0_.agreement_id as agreemen1_0_0_,
agreementd1_.agreement_detail_id as agreemen1_11_1_
from
agreement agreement0_
inner join
agreement_details agreementd1_
on agreement0_.agreement_id=agreementd1_.agreement_id
where
agreementd1_.transaction_id in (
select
max(agreementd2_.transaction_id)
from
agreement_details agreementd2_
inner join
agreement agreement3_
on agreementd2_.agreement_id=agreement3_.agreement_id
where
agreementd2_.transaction_id<=1234
and agreement3_.agreement_id=agreement3_.agreement_id
and agreement3_.entity_split_id=5678
)
order by
agreement0_.agreement_id asc
You can see that the alias of the Agreement EntityPath a1 is not being used in the subquery and is being replaced by the alias of the Agreement EntityPath a2. Is there something else I have to do in querydsl to be able to produce this query?

The problem is that you don't use unique variables
QAgreement a1 = QAgreement.agreement;
QAgreementDetails ad1 = QAgreementDetails.agreementDetails;
QAgreement a2 = QAgreement.agreement;
QAgreementDetails ad2 = QAgreementDetails.agreementDetails;
In this case a1 and a2 as well as ad1 and ad2 refer to the same path.
The variable names in the Java code don't matter, you need to use them for example like this
QAgreement a1 = new QAgreement("a1");
QAgreementDetails ad1 = new QAgreementDetails("ad1");
QAgreement a2 = new QAgreement("a2");
QAgreementDetails ad2 = new QAgreementDetails("ad2");

Related

ATHENA/PRESTO complex query with multiple unnested tables

i have i would like to create a join over several tables.
table login : I would like to retrieve all the data from login
table logging : calculating the Nb_of_sessions for each db & for each a specific event type by user
table meeting : calculating the Nb_of_meetings for each db & for each user
table live : calculating the Nb_of_live for each db & for each user
I have those queries with the right results :
SELECT db.id,_id as userid,firstname,lastname
FROM "logins"."login",
UNNEST(dbs) AS a1 (db)
SELECT dbid,userid,count(distinct(sessionid)) as no_of_visits,
array_join(array_agg(value.from_url),',') as from_url
FROM "loggings"."logging"
where event='url_event'
group by db.id,userid;
SELECT dbid,userid AS userid,count(*) as nb_interviews,
array_join(array_agg(interviewer),',') as interviewer
FROM "meetings"."meeting"
group by dbid,userid;
SELECT dbid,r1.user._id AS userid,count(_id) as nb_chat
FROM "lives"."live",
UNNEST(users) AS r1 (user)
group by dbid,r1.user._id;
But when i begin to try put it all together, it seems i retrieve bad data (i have only on db retrieved) and it seems not efficient.
select a1.db.id,a._id as userid,a.firstname,a.lastname,count(rl._id) as nb_chat
FROM
"logins"."login" a,
"loggings"."logging" b,
"meetings"."meeting" c,
"lives"."live" d,
UNNEST(dbs) AS a1 (db),
UNNEST(users) AS r1 (user)
where a._id = b.userid AND a._id = c.userid AND a._id = r1.user._id
group by 1,2,3,4
Do you have an idea ?
Regards.
The easiest way is to work with with to structure the subquery and then reference them.
with parameter reference:
You can use WITH to flatten nested queries, or to simplify subqueries.
The WITH clause precedes the SELECT list in a query and defines one or
more subqueries for use within the SELECT query.
Each subquery defines a temporary table, similar to a view definition,
which you can reference in the FROM clause. The tables are used only
when the query runs.
Since you already have working sub queries, the following should work:
with logins as
(
SELECT db.id,_id as userid,firstname,lastname
FROM "logins"."login",
UNNEST(dbs) AS a1 (db)
)
,visits as
(
SELECT dbid,userid,count(distinct(sessionid)) as no_of_visits,
array_join(array_agg(value.from_url),',') as from_url
FROM "loggings"."logging"
where event='url_event'
group by db.id,userid
)
,meetings as
(
SELECT dbid,userid AS userid,count(*) as nb_interviews,
array_join(array_agg(interviewer),',') as interviewer
FROM "meetings"."meeting"
group by dbid,userid
)
,chats as
(
SELECT dbid,r1.user._id AS userid,count(_id) as nb_chat
FROM "lives"."live",
UNNEST(users) AS r1 (user)
group by dbid,r1.user._id
)
select *
from logins l
left join visits v
on l.dbid = v.dbid
and l.userid = v.userid
left join meetings m
on l.dbid = m.dbid
and l.userid = m.userid
left join chats c
on l.dbid = c.dbid
and l.userid = c.userid;

Invalid Column In SQL Query

select
university_cars_video_kroenke.dbo.car_customer.cus_first,
university_cars_video_kroenke.dbo.car_customer.cus_last,
(
select COUNT(university_cars_video_kroenke.dbo.car_customer.cus_id)
from university_cars_video_kroenke.dbo.car_purchases
where university_cars_video_kroenke.dbo.car_customer.cus_id = university_cars_video_kroenke.dbo.car_purchases.cus_id
)
from university_cars_video_kroenke.dbo.car_customer
(edited for clarity)
select
customer.cus_first,
customer.cus_last,
(select
COUNT(customer.cus_id)
from purchases
where customer.cus_id = purchases.cus_id )
from customer
My error message is
Msg 8120, Level 16, State 1, Line 4 Column
'university_cars_video_kroenke.dbo.car_customer.cus_first'
is invalid in the select list because it is not contained
in either an aggregate function or the GROUP BY clause
I just want a count of records the cus_id is the same in both tables.
I just want a count of records the cus_id is the same in both tables.
Something like the following should work.
SELECT
A.cus_id,
count(A.cus_id)
FROM
university_cars_video_kroenke.dbo.car_customer AS A,
university_cars_video_kroenke.dbo.car_purchases AS B
WHERE
A.cus_id = B.cus_id

How can I store the value of a subquery into a variable in Hana Studio?

I would like to know how can I store the value of subquery to use it in an operation after it recieve the value. For example:
Select IDTruck
, TruckPrice = (select "TruckPrice" from "Table1" where ("TruckID" = '123'))
, TruckUnit = (select "TruckUnit" from "Table2" )
, TruckPrice * TruckUnit as "PriceTotal"
from Table3
I just want to store the value and then use it in the operation so I don't have to do the select again.
I'm not sure why it should be necessary to store the values in variables for usage in your case. I think the calculation can be done also by joining just the data (assuming that table3 contains a reference to table1 and table2).
Your example above would also not work, because TruckPrice and TruckUnits are no atomar results.
So please try to refactor your statement to use joins.

How to get sub query columns in main query with WHERE EXISTS in PostgreSQL?

I am stuck with a query which takes more time in JOIN, I want to use WHERE EXISTS in place of JOIN since as performance wise EXISTS takes less time than it.
I have modified the query and it's executing as per expectation but I am not able to use sub query's columns in my main query
Here is my query
SELECT MAX(st.grade_level::integer) AS grades ,
scl.sid AS org_sourced_id
FROM schedules_53b055b75cd237fde3af904c1e726e12 sch
LEFT JOIN schools scl ON(sch.school_id=scl.school_id)
AND scl.batch_id=sch.batch_id
AND scl.client_id = sch.client_id
AND sch.run_id = scl.run_id
WHERE EXISTS
(SELECT t.term_id,t.abbreviation
FROM terms t
WHERE (sch.term = t.term_id)
AND t.batch_id=sch.batch_id
AND t.client_id = sch.client_id
AND t.run_id = sch.run_id)
AND EXISTS
(SELECT st.grade_level,
st.sid
FROM students st
WHERE (sch.student_id=st.sid)
AND st.batch_id= sch.batch_id
AND st.client_id = sch.client_id
AND st.run_id = sch.run_id)
GROUP BY scl.sid ,
sch.course_name ,
sch.course_number,
sch.school_id
And I am getting this error:
ERROR: missing FROM-clause entry for table "st"
SQL state: 42P01
Character: 29
I have only used one column here just for sample but I have to use more fields from sub query.
My main aim is that how can I achieve this with EXISTS or any alternate solution which is more optimal as performance wise
I am using pg module on Node.js since as back end I am using Node.js.
UPDATE
Query with JOIN
SELECT MAX(st.grade_level::integer) AS grades ,
scl.sid AS org_sourced_id
FROM schedules_53b055b75cd237fde3af904c1e726e12 sch
LEFT JOIN schools scl ON(sch.school_id=scl.school_id)
AND scl.batch_id=sch.batch_id
AND scl.client_id = sch.client_id
AND sch.run_id = scl.run_id
LEFT JOIN terms t ON (sch.term = t.term_id)
AND t.batch_id=sch.batch_id
AND t.client_id = sch.client_id
AND t.run_id = sch.run_id
LEFT JOIN students st ON (sch.student_id=st.sid)
AND st.batch_id= sch.batch_id
AND st.client_id = sch.client_id
AND st.run_id = sch.run_id
GROUP BY scl.sid ,
sch.course_name ,
sch.course_number,
sch.school_id

DocumentDB multiple filter query on array

Using the DocumentDB query playground, I am working on a filter type of query. I have a set of attributes in my data that are set up to allow the user to search by the specific attribute. Each attribute type becomes and OR statement if multiple items are selected from the name in the name/value collection. If attributes are selected that differ (i.e. color and size) this becomes an AND statement.
SELECT food.id,
food.description,
food.tags,
food.foodGroup
FROM food
JOIN tag1 IN food.tags
JOIN tag2 IN food.tags
WHERE (tag1.name = "snacks" OR tag1.name = "granola bars")
AND (tag2.name = "microwave")
This query works beautifully in the playground.
The main issue is that I have up to 12 attributes, and maybe more. Once I hit 5 joins, that is my maximum allowed number of joins, so the query below doesn't work. (note that this isn't playground data, but a sample of my own)
SELECT s.StyleID FROM StyleSearch s
JOIN a0 in s.Attributes
JOIN a1 in s.Attributes
JOIN a2 in s.Attributes
JOIN a3 in s.Attributes
JOIN a4 in s.Attributes
JOIN a5 in s.Attributes
WHERE (a0 = "color-finish|Grey" OR a0 = "color-finish|Brown" OR a0 = "color-finish|Beige")
AND (a1 = "fabric-type|Polyester" OR a1 = "fabric-type|Faux Leather")
AND (a2 = "design-features|Standard" OR a2 = "design-features|Reclining")
AND (a3 = "style_parent|Contemporary" OR a3 = "style_parent|Modern" OR a3 = "style_parent|Transitional")
AND (a4 = "price_buckets|$1500 - $2000" OR a4 = "price_buckets|$2000 and Up")
AND (a5 = "dimension_width|84 in +")
I am not 100% sure I am using the proper query to perform this, but a simple where clause per below which works in SQL brings back anything matching in the or statements so I end up with items from each "AND statement.
SELECT s.StyleID FROM StyleSearch s
JOIN a in s.Attributes
WHERE (a = "color-finish|Grey" OR a = "color-finish|Brown" OR a = "color-finish|Beige")
AND (a = "fabric-type|Polyester" OR a = "fabric-type|Faux Leather")
AND (a = "design-features|Standard" OR a = "design-features|Reclining")
AND (a = "style_parent|Contemporary" OR a = "style_parent|Modern" OR a = "style_parent|Transitional")
AND (a = "price_buckets|$1500 - $2000" OR a = "price_buckets|$2000 and Up")
AND (a = "dimension_width|84 in +")
Here is an example of the data:
{
"StyleID": "chf_12345-bmc",
"Attributes": [
"brand|chf",
"color|red",
"color|yellow",
"dimension_depth|30 in +",
"dimension_height|counter height",
"materials_parent|wood",
"price_buckets|$500 - $1000",
"style_parent|rustic",
"dimension_width|55 in +"
]
}
I am looking for the proper way to handle this. Thanks in advance.
Is it possible for you to change the structure of your document to add filter attributes specifically for your query on e.g.
{
"StyleID": "chf_12345-bmc",
"Attributes": [
"brand|chf",
"color|red",
"color|yellow",
"dimension_depth|30 in +",
"dimension_height|counter height",
"materials_parent|wood",
"price_buckets|$500 - $1000",
"style_parent|rustic",
"dimension_width|55 in +"
],
"filter_color": "red,yellow",
"filter_fabric_type":"Polyester,leather"
}
This would eliminate the join restriction because now your query looks something like this:
SELECT s.StyleID FROM StyleSearch s
WHERE (CONTAINS(s.filter_color, "Grey") OR CONTAINS(s.filter_color, "Red"))
AND (CONTAINS(s.filter_fabric_type, "Polyester") OR CONTAINS(s.filter_fabric_type, "Leather"))
Of course this does mean that you have additional fields to maintain.
You might also consider writing a stored proc for this and using javascript to loop through your collection and filtering that way: DocumentDB stored procedure tutorial

Resources