How to include a JOIN after the WHERE? - sql

I need to execute a statement that follows a given Prefix.
We use a certain program, it features a 'Search Folder'. Into the Search folder, I can define an SQL query. The Folder has a built-in part of the query, which I can not modify.
The built-in part is:
Prefix Artikelfilter: SELECT * FROM CMKAT.ART WHERE 1=1 AND
Now I would like to perform the following search query:
select * from CMKAT.ART
join CMKAT.AEZ on art.artKEYI = aez.aezartkeyi
join pro on pro.prokeyi = aez.aezprokeyi
left outer join psz on pro.prokeyi = psz.pszprokeyi
WHERE psz.pszprokeyi is null
AND pro.proetykeyi = 1;
Of course, the 'SELECT *...' part is redundant, but how can I get the query to work? The JOINs are after the WHERE.
I know the developers solved this issues by creating Views, and making the selection from the view, not directly in the query.
Edit:
Exception: JdbcAccess.execute failed (ORA-00904: "KVTBEZC": ungültige ID
).
SQL:
<prefix>
SELECT /* filter art */ artkeyi, artkavkeyi, artvnrs FROM art JOIN
kav ON art.artkavkeyi = kav.kavkeyi JOIN kvt ON kav.kavkvtkeyi =
kvt.kvtkeyi JOIN kat ON kav.kavkatkeyi = kat.katkeyi WHERE
(artkavkeyi IN (587, 3075, 7, 8, 592)) AND
</prefix>
1 = 0 union all select *
from cmkat.art join cmkat.aez on art.artkeyi = aez.aezartkeyi join
pro on pro.prokeyi = aez.aezprokeyi left join psz on pro.prokeyi =
psz.pszprokeyi where psz.pszprokeyi is null and pro.proetykeyi = 1
AND katkeyi = 4 AND (katspes IN (0, 3, 1, 2))/* join-dummy */ ORDER BY
artkeyi, kvtbezc (DATABASE_EXECUTE_FAILED)

I guess you need right query like this:
If exists (SELECT 1 FROM CMKAT.ART WHERE 1=1)
Begin
(
Select *
From CMKAT.ART
Inner join CMKAT.AEZ on art.artKEYI = aez.aezartkeyi
Inner join pro on pro.prokeyi = aez.aezprokeyi
Left Outer join psz on pro.prokeyi = psz.pszprokeyi
WHERE psz.pszprokeyi is null AND pro.proetykeyi = 1;
)
END

I'd construct the SQL this way:
SELECT *
FROM CMKAT.ART
WHERE 1=1 AND EXISTS (Select 1
From CMKAT.AEZ, pro
left outer join psz on pro.prokeyi = psz.pszprokeyi
Where aez.aezartkeyi = art.artKEYI and pro.prokeyi = aez.aezprokeyi and psz.pszprokeyi is null AND pro.proetykeyi = 1
);

I don't know if your tool allows such construction, but you could cheat it using union all:
select * from cmkat.art where 1 = 1 and 1 = 0
union all
select cmkat.art.*
from cmkat.art
join cmkat.aez on art.artkeyi = aez.aezartkeyi
join pro on pro.prokeyi = aez.aezprokeyi
left join psz on pro.prokeyi = psz.pszprokeyi
where psz.pszprokeyi is null and pro.proetykeyi = 1;
First line removes data of original query because of 1 = 0 condition so we get only data from second part of union.
Unfortunately you can obtain only columns of art table because your tool does not allow to change selected data. But you can change it selecting some columns from joined tables instead of art columns.

Related

Rewrite union query to a single query

I wondered if it was possible to write this as one query:
SELECT * FROM
(SELECT "markets".*
FROM "markets"
INNER JOIN "positions" ON "positions"."id" = "markets"."position_id"
INNER JOIN "players" ON "players"."id" = "positions"."player_id"
INNER JOIN "other_players" ON "other_players"."id" = "players"."other_player_id"
WHERE (markets.updated_at > '2021-01-10 11:50:14.136015')
AND "markets"."on_feed" = true
AND "markets"."deleted_at" IS NULL
UNION
SELECT "markets".*
FROM "markets"
WHERE (markets.updated_at > '2021-01-10 11:50:14.136015')
AND "markets"."on_feed" = true
AND "markets"."deleted_at" IS NOT NULL) results
ORDER BY results.updated_at DESC
There's a lot of overlap in the two queries. In the first one we want all markets that have those associations in place. For the 2nd query we don't really care if the associations are there or not.
SELECT * FROM "markets"
LEFT JOIN "positions" ON "positions"."id" = "markets"."position_id"
LEFT JOIN "players" ON "players"."id" = "positions"."player_id"
LEFT JOIN "other_players" ON "other_players"."id" = "players"."other_player_id"
WHERE markets.updated_at > '2021-01-10 11:50:14.136015'
AND "markets"."on_feed" = true
AND ("markets"."deleted_at" IS NOT NULL
OR "positions"."id" IS NOT NULL AND "players"."id" IS NOT NULL
AND "other_players"."id" IS NOT NULL)
ORDER BY markets.updated_at DESC
Use EXISTS instead:
SELECT m.*
FROM "markets" m
WHERE m.updated_at > '2021-01-10 11:50:14.136015' AND
markets."on_feed" = true AND
(m."deleted_at" IS NOT NULL OR
EXISTS (SELECT 1
FROM "positions" p JOIN
"players" pl
ON pl."id" = p."player_id" JOIN
"other_players" op
ON op."id" = p."other_player_id"
WHERE p."id" = m."position_id"
)
)
ORDER BY m.updated_at DESC

