I am trying to convert this SQL into a JPA #Query call, and am struggling to understand how to handle multiple table calls in one JPA Query, specifically i am trying to return a Count of all the Users that are assigned to a Program.
The DB structure is shown:
The query I want to translate is:
SELECT *FROM User WHERE id in ( SELECT user FROM UserProjectAssignment WHERE project in ( SELECT id FROM Project WHERE program = programId))
My current Query is:
#Query("SELECT COUNT(u) FROM User u, UserProjectAssignment upa, Project p WHERE u.id = upa.project AND WHERE upa.project = (p.program = :programId)")
Long countUsersAssignedToProgram(#Param("programId") Long programId);
Basically what you need here is query with JOIN s
But one can form the query only if he knows the class structures.
You can change the mysql query like this
Select user from User user join UserProjectAssignment upa on user.id = upa.userid join Project p on upa.projectId = p.id join program pgm on p.programId = pgm.id ;
Related
I have a Java application using Spring and Hibernate. I'm updating a legacy application that was using a stored procedure to get a count of rows from the below query and display the count on a home page. I've been trying to implement QueryDSL, as we need this to be type safe and cannot use inline strings, but can't seem to get the syntax correctly (if it is even possible to handle a query like this in QueryDSL)
SELECT count(*) from TABLE_A A
LEFT OUTER JOIN
(
SELECT ONE_ID, TWO_ID, STATUS, STATUS_CHANGE_DATE
FROM
(
SELECT B.ONE_ID, B.FLOW_STATUS_ID, C.DESCRIPTION, B.STATUS_CHANGE_DATE,
MAX (B.STATUS_CHANGE_DATE) OVER (PARTITION BY B.ONE_ID) RECENT_DATE
FROM TABLE_B B
INNER JOIN TABLE_C C ON B.TWO_ID = C.THREE_ID
)
WHERE STATUS_CHANGE_DATE = RECENT_DATE
) D
ON D.ONE_ID = A.THREE_ID WHERE D.TWO_ID = 3;
Can anyone please point me in the right direction or recommend another way to handle this query?
Thanks!
I tried using QueryDSL's HibernateQueryFactory to construct the query but I'm not sure how to construct it in a way that handles the outside left join with the two inner queries that also includes an inner join.
I have two scripts that work in isolation, but I don't know how to stitch them together to do this all at once.
The first script:
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
This produces a table (is that the right word?). Suppose I could save that table as 'appQuote'. I then want to run this script on it:
SELECT
ApplicationId,
STRING_AGG(YEARLYPAYAMOUNT) allPremium,
STRING_AGG(SECTIONID) allSection,
STRING_AGG(SHORTNAME) allSectionName,
FROM
appQuote
GROUP BY
ApplicationId
For storage reasons I don't want to actually save the table from the first script, I just want to get the result from the first script and immediately apply the second script to it.
This is very basic, so any guidance would help.
The relevant term is known as a derived table.
In SQL you can use the result of a query as the input to another. The "nested query" produces the derived table which is then consumed by the outer query:
Select <columns>
from (
select <columns> from table join table etc
)as TableAliasName
To get the nomenclature right, what you have are not scripts or tables, but rather two queries. When a query runs it produces a result set.
To accomplish your goal, either of these queries will work:
SELECT
ApplicationId,
STRING_AGG(YEARLYPAYAMOUNT) allPremium,
STRING_AGG(SECTIONID) allSection,
STRING_AGG(SHORTNAME) allSectionName,
FROM (
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
) appQuote
GROUP BY
ApplicationId
Here, the inner nested query is formally called a derived table, but people will often use the phrase "subquery".
The other option is a Common Table Expression (CTE):
With appQuote As (
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
)
SELECT
ApplicationId,
STRING_AGG(YEARLYPAYAMOUNT) allPremium,
STRING_AGG(SECTIONID) allSection,
STRING_AGG(SHORTNAME) allSectionName,
FROM
appQuote
GROUP BY
ApplicationId
Finally, you could also create a View from the first query:
CREATE View AppQuote As
SELECT *
FROM PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTES bq
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.PRODUCT p ON bq.ProductId = p.Id
JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.BCAPPLICATIONQUOTEFEES F ON F.ApplicationQuoteId = bq.Id
LEFT JOIN PROD_ANALYTIC.SRC_MVC_AU_DBO.COVERAGESECTIONTYPE CST ON F.CoverageSectionTypeID = CST.SECTIONID
A view is not just a query; it will actually become part of the database, such that you can use it in many of the same ways you would use a table saved on disk, and then the second query in the original question will run unmodified.
tell me how to make a user access to data access,
There is a table with dialogs, and you need to build a query so that another user cannot see this data if he does not have access to this dialog.
I tried to do it but it didn't work
SELECT *
FROM NameDS INNER JOIN
DialogueListDS ON NameDS.UserID = DialogueListDS.UserID INNER JOIN
MessegesListDS ON DialogueListDS.DialogueID = MessegesListDS.DialogueID
WHERE NameDS.UserID = '2B3F7596-DEC9-4CAF-A867-0127186CFC5C'
I have a user who can have meetings from different relationships.He can be directly assigned to a meeting with one too many relationships, he can have user groups with many too many relationships that can have meetings with many too many relationships, and he can be responsible for a meeting with a relationship of one to many.
I want to get all meetings for one user. I don't want to merge the collections because I want to be able to use features like where directly in the database. My attempt is to merge all meeting ids and then get the meetings via 'whereIn'.
$ids = $this->meetings()->select('meetings.id')
->union($this->meetingsFromGroups()->select('meetings.id'))
->union($this->responsibleMeetings()->select('meetings.id'));
return Meeting::whereIn('id', $ids)->get();
When I execute this, I get this error:
"SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select `meetings`.`id` from `meetings` inner join `meeting_user_group` on' at line 1 (SQL:...)"
The SQL that is executed:
select *
from `meetings`
where `id` in (
(
select `meetings`.`id`
from `meetings`
inner join `meeting_user` on `meetings`.`id` = `meeting_user`.`meeting_id`
where `meeting_user`.`user_id` = 1
)
union
(
select `meetings`.`id`
from `meetings`
inner join `meeting_user_group` on `meeting_user_group`.`meeting_id` = `meetings`.`id`
inner join `user_groups` on `user_groups`.`id` = `meeting_user_group`.`user_group_id`
inner join `user_user_group` on `user_user_group`.`user_group_id` = `user_groups`.`id`
where `user_user_group`.`user_id` = 1
)
union
(
select `meetings`.`id`
from `meetings`
where `meetings`.`responsible_id` = 1
and `meetings`.`responsible_id` is not null
)
)
The relations:
public function responsibleMeetings(): HasMany {
return $this->hasMany(Meeting::class, 'responsible_id');
}
public function meetings(): BelongsToMany {
return $this->belongsToMany(Meeting::class)->withTimestamps();
}
public function meetingsFromGroups(): HasManyDeep {
return $this->hasManyDeepFromRelations($this->userGroups(), (new UserGroup())->meetings());
}
I'm using the package Staudenmeir\EloquentHasManyDeep for meetingsFromGroups.
I can't use union on the whole meeting, because then I would get
SQLSTATE[21000]: Cardinality violation: 1222 The used SELECT statements have a different number of columns
because of the pivot fields.
How would the SQL have to change for it to work, and how can I do that with Eloquent?
By default whereIn expects array to perform IN() clause on array items but in your case your are sending a union query which is why it is throwing error.
$ids = $this->meetings()->select('meetings.id')
->union($this->meetingsFromGroups()->select('meetings.id'))
->union($this->responsibleMeetings()->select('meetings.id'))
->pluck('id')->all();
return Meeting::whereIn('id', $ids)->get();
Additionally whereIn accepts a closure method also but not sure how would you call these relateables $this->meetings() ,$this->meetingsFromGroups() & $this->responsibleMeetings() inside closure
return Meeting::whereIn('id', function($query){
$query->select('...')
...;
})->get();
I am working with APEX 4.2.1.00.08 and I keep getting the validation error "LOV query is invalid, a display and a return value are needed, the column names need to be different. If your query contains an in-line query, the first FROM clause in the SQL statement must not belong to the in-line query.". I'm not sure what's causing this. My sql is:
SELECT u1.name d, susu.subunitid r
FROM basic.subunitsuperunit susu
INNER JOIN basic.unit u1 ON susu.subunitid = u1.unitid
INNER JOIN basic.unit u2 ON susu.superunitid = u2.unitid
WHERE level = 3
AND u1.name != 'XYZ'
CONNECT BY PRIOR subunitid = superunitid
START WITH u1.name = (SELECT u3.name FROM basic.unit u3 WHERE u3.unitid = (SELECT TO_NUMBER(gp.value) FROM basic.global_parameters gp WHERE gp.name = 'A_UNIT'))
ORDER BY u1.name
I have made sure there was no semicolon, and I have checked this query in SQL Developer and it runs fine. I already realize those subqueries aren't optimal, but what am I doing wrong here?
Try to create an apex_collection or a database view with your query and then create your lov based on the new object.
I too face same kind of difficulties with other queries and I always solved it so.
This happens also if you begin your query using the WITH clause. You can wrap the whole lot up with
SELECT name d, ID r
From (your query here)
I see this post is old, but I ran into the same error in the "Lists of Values" portion of the application. My issue happened to be that a grant was missing for the applicaton's run as user.