Get all parents for a child in postgresql - sql

I have been runed success On SQL Server. My System run on SQL Server and postgresql.
But when I change from SQL Server to postgresql it running fail.
My sql like this:
with name_tree as
(
SELECT DepartNo, ParentNo FROM Departments
WHERE DepartNo IN (
SELECT DepartNo FROM BelongToDepartment
WHERE UserNo = 1)
union all
select C.DepartNo, C.ParentNo
from Departments c
join name_tree p on C.DepartNo = P.ParentNo
AND C.DepartNo<>C.ParentNo
)
select * from name_tree
The error is:
name_tree doesn't exist
How can get all parents for a child in postgresql
More detail in MSQ Server here

Try:
with RECURSIVE name_tree as
(
SELECT DepartNo, ParentNo FROM Departments
WHERE DepartNo IN (
SELECT DepartNo FROM BelongToDepartment
WHERE UserNo = 1)
union all
select C.DepartNo, C.ParentNo
from Departments c
join name_tree p on C.DepartNo = P.ParentNo
AND C.DepartNo<>C.ParentNo
)
select * from name_tree

Related

Re-writting the query without "Connect By "

I am rewriting the query to replace to remove CONNECT BY:
SELECT *
FROM ADM_TRT AT
INNER JOIN UTILISATEUR U
ON U.UTI_ID = AT.UTI_ID
INNER JOIN
(
SELECT CM.MAI_ID
FROM CON_MAI CM
CONNECT BY CM.MAI_PER_RES = PRIOR CM.MAI_ID
START WITH CM.MAI_ID IN (
SELECT MAJ_ID
FROM DROIT_LOGIN
WHERE LOG_ID = 21543
)
) CON_MAI_FILTERED_ON_LOGIN
ON AT.TRT_MAI_ID = CON_MAI_FILTERED_ON_LOGIN.MAI_ID;
For CONNECT BY Part , I wrote this
WITH tree (MAI_ID,MAI_PER_RES, level1) AS (
SELECT MAI_PER_RES, MAI_ID, 1 as level1 FROM CON_MAI
UNION ALL
SELECT child.MAI_ID, child.MAI_PER_RES, parent.level1 + 1
FROM CON_MAI child --Line 20
JOIN tree parent
on parent.MAI_PER_RES = child.MAI_ID
)
SELECT MAI_ID FROM tree
But I am stuck to integrate this in subquery in the CONNECT BY sub-query. Can someone please help to integrate this?
It looks like you have the recursion reversed in the recursive sub-query and can use:
WITH tree (MAI_ID) AS (
SELECT MAI_ID
FROM CON_MAI
WHERE MAI_ID IN ( SELECT MAJ_ID
FROM DROIT_LOGIN
WHERE LOG_ID = 21543 )
UNION ALL
SELECT c.MAI_ID
FROM CON_MAI c
JOIN tree p
on c.MAI_PER_RES = p.MAI_ID
)
SELECT *
FROM ADM_TRT AT
INNER JOIN UTILISATEUR U
ON U.UTI_ID = AT.UTI_ID
INNER JOIN tree CON_MAI_FILTERED_ON_LOGIN
ON AT.TRT_MAI_ID = CON_MAI_FILTERED_ON_LOGIN.MAI_ID;
(untested as I do not have your tables or data)

Capturing level in multilevel BOM sql query

I have the following query to capture a multi-level BOM. I now know all the child items for the parent but is there a way to capture the level as well in this query.
with mlBOM
AS (
select bom_item_material_number, bom_item_component
from BOM_TABLE bom
where not exists (
select *
from BOM_TABLE BOM inner join
BOM_TABLE BOM1
on BOM1.bom_item_component = BOM.bom_item_material_number
)
union all
select BOM.bom_item_material_number,
BOM.bom_item_component
from BOM_TABLE BOM
inner join BOM_TABLE mlBOM on mlBOM.bom_item_component = BOM.bom_item_material_number
) select *
from mlBOM
;
Thanks,
Running on DBeaver Postgressql database
You add an integer column that starts at 1 and increment it for each iteration:
with recursive mlbom as (
select bom_item_material_number, bom_item_component, 1 lvl
from bom_table bom
where not exists (
select 1
from bom_table bom1
where bom1.bom_item_component = bom.bom_item_material_number
)
union all
select bom.bom_item_material_number, bom.bom_item_component, mlbom.lvl + 1
from bom_table bom
inner join mlbom on mlbom.bom_item_component = bom.bom_item_material_number
)
select * from mlbom ;
I made a few fixes to the query:
the cte declaration needs the recursive keyword
there is no need to join in the exists subquery of the anchor of the recusive query
presumably, the recursive part of the query oughts to join bom to mlbom instead of self-joining bom.