Big Query : LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join

I am writing an equivalent logic in BQ as in my source system. In source SQL server side it is working fine. But in Big query it is failing with the OR condition in the last left outer join condition. If I am moving the OR condition in the where clause it is giving wrong count. Need help to fix this issue. How can I re write the below query ?
SELECT count(*)
FROM stprof PRO
INNER JOIN stdim DIM
ON (DIM.diSet = PRO.diSet)
INNER JOIN DQConfig CFG
ON (CFG.ConSet = PRO.ConSet)
LEFT OUTER JOIN AgSt CCT
ON (CCT.StSet = PRO.StSet)
INNER JOIN stprof SummPRO
ON (SummPRO.diSet = DIM.SummdiSet AND
SummPRO.dIntervalStart = PRO.dIntervalStart AND
SummPRO.SiteId = PRO.SiteId AND
SummPRO.nDuration = PRO.nDuration)
LEFT OUTER JOIN AgSt SummCCT
ON (SummCCT.StSet = SummPRO.StSet)
LEFT OUTER JOIN AgentStatus SummSTS
ON (
SummSTS.StSet = SummPRO.StSet
OR
SummSTS.StSet = PRO.StSet)
WHERE DIM.cType = 'A'
You can replace LEFT JOIN with CROSS JOIN and move condition from ON clause to WHERE clause as in below example
#standardSQL
SELECT COUNT(*)
FROM stprof PRO
INNER JOIN stdim DIM
ON DIM.diSet = PRO.diSet
INNER JOIN DQConfig CFG
ON CFG.ConSet = PRO.ConSet
LEFT OUTER JOIN AgSt CCT
ON CCT.StSet = PRO.StSet
INNER JOIN stprof SummPRO
ON SummPRO.diSet = DIM.SummdiSet
AND SummPRO.dIntervalStart = PRO.dIntervalStart
AND SummPRO.SiteId = PRO.SiteId
AND SummPRO.nDuration = PRO.nDuration
LEFT OUTER JOIN AgSt SummCCT
ON SummCCT.StSet = SummPRO.StSet
CROSS JOIN AgentStatus SummSTS
WHERE DIM.cType = 'A'
AND (
SummSTS.StSet = SummPRO.StSet
OR SummSTS.StSet = PRO.StSet
)

Single-row subquery returns more than one row - Case statement

