Recursive select in Postgres SQL - postgresql

I'm trying to make my first recursive query in SQL and get an unxpected syntax error with inner join clause. I don't understand what causes this error. The query is simple it is just to select all employee attached to their boss with simple rule: BOSS_POS_ID = POS_ID
Here is example of my data:
POS_ID;POS_NAME;BOSS_POS_ID
32520602;CEO;
32809988;Manager;32520602
35244656;Vice;32520602
35244652;CEO assistant;32520602
35042934;Manager;32520602
35255704;Manager;32520602
35342468;Director;32520602
34091164;Director;32520602
35236439;Excecutive;32520602
32809978;Director;32520602
Here is my query:
with recursive subordinates as
(
select POS_ID, POS_NAME, BOSS_POS_ID
from gdm.hr_oss
where
POS_ID = 32520602
and CAL_DAY = (select max(CAL_DAY) from gdm.hr_oss)
union select
e.POS_ID,
e.POS_NAME,
e.BOSS_POS_ID
from gdm.hr_oss e
where CAL_DAY = (select max(CAL_DAY) from gdm.hr_oss)
inner join subordinates s on s.POS_ID = e.BOSS_POS_ID
)
select * from subordinates;
Here is error:
ERROR. Execution failed on sql '
with recursive subordinates as
(
select POS_ID, POS_NAME, BOSS_POS_ID
from gdm.hr_oss
where
POS_ID = 32520602
and CAL_DAY = (select max(CAL_DAY) from gdm.hr_oss)
union select
e.POS_ID,
e.POS_NAME,
e.BOSS_POS_ID
from gdm.hr_oss e
where CAL_DAY = (select max(CAL_DAY) from gdm.hr_oss)
inner join subordinates s on s.POS_ID = e.BOSS_POS_ID
)
select * from subordinates;
': syntax error at or near "inner"
LINE 15: inner join subordinates s on s.POS_ID = e.BOSS_POS_ID

Related

Prisma ORM Generated SQL Performance