Unable to convert this legacy SQL into Standard SQL in Google BigQuery

I am not able to validate this legacy sql into standard bigquery sql as I don't know what else is required to change here(This query fails during validation if I choose standard SQL as big query dialect):
SELECT
lineitem.*,
proposal_lineitem.*,
porder.*,
company.*,
product.*,
proposal.*,
trafficker.name,
salesperson.name,
rate_card.*
FROM (
SELECT
*
FROM
dfp_data.dfp_order_lineitem
WHERE
DATE(end_datetime) >= DATE(DATE_ADD(CURRENT_TIMESTAMP(), -1, 'YEAR'))
OR end_datetime IS NULL ) lineitem
JOIN (
SELECT
*
FROM
dfp_data.dfp_order) porder
ON
lineitem.order_id = porder.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_proposal_lineitem) proposal_lineitem
ON
lineitem.id = proposal_lineitem.dfp_lineitem_id
JOIN (
SELECT
*
FROM
dfp_data.dfp_company) company
ON
porder.advertiser_id = company.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_product) product
ON
proposal_lineitem.product_id=product.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_proposal) proposal
ON
proposal_lineitem.proposal_id=proposal.id
LEFT JOIN (
SELECT
*
FROM
adpoint_data.dfp_rate_card) rate_card
ON
proposal_lineitem.ratecard_id=rate_card.id
LEFT JOIN (
SELECT
id,
name
FROM
dfp_data.dfp_user) trafficker
ON
porder.trafficker_id =trafficker.id
LEFT JOIN (
SELECT
id,
name
FROM
dfp_data.dfp_user) salesperson
ON
porder. salesperson_id =salesperson.id
Most likely the error you are getting is something like below
Duplicate column names in the result are not supported. Found duplicate(s): name
Legacy SQL adjust trafficker.name and salesperson.name in your SELECT statement into respectively trafficker_name and salesperson_name thus effectively eliminating column names duplication
Standard SQL behaves differently and treat both those columns as named name thus producing duplication case. To avoid it - you just need to provide aliases as in example below
SELECT
lineitem.*,
proposal_lineitem.*,
porder.*,
company.*,
product.*,
proposal.*,
trafficker.name AS trafficker_name,
salesperson.name AS salesperson_name,
rate_card.*
FROM ( ...
You can easily check above explained using below simplified/dummy queries
#legacySQL
SELECT
porder.*,
trafficker.name,
salesperson.name
FROM (
SELECT 1 order_id, 'abc' order_name, 1 trafficker_id, 2 salesperson_id
) porder
LEFT JOIN (SELECT 1 id, 'trafficker' name) trafficker
ON porder.trafficker_id =trafficker.id
LEFT JOIN (SELECT 2 id, 'salesperson' name ) salesperson
ON porder. salesperson_id =salesperson.id
and
#standardSQL
SELECT
porder.*,
trafficker.name AS trafficker_name,
salesperson.name AS salesperson_name
FROM (
SELECT 1 order_id, 'abc' order_name, 1 trafficker_id, 2 salesperson_id
) porder
LEFT JOIN (SELECT 1 id, 'trafficker' name) trafficker
ON porder.trafficker_id =trafficker.id
LEFT JOIN (SELECT 2 id, 'salesperson' name ) salesperson
ON porder. salesperson_id =salesperson.id
Note: if you have more duplicate names - you need to alias all of them too

SQL hide rows specifically

This is my table structure and sample rows:
And I have a SQL query like this :
WITH Test(ObjId, ObjectIcerik, KeyMi) AS
(
SELECT
ObjId, ObjectIcerik, KeyMi
FROM
Tek
WHERE
ObjId = 8
UNION ALL
SELECT
T.ObjId, T.ObjectIcerik, T.KeyMi
FROM
Tek T
INNER JOIN
Test as TE ON T.ObjParent = TE.ObjId
)
SELECT *
FROM Test
This is the result :
But I also need to hide parent and child rows if parent's KeyMi column is '1'.
What do I need to change in the SQL query to do this?
You should be able to just add the condition to the recursive CTE:
WITH Test(ObjId, ObjectIcerik, KeyMi) AS (
SELECT ObjId, ObjectIcerik, KeyMi FROM Tek
WHERE ObjId = 8 AND (KeyMI <> 1 OR KeyMI IS NULL)
UNION ALL
SELECT T.ObjId, T.ObjectIcerik, T.KeyMi
FROM Tek T INNER JOIN
Test TE
ON T.ObjParent = TE.ObjId
WHERE (t.KeyMI <> 1 OR t.KeyMI IS NULL)
)
SELECT *
FROM Test ;

PostgreSQL - how to query "result IN ALL OF"?

I am new to PostgreSQL and I have a problem with the following query:
WITH relevant_einsatz AS (
SELECT einsatz.fahrzeug,einsatz.mannschaft
FROM einsatz
INNER JOIN bergefahrzeug ON einsatz.fahrzeug = bergefahrzeug.id
),
relevant_mannschaften AS (
SELECT DISTINCT relevant_einsatz.mannschaft
FROM relevant_einsatz
WHERE relevant_einsatz.fahrzeug IN (SELECT id FROM bergefahrzeug)
)
SELECT mannschaft.id,mannschaft.rufname,person.id,person.nachname
FROM mannschaft,person,relevant_mannschaften WHERE mannschaft.leiter = person.id AND relevant_mannschaften.mannschaft=mannschaft.id;
This query is working basically - but in "relevant_mannschaften" I am currently selecting each mannschaft, which has been to an relevant_einsatz with at least 1 bergefahrzeug.
Instead of this, I want to select into "relevant_mannschaften" each mannschaft, which has been to an relevant_einsatz WITH EACH from bergefahrzeug.
Does anybody know how to formulate this change?
The information you provide is rather rudimentary. But tuning into my mentalist skills, going out on a limb, I would guess this untangled version of the query does the job much faster:
SELECT m.id, m.rufname, p.id, p.nachname
FROM person p
JOIN mannschaft m ON m.leiter = p.id
JOIN (
SELECT e.mannschaft
FROM einsatz e
JOIN bergefahrzeug b ON b.id = e.fahrzeug -- may be redundant
GROUP BY e.mannschaft
HAVING count(DISTINCT e.fahrzeug)
= (SELECT count(*) FROM bergefahrzeug)
) e ON e.mannschaft = m.id
Explain:
In the subquery e I count how many DISTINCT mountain-vehicles (bergfahrzeug) have been used by a team (mannschaft) in all their deployments (einsatz): count(DISTINCT e.fahrzeug)
If that number matches the count in table bergfahrzeug: (SELECT count(*) FROM bergefahrzeug) - the team qualifies according to your description.
The rest of the query just fetches details from matching rows in mannschaft and person.
You don't need this line at all, if there are no other vehicles in play than bergfahrzeuge:
JOIN bergefahrzeug b ON b.id = e.fahrzeug
Basically, this is a special application of relational division. A lot more on the topic under this related question:
How to filter SQL results in a has-many-through relation
Do not know how to explain it, but here is an example how I solved this problem, just in case somebody has the some question one day.
WITH dfz AS (
SELECT DISTINCT fahrzeug,mannschaft FROM einsatz WHERE einsatz.fahrzeug IN (SELECT id FROM bergefahrzeug)
), abc AS (
SELECT DISTINCT mannschaft FROM dfz
), einsatzmannschaften AS (
SELECT abc.mannschaft FROM abc WHERE (SELECT sum(dfz.fahrzeug) FROM dfz WHERE dfz.mannschaft = abc.mannschaft) = (SELECT sum(bergefahrzeug.id) FROM bergefahrzeug)
)
SELECT mannschaft.id,mannschaft.rufname,person.id,person.nachname
FROM mannschaft,person,einsatzmannschaften WHERE mannschaft.leiter = person.id AND einsatzmannschaften.mannschaft=mannschaft.id;