Use alias for JOIN using JOOQ's SelectQuery - sql

I need to write query with nested select and join using JOOQ's SelectQuery:
SELECT *
FROM (select * from
"public"."parent"
order by "public"."parent"."setup_time"
desc limit 10 offset 0) as "parent1"
join "public"."child"
on "public"."child"."parent_id" = "parent1"."id"
where "public"."child"."name" = 'test'
So, I've written something like this:
SelectQuery<ParentRecord> subSelectQuery = context.selectQuery(PARENT);
selectQuery.addJoinOnKey(CHILD, JoinType.JOIN, CHILD.PARENT_ID);
But it generates sql code like
join "public"."child" on "public"."child"."parent_id" = "public"."parent"."id
How can I use alias parent1 instead of full table name "public"."child"."parent_id"?

I've found solution.
SelectQuery<ParentRecord> selectQuery = context.selectQuery(subSelectQuery.asTable(PARENT.getName()));
selectQuery.addJoin(CHILD, JoinType.JOIN, CHILD.PARENT_ID.eq(PARENT.as(PARENT.getName()).ID));

Related

Optimize many subqueries with same source

Does anyone have any idea how to optimize such a query?
How do you encapsulate this into one query?
,(SELECT top 1 WFD_AttDecimal2 as Nocleg
FROM WFElements INNER JOIN
WFElementDetails ON WFElements.WFD_ID = WFElementDetails.DET_WFDID
Where
WFD_STPID = #KrokSlownikUdostepnionyKraj
and dbo.ClearWFElemID (WFD_AttChoose20) = KrajDoDiety6 -- id kraju
and dbo.ClearWFElemID (WFD_AttChoose9) = #Spolka) as NoclegStawka7
,(SELECT top 1 WFD_AttDecimal3 as NoclegPrzelicznik
FROM WFElements INNER JOIN
WFElementDetails ON WFElements.WFD_ID = WFElementDetails.DET_WFDID
Where
WFD_STPID = #KrokSlownikUdostepnionyKraj
and dbo.ClearWFElemID (WFD_AttChoose20) = KrajDoDiety6 -- id kraju
and dbo.ClearWFElemID (WFD_AttChoose9) = #Spolka) as NoclegPrzelicznik7
,PelneDoby6 * (select MinDieta from #MinDieta where RodzajDelegacji = KrajZagr6) as MinIloscDiet7
from #Dieta4
You can use OUTER APPLY or CROSS APPLY and select all the necessary columns within that, you can then access all of them in the SELECT
SELECT
wfd.Nocleg as NoclegStawka7
, wfd.NoclegPrzelicznik as NoclegPrzelicznik7
, d.PelneDoby6 * (select md.MinDieta from #MinDieta md where RodzajDelegacji = KrajZagr6) as MinIloscDiet7
from #Dieta4 d
OUTER APPLY (
SELECT TOP (1)
WFD_AttDecimal2 as Nocleg,
WFD_AttDecimal3 as NoclegPrzelicznik
FROM WFElements INNER JOIN
WFElementDetails ON WFElements.WFD_ID = WFElementDetails.DET_WFDID
Where
WFD_STPID = #KrokSlownikUdostepnionyKraj
and dbo.ClearWFElemID (WFD_AttChoose20) = KrajDoDiety6 -- id kraju
and dbo.ClearWFElemID (WFD_AttChoose9) = #Spolka
) wfd;
Note also:
I suggest you rethink your usage of a scalar function ClearWFElemID as it can be slow. Use a join or a Table Valued function instead.
TOP (1) without an ORDER BY is a code-smell: you may get a different result each time.
Always specify the table alias when using subqueries, or you risk getting the wrong results.

Add an alias for a subquery that I can reference in the main WHERE clause

I want to create an alias for a subquery so I can reference in the WHERE clause from the main query but it keeps throwing me error telling me that the column doesn't exist.
SELECT x.id_lib, (
SELECT sg.nom FROM subgenres sg WHERE (x.id_gen = sg.id)
)as genname, x.id_gen
FROM subgenres_books x WHERE x.id_lib = 1 and genname LIKE 'Satira'
As zip suggests, you can phrase the query as a simple join:
SELECT sb.id_lib, s.nom, sb.id_gen
FROM subgenres_books sb JOIN
subgenres s
ON s.id_gen = sb.id
WHERE sb.id_lib = 1 and s.nom = 'Satira';
However, there seems to be no reason to return the subgenre -- it is constant. So I'm thinking that an EXISTS subquery is appropriate:
SELECT sb.id_lib, sb.id_gen
FROM subgenres_books sb
WHERE sb.id_lib = 1 AND
EXISTS (SELECT 1
FROM subgenres s
WHERE s.id_gen = sb.id
s.nom = 'Satira'
);
Try this:
SELECT x.id_lib, x.id_gen, genname.nom
FROM subgenres_books x inner join
subgenres genname on x.id_gen = genname.id
WHERE x.id_lib = 1 and genname.nom LIKE 'Satira'

SQL Server Loop Over Records

I have a view vwDocumentLinks with data as shown below:
I have another table RiskTypes with data as below.
The link between the table & viewis : Idx25 = Risk Type and LinkDocNo = DocumentType. What I am trying to achieve is to get DocumentType in RiskTypes that's not in the view vwDocumentLinks foreach BaseValue and where Idx25 = RiskType. An example using a single BaseValue will be:
SELECT * FROM RiskTypeDocuments WHERE RiskType = 'BUSINESS LIMITED COMPANY' AND DocumentType NOT IN (SELECT LINKDOCNO FROM DBO.VWLINKS WHERE BaseValue = '00007573-1637-4B8E-9374-730AF58BCFB6')
I tried the below query and it's not working as expected. Any help will be greatly appreciated. I am a newbie in SQL
SELECT dbo.RiskTypeDocuments.DocumentType,
dbo.RiskTypeDocuments.RiskType,
dbo.vwLinks.BaseValue AS Document
FROM dbo.vwLinks LEFT OUTER JOIN
dbo.RiskTypeDocuments ON dbo.vwLinks.LinkDocNo =
dbo.RiskTypeDocuments.DocumentType AND dbo.vwLinks.Idx25 =
dbo.RiskTypeDocuments.RiskType
WHERE dbo.RiskTypeDocuments.DocumentType IS NOT NULL
ORDER BY Document
NB: I can't change the schema. I can only create views from the existing tables.
Sample Data from the two datasets: vwDocumentLinks & RiskTypeDocuments
SELECT a.DocumentType,
a.RiskType,
b.BaseValue AS Document
FROM dbo.RiskTypeDocuments as a
INNER JOIN (Select distinct Idx25, BaseValue from vwDocumentLinks) as b on b.Idx25 = a.RiskType
where a.DocumentType not in (Select LINKDOCNO from vwDocumentLinks as c where c.basevalue = b.BaseValue )
I think what you are looking for is NOT EXISTS. It takes a little to get your head around, but the idea is to have what is called a correlated subquery. The subquery is joined to the main query, hence the term correlated.
SELECT *
FROM RiskTypeDocuments
WHERE NOT EXISTS (
SELECT 1 FROM vwDocumentLinks
WHERE RiskTypeDocuments.RiskType = vwDocumentLinks.idx25
AND RiskTypeDocuments.DocumentType = vwDocumentLinks.LinkDocNo
)
If you want to retrieve the records which don't exist in the view then
Try like this
SELECT d.DocumentType,
d.RiskType,
v.BaseValue
FROM dbo.vwLinks AS v
OUTER JOIN dbo.RiskTypeDocuments d ON v.LinkDocNo = d.DocumentType AND v.vwLinks.Idx25 =d.RiskType
WHERE v.BaseValue IS NULL
ORDER BY DocumentType

I need to do a sub-select in DQL

I have this query:
$query = $this->createQueryBuilder('l')
->select('l')
->leftJoin('l.processedLeads', 'pl')
->where('pl.company <> :company')
->andWhere('pl.company IS NULL')
->setParameters(array('company' => $company))
->getQuery();
But i need it formed like the following:
SELECT * FROM leads WHERE NOT IN
( SELECT * FROM processed_leads WHERE lead = :lead AND company = :company)
Can i do a sub-select in a join where 2 parameters of the join (lead_id and company) do not exist?
As in, only select the leads that do not exist in processedLeads with the specific company?
I'm not familiar with the QueryBuilder, but I would recommend something like this in DQL:
$query = $em->createQuery('SELECT l FROM Project\model\leads l WHERE l NOT IN
(SELECT p.lead FROM Project\model\processed_leads p WHERE p.lead = ? AND company = ?)')
->setParameters(array($lead, $company))
->getResult;
Hopefully, this helps you. I would use the NOT INstatement. In case the sub query returns a null value, there is just no lead in the processed_leads for this company and you'll get all leads - which should be ok in this case.

Sql query taking forever to execute

Following is query that i am trying to execute and it is taking forever to execute.
SELECT DISTINCT (CLN_CLNDR_DT)FROM CLN_CLNDR CLN,
SYG_SYSTEM_GLOBALS SYG,CTD_CSH_TRNSCTN_DTLS CTD WHERE CLN.CLN_BP_ID = SYG.SYG_BP_ID AND CLN.CLN_ENTITY_ID = CTD.CTD_ENTITY_ID AND CLN_DT_SEQ_NUM
IN
(SELECT DISTINCT (CLN1.CLN_DT_SEQ_NUM)
FROM CLN_CLNDR CLN1,
SBD_SYS_BSNS_DTS SBD,
SYG_SYSTEM_GLOBALS SYG,
CTD_CSH_TRNSCTN_DTLS CTR
WHERE SBD.SBD_BSNS_DT = CLN1.CLN_CLNDR_DT
AND CLN1.OU_ID = SBD.OU_ID
AND CLN1.CLN_BP_ID = SYG.SYG_BP_ID
AND CLN1.CLN_ENTITY_ID = CTR.CTD_ENTITY_ID
);
When i try to run just the query inside in , it easily returns result as
(522,470,419,417,553,582,305,361)
SELECT DISTINCT (CLN1.CLN_DT_SEQ_NUM)
FROM CLN_CLNDR CLN1,
SBD_SYS_BSNS_DTS SBD,
SYG_SYSTEM_GLOBALS SYG,
CTD_CSH_TRNSCTN_DTLS CTR
WHERE SBD.SBD_BSNS_DT = CLN1.CLN_CLNDR_DT
AND CLN1.OU_ID = SBD.OU_ID
AND CLN1.CLN_BP_ID = SYG.SYG_BP_ID
AND CLN1.CLN_ENTITY_ID = CTR.CTD_ENTITY_ID;
Also when i try to execute directly the full query replacing the query inside in block
with the result of inner query that is (522,470,419,417,553,582,305,361),
It is working fine.
As i am new to this , i don't know what is going on .
Please help me with this.
I don't think you need all the tables in the subquery since you are already using them to filter rows in the outer query. Try this:
SELECT DISTINCT (CLN_CLNDR_DT)
FROM CLN_CLNDR CLN,
SYG_SYSTEM_GLOBALS SYG,
CTD_CSH_TRNSCTN_DTLS CTD
WHERE CLN.CLN_BP_ID = SYG.SYG_BP_ID
AND CLN.CLN_ENTITY_ID = CTD.CTD_ENTITY_ID
AND CLN_DT_SEQ_NUM
IN
(SELECT DISTINCT (CLN1.CLN_DT_SEQ_NUM)
FROM CLN_CLNDR CLN1,
SBD_SYS_BSNS_DTS SBD,
WHERE SBD.SBD_BSNS_DT = CLN1.CLN_CLNDR_DT
AND CLN1.OU_ID = SBD.OU_ID
);