Trying to fetch data from table with good performance - join

I am trying to fetch customer and owner data
customer
|cnumber |id |
|080204220 |32859471000|
|907501981|6029151000|
role
|id|type|
|32859471000|owner|
|6029151000|customer|
result set
id|number|owner number|type|
|32859471000|080204220 |080204220 | owner
|6029151000|907501981|080204220 |customer
query
select c.id,sub.cnumber,c.cnumber, r.roletype
from customer c
inner join role r on c.id = r.id
left outer join (select c.cnumber ,r.roletype,c.id
from customer c
INNER JOIN role r
ON c.id = r.id ) sub on sub.roletype='owner';
This query gives proper result, but left outer join with same tables may cause impact on performance, is there any other way to achieve this?

I would prefer you to go with this only.
select c.id,sub.cnumber,c.cnumber, r.roletype
from customer c
inner join role r on c.id = r.id
left outer join (select c.cnumber ,r.roletype,c.id
from customer c
INNER JOIN role r
ON c.id = r.id ) sub on sub.roletype='owner';

As far as I can get the logic, you need to display an "owner"-customer among all of the others.
Since there is only one owner in the example data, I'd do it using the "cross join" (cartesian join)
select c.id,sub.cnumber,c.cnumber, r.roletype
from customer c
inner join role r on c.id = r.id
cross join (select c.cnumber ,r.roletype,c.id
from customer c
INNER JOIN role r
ON c.id = r.id where r.roletype='owner') sub

select c.id,sub.cnumber,c.cnumber, r.roletype
from customer c
inner join role r on c.id = r.id
left outer join (select c.cnumber ,r.roletype,c.id
from customer c
INNER JOIN role r
ON c.id = r.id ) sub on sub.roletype='owner';

Related

JOIN SQL query with two tables

SELECT u.id, u.name, u.surname, p.id as p_id, SUM(t.summa)
FROM users u
LEFT JOIN pupils p ON p.userid = u.id
LEFT JOIN tulovlar t ON t.pupilid = p.id
WHERE u.turi = 3
GROUP BY u.id
ORDER BY u.surname
sql response is showing this error
#1055 - Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'crm_test.p.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

how to embed order by string in hql in grails for sorting?

In grails 2 i used to use the following hql
def sortp = ""
if(params.sort){
sortp = "order by r.${params.sort} ${params.order}"
}
def allRegsData = RaceRegistration.executeQuery("select r.id, r.bibLabelPrinted, r.raceParticipant.bibNumber, r.bibLabelCollected, r.raceParticipant.firstName,r.raceParticipant.lastName,r.raceParticipant.gender,r.race.name, rt.name, r.raceParticipant.ageDate, ad.genderOption, ad.minAge, ad.maxAge, sd.name, sm.encodedMark, p.name, p.abbreviation, ps.name, r.dateCreated, r.status, r.race.id, re.invoice.id, io.status, r.notes from InventoryOrder io inner join io.product p inner join io.productSize ps right outer join io.registration r left outer join r.registrationEntry re left outer join r.specialDivision sd left outer join r.ageDivision ad left outer join r.team rt left outer join r.seedMark sm where r.compositeEvent = ? ${sortp}", [raceGroup]);
I am now using grails 4 and it seems i can no longer use this way of embedding sortp string.
It throws the error
Unsafe query [select r.id, r.bibLabelPrinted, r.raceParticipant.bibNumber, r.bibLabelCollected, r.raceParticipant.firstName,r.raceParticipant.lastName,r.raceParticipant.gender,r.race.name, rt.name, r.raceParticipant.ageDate, ad.genderOption, ad.minAge, ad.maxAge, sd.name, sm.encodedMark, p.name, p.abbreviation, ps.name, r.dateCreated, r.status, r.race.id, re.invoice.id, io.status, r.notes from InventoryOrder io inner join io.product p inner join io.productSize ps right outer join io.registration r left outer join r.registrationEntry re left outer join r.specialDivision sd left outer join r.ageDivision ad left outer join r.team rt left outer join r.seedMark sm where r.compositeEvent = ? ]. GORM cannot automatically escape a GString value when combined with ordinal parameters, so this query is potentially vulnerable to HQL injection attacks. Please embed the parameters within the GString so they can be safely escaped.
i have tried this approach but it doesnt seem to sort
def allRegsData = RaceRegistration.executeQuery("select r.id, r.bibLabelPrinted, r.raceParticipant.bibNumber, r.bibLabelCollected, r.raceParticipant.firstName,r.raceParticipant.lastName,r.raceParticipant.gender,r.race.name, rt.name, r.raceParticipant.ageDate, ad.genderOption, ad.minAge, ad.maxAge, sd.name, sm.encodedMark, p.name, p.abbreviation, ps.name, r.dateCreated, r.status, r.race.id, re.invoice.id, io.status, r.notes from InventoryOrder io inner join io.product p inner join io.productSize ps right outer join io.registration r left outer join r.registrationEntry re left outer join r.specialDivision sd left outer join r.ageDivision ad left outer join r.team rt left outer join r.seedMark sm where r.compositeEvent = :rg order by :s", [rg: raceGroup, s: 'r.' + params.sort + ' ' + params.order ]);
i appreciate any guide as to how to do the same in grails 4? Thanks!
thanks to Prudius from grails.slack.com
I had to change slightly how i form the string.
def sortp = ""
if(params.sort){
sortp = "order by r.${params.sort} ${params.order}"
}
def q = "select r.id, r.bibLabelPrinted, r.raceParticipant.bibNumber, r.bibLabelCollected, r.raceParticipant.firstName,r.raceParticipant.lastName,r.raceParticipant.gender,r.race.name, rt.name, r.raceParticipant.ageDate, ad.genderOption, ad.minAge, ad.maxAge, sd.name, sm.encodedMark, p.name, p.abbreviation, ps.name, r.dateCreated, r.status, r.race.id, re.invoice.id, io.status, r.notes from InventoryOrder io inner join io.product p inner join io.productSize ps right outer join io.registration r left outer join r.registrationEntry re left outer join r.specialDivision sd left outer join r.ageDivision ad left outer join r.team rt left outer join r.seedMark sm where r.compositeEvent = :rg "
q <<= sortp
def allRegsData = RaceRegistration.executeQuery(q, [rg: raceGroup]);
this further helped.
Groovy literal StringBuilder/StringBuffer