My following code returns the error stated in the title, however the error does not show when the case statement is ran by itself.
I've tried to dismantle the case statement, however this isn't my query but IS being used elsewhere, i'm wondering how they manage to get it to return rows in its current state.
SELECT DISTINCT V55."INPUTSPECNAME",
V55."FKMATERIAL",
V55."INPUTQUANTITYVALUE",
B.ABBREVIATION,
(CASE
WHEN z.COST IS NULL
THEN (SELECT DISTINCT (CASE
WHEN MatOut_D.PERVALUEQUANTITY > 0 THEN
ROUND(MatOut_D.PRICE /
MatOut_D.PERVALUEQUANTITY /
10 /
MatOut_E.USDCONVERSIONFACTOR *
C.USDCONVERSIONFACTOR, 5)
ELSE 0
END)
FROM V55_FORMULATIONJOINMATOUTPUT MatOut_B,
V55_FORMULATIONINPUTOUTPUT MatOut_C,
THEORETICALCOSTS MatOut_D,
COMMONCURRENCIES MatOut_E,
UOMML MatOut_F
WHERE MatOut_B.FKREFERENCEDMATERIAL = V55.FKMATERIAL
AND MatOut_B.FKOWNER = MatOut_C.FKOWNER
AND MatOut_C.FORMULATIONOUTPUTPKID = MatOut_D.FKPARENT
AND MatOut_D.FKCURRENCY = MatOut_E.PKID
AND MatOut_D.FKPERVALUEUOM = MatOut_F.FKUOM
AND MatOut_F.LANGID = 0)
ELSE ROUND(z.COST*100/D.USDCONVERSIONFACTOR*C.USDCONVERSIONFACTOR,5)
END) AS COST_100G
FROM V55_FORMULATIONINPUTOUTPUT V55
INNER JOIN UOM A
on V55.FKINPUTUOM = A.PKID
INNER JOIN UOMML B
on a.pkid = B.FKUOM
INNER JOIN DWBSpecificationRoots dwbRoot
on dwbRoot.fkOwner = V55.FKOWNER
INNER JOIN dwbSpecifications dwbSpec
ON dwbSpec.fkWorkingVersionParent = dwbRoot.pkid
LEFT OUTER JOIN specLegacySpecJoin y
on dwbSpec.fkdisplayedlegacyprofile = y.fklegacyprofileid
and y.fkspecid = V55.fkMaterial
LEFT OUTER join COSTITEMS z
on z.equivalent = y.equivalent
and z.fklegacyprofile = dwbSpec.fkdisplayedlegacyprofile
and z.FKSCRMENTITY = dwbSpec.FKSCRMSUPPLIERBASE
and z.COSTTYPE = dwbSpec.COSTTYPE
LEFT OUTER JOIN COMMONCURRENCIES C
ON C.PKID = dwbSpec.FKCURRENCY
LEFT OUTER JOIN COMMONCURRENCIES D
ON D.PKID = Z.FKCURRENCY
The problem is that the subquery in your CASE statement is returning multiple rows in some situations and as has been stated in the question's comments that's a no-no.
I suggest that you pull the subquery out of the CASE statement and make it a Common Table Expression, then join it into the query as you would any other table:
WITH cteSubexpr AS (SELECT DISTINCT MatOut_B.FKREFERENCEDMATERIAL,
(CASE
WHEN MatOut_D.PERVALUEQUANTITY > 0 THEN
ROUND(MatOut_D.PRICE /
MatOut_D.PERVALUEQUANTITY /
10 /
MatOut_E.USDCONVERSIONFACTOR *
C.USDCONVERSIONFACTOR, 5)
ELSE 0
END) AS CALC_QTY
FROM V55_FORMULATIONJOINMATOUTPUT MatOut_B
INNER JOIN V55_FORMULATIONINPUTOUTPUT MatOut_C
ON MatOut_C.FKOWNER = MatOut_B.FKOWNER
INNER JOIN THEORETICALCOSTS MatOut_D
ON MatOut_D.FKPARENT = MatOut_C.FORMULATIONOUTPUTPKID
INNER JOIN COMMONCURRENCIES MatOut_E
ON MatOut_E.PKID = MatOut_D.FKCURRENCY
INNER JOIN UOMML MatOut_F
ON MatOut_F.FKUOM = MatOut_D.FKPERVALUEUOM
WHERE MatOut_F.LANGID = 0)
SELECT DISTINCT V55.INPUTSPECNAME,
V55.FKMATERIAL,
V55.INPUTQUANTITYVALUE,
B.ABBREVIATION,
(CASE
WHEN z.COST IS NULL
THEN cs.CALC_QTY
ELSE ROUND(z.COST * 100 / D.USDCONVERSIONFACTOR * C.USDCONVERSIONFACTOR, 5)
END) AS COST_100G
FROM V55_FORMULATIONINPUTOUTPUT V55
INNER JOIN cteSubexpr cs
ON cs.FKREFERENCEDMATERIAL = V55.FKMATERIAL
INNER JOIN UOM A
on V55.FKINPUTUOM = A.PKID
INNER JOIN UOMML B
on a.pkid = B.FKUOM
INNER JOIN DWBSpecificationRoots dwbRoot
on dwbRoot.fkOwner = V55.FKOWNER
INNER JOIN dwbSpecifications dwbSpec
ON dwbSpec.fkWorkingVersionParent = dwbRoot.pkid
LEFT OUTER JOIN specLegacySpecJoin y
on dwbSpec.fkdisplayedlegacyprofile = y.fklegacyprofileid
and y.fkspecid = V55.fkMaterial
LEFT OUTER join COSTITEMS z
on z.equivalent = y.equivalent
and z.fklegacyprofile = dwbSpec.fkdisplayedlegacyprofile
and z.FKSCRMENTITY = dwbSpec.FKSCRMSUPPLIERBASE
and z.COSTTYPE = dwbSpec.COSTTYPE
LEFT OUTER JOIN COMMONCURRENCIES C
ON C.PKID = dwbSpec.FKCURRENCY
LEFT OUTER JOIN COMMONCURRENCIES D
ON D.PKID = Z.FKCURRENCY
Best of luck.