I have a query that I've written in Prisma. It basically connects 7 tables, each of which only has maybe 2-4 rows. Yes, 2-4 rows, that's it.
The query that Prisma generates can take upwards of 2-3 minutes to run.
When I write the query directly in SQL, it runs in 1ms.
So, the query I write looks like :
SELECT *
FROM rubricCellAssessment
INNER JOIN rubricAssessment ON rubricCellAssessment.rubricAssessmentId = rubricAssessment.id
INNER JOIN rubricCell ON rubricCellAssessment.rubricCellId = rubricCell.id
INNER JOIN criteriaDescriptor ON rubricCell.criteriaDescriptorId = criteriaDescriptor.id
INNER JOIN criteria ON criteriaDescriptor.criteriaId = criteria.id
INNER JOIN skill ON criteria.skillId = skill.id
INNER JOIN user AS student ON rubricAssessment.studentId = student.id
INNER JOIN user AS assessor ON rubricAssessment.assessorId = assessor.id
LEFT JOIN studentContentBase ON rubricAssessment.studentContentBaseId = studentContentBase.id
WHERE student.userTypeId = 1
AND assessor.userTypeId IN (2, 1000, 3)
AND skill.id = 'bd47bfff-760c-4fec-86d2-1063bbd89d63'
AND criteriaDescriptor.criteriaId = criteria.id
AND rubricCell.criteriaDescriptorId = criteriaDescriptor.id;
The query prisma produces looks like this:
select
`lp-mvp`.`RubricCellAssessment`.`id`,
`lp-mvp`.`RubricCellAssessment`.`createdAt`,
`lp-mvp`.`RubricCellAssessment`.`updatedAt`,
`lp-mvp`.`RubricCellAssessment`.`assessmentValue`,
`lp-mvp`.`RubricCellAssessment`.`rubricCellId`,
`lp-mvp`.`RubricCellAssessment`.`rubricAssessmentId`
from
`lp-mvp`.`RubricCellAssessment`
where
((`lp-mvp`.`RubricCellAssessment`.`id`) in (
select
`t0`.`id`
from
`lp-mvp`.`RubricCellAssessment` as `t0`
inner join `lp-mvp`.`RubricAssessment` as `j0` on
(`j0`.`id`) = (`t0`.`rubricAssessmentId`)
where
((`j0`.`id`) in (
select
`t1`.`id`
from
`lp-mvp`.`RubricAssessment` as `t1`
inner join `lp-mvp`.`User` as `j1` on
(`j1`.`id`) = (`t1`.`studentId`)
where
(`j1`.`userTypeId` = 1
and `t1`.`id` is not null))
and `t0`.`id` is not null))
and (`lp-mvp`.`RubricCellAssessment`.`id`) in (
select
`t0`.`id`
from
`lp-mvp`.`RubricCellAssessment` as `t0`
inner join `lp-mvp`.`RubricCell` as `j0` on
(`j0`.`id`) = (`t0`.`rubricCellId`)
where
((`j0`.`id`) in (
select
`t1`.`id`
from
`lp-mvp`.`RubricCell` as `t1`
inner join `lp-mvp`.`CriteriaDescriptor` as `j1` on
(`j1`.`id`) = (`t1`.`criteriaDescriptorId`)
where
((`j1`.`id`) in (
select
`t2`.`id`
from
`lp-mvp`.`CriteriaDescriptor` as `t2`
inner join `lp-mvp`.`Criteria` as `j2` on
(`j2`.`id`) = (`t2`.`criteriaId`)
where
((`j2`.`id`) in (
select
`t3`.`id`
from
`lp-mvp`.`Criteria` as `t3`
inner join `lp-mvp`.`Skill` as `j3` on
(`j3`.`id`) = (`t3`.`skillId`)
where
(`j3`.`id` = "bd47bfff-760c-4fec-86d2-1063bbd89d63"
and `t3`.`id` is not null))
and `t2`.`id` is not null))
and `t1`.`id` is not null))
and `t0`.`id` is not null))
and (`lp-mvp`.`RubricCellAssessment`.`id`) in (
select
`t0`.`id`
from
`lp-mvp`.`RubricCellAssessment` as `t0`
inner join `lp-mvp`.`RubricAssessment` as `j0` on
(`j0`.`id`) = (`t0`.`rubricAssessmentId`)
where
((`j0`.`id`) in (
select
`t1`.`id`
from
`lp-mvp`.`RubricAssessment` as `t1`
inner join `lp-mvp`.`User` as `j1` on
(`j1`.`id`) = (`t1`.`assessorId`)
where
(`j1`.`userTypeId` in (2,1000,3)
and `t1`.`id` is not null))
and `t0`.`id` is not null))
and (`lp-mvp`.`RubricCellAssessment`.`id`) in (
select
`t0`.`id`
from
`lp-mvp`.`RubricCellAssessment` as `t0`
inner join `lp-mvp`.`RubricCell` as `j0` on
(`j0`.`id`) = (`t0`.`rubricCellId`)
where
((`j0`.`id`) in (
select
`t1`.`id`
from
`lp-mvp`.`RubricCell` as `t1`
inner join `lp-mvp`.`CriteriaDescriptor` as `j1` on
(`j1`.`id`) = (`t1`.`criteriaDescriptorId`)
where
((`j1`.`id`) in (
select
`t2`.`id`
from
`lp-mvp`.`CriteriaDescriptor` as `t2`
inner join `lp-mvp`.`Criteria` as `j2` on
(`j2`.`id`) = (`t2`.`criteriaId`)
where
((`j2`.`id`) in (
select
`t3`.`id`
from
`lp-mvp`.`Criteria` as `t3`
inner join `lp-mvp`.`Skill` as `j3` on
(`j3`.`id`) = (`t3`.`skillId`)
where
(`j3`.`id` = "bd47bfff-760c-4fec-86d2-1063bbd89d63"
and `t3`.`id` is not null))
and `t2`.`id` is not null))
and `t1`.`id` is not null))
and `t0`.`id` is not null)))
Is there any way to optimize this (other than use RAWsql?)? I'm surprised Prisma's code generation is this bad, but I'd rather not move away from it at this point if possible.
All help gratefully accepted.

Syntax Error: Lateral Join with Delete (PostgreSQL)