How to only join on numeric values

Right now I have:
select
a.id
b.colone
b.coltwo
from tablea a
left join tableb b on b.id = a.id
I'm getting the "numeric value not recognized" error because one value from b.id is not numeric. How do I join results from tableb to tablea just omitting the non-numeric value/row? Or how else can I bypass this error? Using snowflake.
Thank you!
You can use TRY_TO_NUMBER():
select
a.id
b.colone
b.coltwo
from tablea a
left join tableb b on TRY_TO_NUMBER(b.id) = a.id

Rails - Using SELECT in a WHERE clause

I'm trying to make a Rails model scope based on the following query:
SELECT * FROM tableA a
INNER JOIN tableB b ON a.id = b.id
WHERE a.id = (SELECT MAX(id) FROM tableB WHERE field = a.field)
I want to join rows of tableA with only one of tableB rows (the max one).
Is it possible?
Thank you!
TableA
.joins(:tableB)
.where("a.id = (SELECT MAX(id) FROM tableB WHERE field = a.field)")
You'll need to have an association between the two tables if you want the joins method works

DQL Select Join

I'm trying to make a DQL query (doctrine from symfony 2.2) with no success on these entities:
Lesson
Which has several LessonContent
Which are each linked to a User
I want to retrieve all the lessons of a user (should be pretty basic...).
SELECT l, lc FROM MyBundle:LessonContent lc
JOIN lc.lesson l JOIN lc.modifiedBy u
WHERE lc.creation=1 AND u.id = :userId
But this returns the LessonContent entities. If I select from Lesson, I can't JOIN the lessons (which is probably what I should be doing).
Can anyone help me?
The main table you query from is what doctrine gives you back as the main objects, so the following should work (assuming l.content points to the LessonContent association):
SELECT l, lc FROM MyBundle:Lesson l
JOIN l.content lc
JOIN lc.modifiedBy u
WHERE lc.creation=1 AND u.id = :userId
It turned out I needed to have a l.content*s* attribute in order to be able to select from lessons and then JOIN on the rest.
Entity:
/**
* #var ArrayCollection $contentHistory
* #ORM\OneToMany(targetEntity="AAA\CoreBundle\Entity\LessonContent", mappedBy="lesson", cascade={"persist", "remove"})
* #ORM\OrderBy({"lastModified" = "DESC"})
*/
private $contentHistory;
Query:
SELECT l FROM AAACoreBundle:Lesson l JOIN l.contentHistory lc JOIN lc.modifiedBy u WHERE lc.creation=1 AND u.id = :userId GROUP BY l
And with that it works like a charm!

Resources