Translate this SQL to jOOQ - sql

I'm failing to translate this SQL into working jOOQ:
SELECT * FROM product p JOIN
( SELECT * FROM
(SELECT max(product_rev_id) as maxi
FROM product_rev
GROUP BY product_id) as a
JOIN product_rev as t ON t.product_rev_id = maxi
WHERE valid_to IS NOT NULL
) as z ON z.product_id = p.product_id
WHERE p.product_id in(1,2,3,4,5);
Here's the SQL-Fiddle:
http://sqlfiddle.com/#!9/d7816/1
I tried several hours, but it's getting a mess with all that aliases and jOOQ.

The easiest way to translate such nested queries to jOOQ is by looking at jOOQ sub queries as composable, reusable elements. I.e.
// Assuming this
import static org.jooq.impl.DSL.*;
// Then write the inner-most derived table
Table<?> a = table(
select(max(PRODUCT_REV.PRODUCT_REV_ID).as("maxi"))
.from(PRODUCT_REV)
.groupBy(PRODUCT_REV.PRODUCT_ID)
).as("a");
// Then use a in the middle derived table
ProductRev t = PRODUCT_REV.as("t");
Table<?> z = table(
select()
.from(a)
.join(t).on(t.PRODUCT_REV_ID.eq(a.field("maxi", PRODUCT_REV.PRODUCT_REV_ID.getType())))
.where(t.VALID_TO.isNotNull())
).as("z");
// Finally, the outer-most query
Product p = PRODUCT.as("p");
DSL.using(configuration)
.select()
.from(p)
.join(z).on(z.field(PRODUCT_REV.PRODUCT_ID).eq(p.PRODUCT_ID))
.where(p.PRODUCT_ID.in(1, 2, 3, 4, 5))
.fetch();
Alternative, using views
From your query, I suspect that the only really dynamic part is
WHERE p.product_id in (1, 2, 3, 4, 5)
This means that you might as well create a view in your database for the rest of the query, and query that view from your client.

Related

How to Join two Queries in Sequelize

I tried to join two queries and based on it find the result. I am able to write the code in SQL. My SQL Code is
SELECT a.awbid,
m.mpscount
FROM ( select a.awbid
FROM awbmaster a
where a.batchid ='B/117/15022022'
and a.hubid ='117'
) as a
left join ( select count('mpsid') as "mpscount" ,
awbid from
mpsmaster m
where m.batchid = 'B/117/15022022'
group by "awbid"
) as m on a.awbid = m.awbid
But, I am not yet found any solution regarding the sequelize. How can I write the above SQL code in sequelize?
First, we can simplify this SQL query simply using a subquery to find out mpscount:
SELECT a.awbid,
(SELECT count(*)
FROM mpsmaster m
WHERE m.batchid = 'B/117/15022022'
AND m.awbid=a.awbid ) AS mpscount
FROM awbmaster a
WHERE a.batchid ='B/117/15022022'
AND a.hubid ='117'
Now if we already have both models MpsMaster and AwbMaster and a correct association between them then we can make a request something like this:
const records = AwbMaster.findAll(}
attributes: [
'awbid',
[Sequelize.literal('(SELECT count(*) FROM mpsmaster m WHERE m.batchid = \'B/117/15022022\' AND m.awbid=AwbMaster.awbid)'), 'mpscount']
]
})

Chaining endless sql and performance