PostgreSQL 11.1
AFAIK, this is correct and should run. It Fails with syntax error on Delete. What am I missing?
Thanks for any help.
ERROR: syntax error at or near "DELETE"
LINE 41: DELETE FROM d
WITH _in (tservice, patient_recid, disease_recid, new_disease_recid) AS (
VALUES ('2021-04-21'::timestamp, '23262'::integer, '34978'::integer, '33364'::integer)
)
UPDATE dx d
SET disease_recid = n.new_disease_recid
FROM _in n,
LATERAL ( WITH RECURSIVE readtoend AS(
SELECT recid, newrecid
FROM patients p1
JOIN _in n ON p1.recid = n.patient_recid
UNION
SELECT c.recid, c.newrecid
FROM patients c
INNER JOIN readtoend s ON s.newrecid = c.recid
),
readtostart AS(
SELECT recid, newrecid
FROM patients p1
JOIN _in n ON p1.recid = n.patient_recid
UNION
SELECT c.recid, c.newrecid
FROM patients c
INNER JOIN readtostart s ON s.recid = c.newrecid
)
SELECT recid FROM readtoend
UNION
SELECT recid FROM readtostart
) j,
LATERAL ( WITH _get_existing_target AS(
SELECT d.*
FROM d
WHERE (d.patient_recid, d.disease_recid) = (j.recid, n.new_disease_recid) AND d.tservice <= n.tservice
),
_get_conflicts AS(
SELECT d.*
FROM d
WHERE (d.patient_recid, d.disease_recid) = (j.recid, n.disease_recid) AND EXISTS ( SELECT 1
FROM _get_existing_target x
WHERE d.patient_recid = x.patient_recid AND d.tservice::date = x.tservice::date)
)
DELETE FROM d
USING _get_conflicts f
WHERE d.recid = f.recid
RETURNING d.*
) del
WHERE (d.patient_recid, d.disease_recid) = (j.recid, n.disease_recid) AND d.tservice::date <= n.tservice::date
AND d.recid NOT IN ( SELECT recid FROM del);
You cannot use DELETE ... RETURNING in the FROM list of a query.

Postgres “missing FROM-clause entry” error on distinct select query

Below error is generated while creating a inner join on 2 tables in PostgreSQL with distinct clause.Here is my query :
select distinct public."firstapp_offer_Vendor".user_id from
(SELECT
public.firstapp_bid.id,
public.firstapp_bid."Bid",
public.firstapp_bid.offer_id,
public."firstapp_offer_Vendor".user_id,
public."firstapp_offer_Vendor".offer_id
FROM
public.firstapp_bid
inner JOIN public."firstapp_offer_Vendor"
ON public."firstapp_offer_Vendor".offer_id = public.firstapp_bid.offer_id) as foo;
but as i execute it,this error is generated.Please help.
ERROR: syntax error at or near "."
LINE 11: ...r".offer_id = public.firstapp_bid.offer_id) public."firstapp...
try this
select distinct user_id from
(SELECT
fb.id,
fb.Bid,
fb.offer_id,
fov.user_id,
fov.offer_id
FROM
public.firstapp_bid as fb
inner JOIN public.firstapp_offer_Vendor as fov
ON fov.offer_id = fb.offer_id) as foo;

Strange Behaviour on Postgresql query