Join two select queries horizontally in Postgresql

I have following two queries:
Query #1:
(SELECT
pl.c_project_Id, pl.c_projectphase_Id, pl.c_projecttask_Id, pl.m_product_Id,
pj.name as projectname, ph.name as phasename, pt.name as taskname, pd.name as prodname,
round(pl.plannedqty, 2) as planqty, round(pl.plannedprice, 2) as planrate,
round(pl.plannedamt, 2) as planamt
FROM adempiere.c_projectline pl
LEFT JOIN adempiere.c_project pj ON pl.c_project_id = pj.c_project_id
LEFT JOIN adempiere.c_projectphase ph ON pl.c_projectphase_id = ph.c_projectphase_id
LEFT JOIN adempiere.c_projecttask pt ON pl.c_projecttask_id = pt.c_projecttask_id
LEFT JOIN adempiere.m_product pd ON pl.m_product_id = pd.m_product_id
WHERE pl.c_project_id = 1000001 AND pl.ad_client_id = 1000000
ORDER BY ph.c_projectphase_id, pt.c_projecttask_id)
Output is: 11 columns and 16 rows
Query #2:
(SELECT
fa.c_project_id, fa.c_projectphase_id, fa.c_projecttask_id, fa.m_product_id,
pj.name as costprojectname, ph.name as costphasename, pt.name as costtaskname,
pd.name as costprodname,
abs(fa.qty) as costqty, round((fa.amtacctdr/fa.qty), 2) as costrate,
round(sum(fa.amtacctdr), 0) as costamt
FROM adempiere.fact_acct fa
LEFT JOIN adempiere.c_project pj ON fa.c_project_id = pj.c_project_id
LEFT JOIN adempiere.c_projectphase ph ON fa.c_projectphase_id = ph.c_projectphase_id
LEFT JOIN adempiere.c_projecttask pt ON fa.c_projecttask_id = pt.c_projecttask_id
LEFT JOIN adempiere.m_product pd ON fa.m_product_id = pd.m_product_id
WHERE fa.c_project_id = 1000001 AND (fa.gl_category_id = 1000006 OR fa.gl_category_id = 1000005)
AND fa.qty > 0 AND fa.c_project_id is not null
GROUP BY fa.m_product_id, fa.c_project_id, fa.c_projectphase_id, fa.c_projecttask_id,
fa.qty, fa.amtacctdr,
pj.name, ph.name, pt.name, pd.name)
Output is: 11 columns and 6 rows
I want to join these queries horizontally, display all columns but rows should not duplicate. As when I apply union to join them the result shows duplicate rows. How can I cope with this issue?
You should be able to join queries like this:
select * from
(
<your first query here>
) tbl1
join (
<your second query here>
) tbl2
on tbl1.c_project_Id = tbl2.c_project_Id
and tbl1.c_projectphase_Id = tbl2.c_projectphase_Id -- you might add or
and tbl1.c_projecttask_Id = tbl2.c_projecttask_Id -- remove join criteria
and tbl1.m_product_Id = tbl2.m_product_Id -- here

How to Select NOT IN Value (Formula Crystal Reports)

I have this query in SQL server:
select * from ARInvoices ar
left join ARInvoiceDetails det on ar.InvoiceID = det.InvoiceID
where ar.InvoiceID not in (select InvoiceID from CashReceiptInvoices )
and det.SubmitTo = 1 and VoucherStatus = 0 and det.TransactionType = 1
I would like to have it thru a Formula in Crystal Reports XI but i'm having a hard time with the not in. I used <> but the results are coming empty.
I don't know crystal reports at all, but if it's only the NOT IN you're having trouble with, but your LEFT JOIN works fine, then you could just add another LEFT JOIN:
select *
from ARInvoices ar
left join ARInvoiceDetails det on ar.InvoiceID = det.InvoiceID
left join CashReceiptInvoices cri on ar.InvoiceID = cri.InvoiceID
where cri.InvoiceID IS NULL
and det.SubmitTo = 1
and VoucherStatus = 0
and det.TransactionType = 1
You could eliminate the NOT IN by using an "anti-join" (a LEFT JOIN with a constraint where the column in the table to which you are joining IS NULL):
select * from ARInvoices ar
left join ARInvoiceDetails det on ar.InvoiceID = det.InvoiceID
left join CashReceiptInvoices cri on ar.InvoiceID = cri.InvoiceID -- new JOIN
where cri.InvoiceID is null -- no match
and det.SubmitTo = 1 and VoucherStatus = 0 and det.TransactionType = 1