I am chaining sql according to user filter which is unknown.
For instance he would like to first ask for certain dates :
def filterDates(**kwargs):
q = ('''
SELECT date_num, {subject_col}, {in_col} as {out_col}
FROM {base}
WHERE date_num BETWEEN {date1} AND {date2}
ORDER BY date_num
''').format(subject_col=subject_col,**kwargs)
return q
(base is input query string from previous, see next)
and then he wants to calculate another thing(or many) so we pass the dates filter string query q as base to this query:
WITH BS AS (
SELECT date_num, {subject_col}, {in_col}
FROM {base}
)
SELECT t1.{subject_col},t1.{in_col}, t2.{in_col} - t1.{in_col} as {out_col}
FROM BS t1
JOIN BS t2
ON t1.{subject_col} = t2.{subject_col} AND t2.date_num = {date2}
WHERE t1.date_num = {date1}
''').format(subject_col=subject_col,**kwargs)
Here the {base} is going to be :
base='('+q+')'+'AS base'
Now we can chain queries as much as we want and it works.
How would the engine handle this ? is that means that the efficiency is bad because engine has to make 2 rounds ( instead of having a normal WHERE on the dates? ) how would he optimize this?
Is there a common good practice way to chain unknown number of queries?

How to perform translation from RAW SQL to django queryset

I am struggling with conversion to django query having raw sql
I am new in django and any help will be appreciated
There are simple models:
Winemaker - target model
Wine
Post
Winemaker has 1+ Wines
Wine has 1+ Posts
I know that it should be done with annotations but have no idea how to implement it.
select w2.*,
(select count(wp.id)
from web_winemaker www
inner join web_wine ww on www.id = ww.winemaker_id
inner join web_post wp on ww.id = wp.wine_id
where
ww.status=20
and
wp.status=20
and
www.id = w2.id
) as wineposts_count,
(
select count(w.id)
from web_winemaker www1
inner join web_wine w on www1.id = w.winemaker_id
where
w.status=20
and www1.id = w2.id
) as wines_count
from web_winemaker w2;
You should be able to accomplish this with a Count aggregation expression in an annotate function. I took a guess at your related_name values on your relationship fields, so the following code may not plug in directly, but should give you an idea of how to do what you want.
from django.db.models import Count, Q
wine_makers = Winemaker.objects.annotate(
posts_count=Count(
'wine__post__id',
filter=Q(wines__status=20, wines__posts__status=20),
),
wines_count=Count(
'wines__id',
filter=Q(wines__status=20),
),
)
You may need to supply distinct=True depending on if you're crossing relationships.

SQL Developer AND OR Statements

Got a task at my job to get several fields from different tables into one sheet, using SQL Developer. Im a noob to SQL, however managed to build something. Taking a look at my output learns me that the restrictions I built in do not work. Short description below. Can someone please help me?! In my output I still see values other than 1006 in the ATINN field, values other tham Empty in the BWTAR field.. What am I doing wrong?
5 tables linked together
Restriction on Users (DMSTRAATL, etc)
Restriction on Productgroup (006*, etc)
Restriction on some individual products
Restriction on product type (HERB, etc)
Restriction on specific data field (All products should have atinn = 1006)
Restiction on specific data field (all products should have bwtar = empty)
SELECT
dmssap.mara.matnr, dmssap.mara.mtart, dmssap.mara.matkl,
dmssap.mara.ersda, dmssap.mara.ernam, dmssap.mara.bismt,
dmssap.marc.werks, dmssap.inob.cuobj,
LPAD(INOB.CUOBJ, 18, '0') AS CUOBJ_18, dmssap.ZMM_MATNR_MPO.matnr, dmssap.ZMM_MATNR_MPO.pname,
dmssap.ZMM_MATNR_MPO.stat, dmssap.mbew.bwkey, dmssap.mbew.bklas,
dmssap.mbew.bwtar, dmssap.mbew.vprsv, dmssap.mbew.bwtty, dmssap.mbew.verpr,
dmssap.mbew.stprs, dmssap.ZMM_MATNR_MPO.matnr, dmssap.ZMM_MATNR_MPO.pname,
dmssap.ZMM_MATNR_MPO.stat, dmssap.ausp.atinn, dmssap.ausp.atwrt
FROM dmssap.mara
LEFT OUTER JOIN dmssap.marc
ON (dmssap.marc.matnr) = (dmssap.mara.matnr)
LEFT OUTER JOIN dmssap.ZMM_MATNR_MPO
ON (dmssap.ZMM_MATNR_MPO.matnr) = (dmssap.mara.matnr)
LEFT OUTER JOIN dmssap.mbew
ON CONCAT(dmssap.mbew.matnr, dmssap.mbew.bwkey) = CONCAT(dmssap.marc.matnr, dmssap.marc.werks)
LEFT OUTER JOIN dmssap.inob
ON (dmssap.inob.objek) = (dmssap.mara.matnr)
LEFT OUTER JOIN dmssap.ausp
ON dmssap.ausp.objek = LPAD(INOB.CUOBJ, 18, '0')
WHERE (dmssap.mara.ernam) IN (
'DMSTRAATL', 'V0342628', 'V0343809',
'V0336003', 'V0009830', 'V0309577', 'V0010144'
)
AND (dmssap.mara.matkl) IN (
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
)
AND (dmssap.mara.mtart) IN ('HERB', 'HALB', 'ZSTP')
AND (dmssap.ausp.atinn) = '1006'
AND (dmssap.mbew.bwtar) IS NULL;
AND operator has an higher precedence order than OR . to make your query easily readable use braces () around filter clauses.
Let's say you want to select records which have certain values in dmssap.mara.matkl or certain values in dmssap.mara.matnr then you can use braces between these blocks to be precise as shown below.
AND (
(dmssap.mara.matkl) IN (
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
)
)
WHERE (dmssap.mara.ernam) IN (
'DMSTRAATL', 'V0342628', 'V0343809',
'V0336003', 'V0009830', 'V0309577', 'V0010144'
)
AND (dmssap.mara.matkl) IN (
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
)
AND (dmssap.mara.mtart) IN ('HERB', 'HALB', 'ZSTP')
AND (dmssap.ausp.atinn) = '1006'
AND (dmssap.mbew.bwtar) IS NULL;
The crux is in your WHERE statement. The evaluation order for keywords in the WHERE statement is NOT -> AND -> OR
What you seem to want is this instead:
WHERE (dmssap.mara.ernam) IN (
'DMSTRAATL', 'V0342628', 'V0343809',
'V0336003', 'V0009830', 'V0309577', 'V0010144'
)
AND (dmssap.mara.matkl) IN ((
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
))
AND (dmssap.mara.mtart) IN ('HERB', 'HALB', 'ZSTP')
AND (dmssap.ausp.atinn) = '1006'
AND (dmssap.mbew.bwtar) IS NULL;
Notice the two extra brackets around the OR on the AND

Database (Oracle 11g) query optimization for joins

So I am trying to optimize a bunch of queries which are taking a lot of time. What I am trying to figure out is how to create an index on columns from different tables.
Here is a simple version of my problem.
What I did
After Googling I looked into bitmap index but I am not sure if this is the right way to solve the issue
Issue
There is a many to many relationship b/w Student(sid,...) and Report(rid, year, isdeleted)
StudentReport(id, sid, rid) is the join table
Query
Select *
from Report
inner join StudentReport on Report.rid = StudentReport.rid
where Report.isdeleted = 0 and StudentReport.sid = x and Report.year = y
What is the best way to create an index?
Please try this:
with TMP_REP AS (
Select * from Report where Report.isdeleted = 0 AND Report.year = y
)
,TMP_ST_REP AS(
Select *
from StudentReport where StudentReport.sid = x
)
SELECT * FROM TMP_REP R, TMP_ST_REP S WHERE S.rid = R.rid