We created a view in Postgres and I am getting strange result.
View Name: event_puchase_product_overview
When I try to get records with *, I get the correct result. but when I try to get specific fields, I get wrong values.
I hope the screens attached here can explain the problem well.
select *
from event_purchase_product_overview
where id = 15065;
select id, departure_id
from event_puchase_product_overview
where id = 15065;
VIEW definition:
CREATE OR REPLACE VIEW public.event_puchase_product_overview AS
SELECT row_number() OVER () AS id,
e.id AS departure_id,
e.type AS event_type,
e.name,
p.id AS product_id,
pc.name AS product_type,
product_date.attribute AS option,
p.upcomming_date AS supply_date,
pr.date_end AS bid_deadline,
CASE
WHEN (pt.categ_id IN ( SELECT unnest(tt.category_ids) AS unnest
FROM ( SELECT string_to_array(btrim(ir_config_parameter.value, '[]'::text), ', '::text)::integer[] AS category_ids
FROM ir_config_parameter
WHERE ir_config_parameter.key::text = 'trip_product_flight.product_category_hotel'::text) tt)) THEN e.maximum_rooms
WHEN (pt.categ_id IN ( SELECT unnest(tt.category_ids) AS unnest
FROM ( SELECT string_to_array(btrim(ir_config_parameter.value, '[]'::text), ', '::text)::integer[] AS category_ids
FROM ir_config_parameter
WHERE ir_config_parameter.key::text = 'trip_product_flight.product_category_flight'::text) tt)) THEN e.maximum_seats
WHEN (pt.categ_id IN ( SELECT unnest(tt.category_ids) AS unnest
FROM ( SELECT string_to_array(btrim(ir_config_parameter.value, '[]'::text), ', '::text)::integer[] AS category_ids
FROM ir_config_parameter
WHERE ir_config_parameter.key::text = 'trip_product_flight.product_category_bike'::text) tt)) THEN e.maximum_bikes
ELSE e.maximum_seats
END AS departure_qty,
CASE
WHEN now()::date > pr.date_end AND po.state::text = 'draft'::text THEN true
ELSE false
END AS is_deadline,
pl.product_qty::integer AS purchased_qty,
pl.comments,
pl.price_unit AS unit_price,
rp.id AS supplier,
po.id AS po_ref,
po.state AS po_state,
po.date_order AS po_date,
po.user_id AS operator,
pl.po_state_line AS line_status
FROM event_event e
LEFT JOIN product_product p ON p.related_departure = e.id
LEFT JOIN product_template pt ON pt.id = p.product_tmpl_id
LEFT JOIN product_category pc ON pc.id = pt.categ_id
LEFT JOIN purchase_order_line pl ON pl.product_id = p.id
LEFT JOIN purchase_order po ON po.id = pl.order_id
LEFT JOIN purchase_order_purchase_requisition_rel prr ON prr.purchase_order_id = po.id
LEFT JOIN purchase_requisition pr ON pr.id = prr.purchase_requisition_id
LEFT JOIN res_partner rp ON rp.id = po.partner_id
LEFT JOIN ( SELECT p_1.id AS product_id,
pav.name AS attribute
FROM product_product p_1
LEFT JOIN product_attribute_value_product_product_rel pa ON pa.prod_id = p_1.id
LEFT JOIN product_attribute_value pav ON pav.id = pa.att_id
LEFT JOIN product_attribute pat ON pat.id = pav.attribute_id
WHERE pat.name::text <> ALL (ARRAY['Date'::character varying, 'Departure'::character varying]::text[])) product_date ON product_date.product_id = p.id
WHERE (p.id IN ( SELECT DISTINCT mrp_bom_line.product_id
FROM mrp_bom_line)) AND p.active
ORDER BY e.id, pt.categ_id, p.id;
If I add new event_event or new product_product I'll get a new definition of row_number in my view, then the column ID of my view is not stable.
at least you can't use row_number as Id of the view,
If you insist to use row_number, you can use the Order By "creation DATE" by this way all new records will be as last lines in the view and this will not change the correspondency between ID (row_number) and other columns.
Hope that helps !
Very likely the execution plan of your query depends on the columns you select. Compare the execution plans!
Your id is generated using the row_number window function. Now window functions are executed before the ORDER BY clause, so the order will depend on the execution plan and hence on the columns you select.
Using row_number without an explicit ordering doesn't make any sense.
To fix that, don't use
row_number() OVER ()
but
row_number() OVER (ORDER BY e.id, pt.categ_id, p.id)
so that you have a reliable ordering.
In addition, you should omit the ORDER BY clause at the end.

Lateral query syntax

I'm trying to get lateral to work in a Postgres 9.5.3 query.
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id",
lateral (select ci."MaximumPlaces" - "EnrolledStudents") x
I want the right-most column to be the result of "MaximumPlaces" - "EnrolledStudents" for that row but am struggling to get it to work. At the moment PG is complaining that "EnrolledStudents" does not exist - which is exactly the point of "lateral", isn't it?
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
lateral (select "MaximumPlaces" - "EnrolledStudents") as "x"
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
If I try inlining the lateral clause (shown above) in the select it gets upset too and gives me a syntax error - so where does it go?
Thanks,
Adam.
You are missing the point with LATERAL. It can access columns in tables in the FROM clause, but not aliases defined in SELECT clause.
If you want to access alias defined in SELECT clause, you need to add another query level, either using a subquery in FROM clause (AKA derived table) or using a CTE (Common Table Expression). As CTE in PostgreSQL acts as an optimization fence, I strongly recommend going with subquery in this case, like:
select
-- get all columns on the inner query
t.*,
-- get your new expression based on the ones defined in the inner query
t."MaximumPlaces" - t."EnrolledStudents" AS new_alias
from (
select b_ci."IdOwner",
ci."MinimumPlaces",
ci."MaximumPlaces",
(select count(*) from "LNK_Stu_CI" lnk
where lnk."FK_CourseInstanceId" = b_ci."Id") as "EnrolledStudents",
from "Course" c
join "DBObjectBases" b_c on c."Id" = b_c."Id"
join "DBObjectBases" b_ci on b_ci."IdOwner" = b_c."Id"
join "CourseInstance" ci on ci."Id" = b_ci."Id"
) t