Take query true when one clause is false - sql

This is my query
SELECT pl.NAME
,pl.id_product
,pl.link_rewrite
,i.id_image
,ar.id_auctions_rutcom
,ar.actual_bid_price
,ar.start_price
,ar.min_price
,ar.buy_now_price
,ar.finish_date
FROM ps_image i
,ps_auctions_rutcom ar
,ps_product_lang pl
WHERE ar.finish_date > '2013-07-26 11:18:15'
AND ar.start_date < '2013-07-26 11:18:15'
AND ar.active = 1
AND ar.finish = 0
AND pl.id_product = ar.id_product
AND i.id_product = ar.id_product
AND i.cover = 1
AND pl.id_lang = 6
I have problem when on table ps_image is no image where i.id_product = ar.id_product my query return false. How to change query to set true?

You should learn about JOIN. Google it.
Your query is equivalent to INNER JOIN:
SELECT
pl.name, pl.id_product, pl.link_rewrite, i.id_image, ar.id_auctions_rutcom,
ar.actual_bid_price, ar.start_price, ar.min_price, ar.buy_now_price, ar.finish_date
FROM ps_auctions_rutcom ar
INNER JOIN ps_product_lang pl
ON pl.id_product = ar.id_product
AND pl.id_lang = 6
INNER JOIN ps_image i
ON i.id_product = ar.id_product
AND i.cover = 1
WHERE ar.finish_date > '2013-07-26 11:18:15'
AND ar.start_date < '2013-07-26 11:18:15'
AND ar.active = 1
AND ar.finish = 0
With an INNER JOIN, if there is no matching row in the related table, the row is omitted from the result set.
Now, you should use an OUTER JOIN, in which case the row is still in the result set and the missing information is set to NULL.
SELECT
pl.name, pl.id_product, pl.link_rewrite, i.id_image, ar.id_auctions_rutcom,
ar.actual_bid_price, ar.start_price, ar.min_price, ar.buy_now_price, ar.finish_date
FROM ps_auctions_rutcom ar
INNER JOIN ps_product_lang pl
ON pl.id_product = ar.id_product
AND pl.id_lang = 6
LEFT OUTER JOIN ps_image i
ON i.id_product = ar.id_product
AND i.cover = 1
WHERE ar.finish_date > '2013-07-26 11:18:15'
AND ar.start_date < '2013-07-26 11:18:15'
AND ar.active = 1
AND ar.finish = 0

You can add in your query to make sure ps_image has not null
Where i.id_product IS NOT NULL

You should separate your joins from your filters, then use a left join to provide all the results
regardless of whether an image exists
FROM ps_auctions_rutcom ar
left join
ps_image i on i.id_product = ar.id_product
and i.cover = 1
left join
ps_product_lang pl on pl.id_product = ar.id_product
and pl.id_lang = 6
WHERE ....

Related

SQL Two result from one column in 2 columns

i have checked some similar issues in the forum but i can't seems to get it to work properly.
i'm on phpmyadmin
i need to get a result like that :
Reference | ProductNameEnglish | ProductNameFrench
What's blocking me is to do 2 requests on the same column (pl.name) :/
Here is my query for now :
SELECT
p.reference AS Reference,
(SELECT pl.name
FROM ps_product p
LEFT JOIN ps_product_lang pl ON (p.id_product = pl.id_product)
WHERE p.active = 1
AND pl.id_lang = 2) AS ENname,
(SELECT pl.name
FROM ps_product p
LEFT JOIN ps_product_lang pl ON (p.id_product = pl.id_product)
WHERE p.active = 1
AND pl.id_lang = 1) AS FRname
FROM ps_product p
You don't need the join in the subqueries:
SELECT p.reference AS Reference,
(SELECT pl.name
FROM ps_product_lang pl
WHERE p.id_product = pl.id_product AND
p.active = 1 AND
pl.id_lang = 2
) AS ENname,
(SELECT pl.name
FROM ps_product_lang pl
WHERE p.id_product = pl.id_product AND
p.active = 1 AND
pl.id_lang = 1
) AS FRname
FROM ps_product p;
This assumes that only one row matches the subqueries. You may need to limit the results to a single row if that is not the case.
SELECT
p.reference AS Reference,
pl.name as ENname,
pf.name as FRname
FROM ps_product p
LEFT JOIN ps_product_lang pl ON (p.id_product = pl.id_product and pl.id_lang = 1)
LEFT JOIN ps_product_lang pf ON (p.id_product = pf.id_product and pf.id_lang = 2)
WHERE p.active = 1
I might have switched English and French, but that should be easy to fix....

I get ORA-00905: missing keyword

I write this query and when I run it I get
ORA-00905: missing keyword
I check with many online SQL query checker and all of them answered it is correct can any body help me what's the problem
select *
from T_TimelineItem ti
where ti.C_HIDE = 0
and ti.F_RELATED_BUSINESS = 4335
and exists(select *
from T_Business b
inner join MM_BIZ_GUILDS g on b.C_ID = g.ID1
where b.C_ID = ti.F_RELATED_BUSINESS
and g.ID2 in (49))
and (CASE ti.C_TYPE
WHEN 1 then ti.C_ID in (select po.C_TIMELINEID
from T_PRODUCT pr
inner join T_POST po on po.C_ID = pr.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and pr.F_GUILD in (49))
WHEN 8 THEN ti.C_ID in (select po.C_TIMELINEID
from T_COMPETITION com
inner join T_POST po on po.C_ID = com.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and com.F_GUILD in (49)) END);
Don't use case in where clauses
and (ti.C_TYPE = 1 and ti.C_ID in (select po.C_TIMELINEID
from T_PRODUCT pr
inner join T_POST po on po.C_ID = pr.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and pr.F_GUILD in (49)))
or (ti.C_TYPE = 8 and ti.C_ID in (select po.C_TIMELINEID
from T_COMPETITION com
inner join T_POST po on po.C_ID = com.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and com.F_GUILD in (49)) END))
I have removed multiple in cause you can use equal easily for single value comparison and you don't need to select all the column inside exists
select *
from T_TimelineItem ti
where ti.C_HIDE = 0
and ti.F_RELATED_BUSINESS = 4335
and exists(select 1
from T_Business b
inner join MM_BIZ_GUILDS g on b.C_ID = g.ID1
where b.C_ID = ti.F_RELATED_BUSINESS
and g.ID2 = 49
)
and (ti.C_TYPE=1
and ti.C_ID in (select po.C_TIMELINEID
from T_PRODUCT pr
inner join T_POST po
on po.C_ID = pr.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and pr.F_GUILD =49
)
or ( ti.C_TYPE=8 and
ti.C_ID in (select po.C_TIMELINEID
from T_COMPETITION com
inner join T_POST po on po.C_ID = com.F_POST
where po.F_BUSINESS = ti.F_RELATED_BUSINESS
and com.F_GUILD =49
)

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.

Else if in my select statement

I want to have an else if in my select statement i have already tried using case when but the results are not so accurate
heres a snippet of my scripts
select distinct t.MovementDate, t.ContractMovementID, t.GID,t.ReferenceGID,
p.refno, t.amount,convert(date,t.CreatedDate) as createdDat
from
LIF_MGM_T_Contract p
inner join LIF_MMS_T_PolicySuspense s with (nolock)
on s.ContractGID = p.GID
inner join LIF_TMS_T_FinancialTransaction t with (nolock)
on t.ContractGID = p.GID
where
p.refno = '1030642 - 1 - Mohahlaula'
and t.ReversedIndicator = 1
and t.counter = (select min(counter)
from LIF_TMS_T_FinancialTransaction t2 with (nolock)
where t2.ContractGID = p.GID
and t2.ReversedIndicator = 1
and t2.MovementDate = t.MovementDate )
So i want a else if t2.reversedindicator = 0 and date = getdate() return results.. Hope this makes sense

Using a sum with a distinct in SQL

I have a query that returns the data i'm looking for using a distinct, but when I SUM that data I get a wrong amount for a my hierachy point '4-2-0-0-5-2'. 4-2-0-0-5-2 has multiple rows so when I sum it, it doesn't add up correctly. What would be the best way to incorporate a distinct into a SUM statement. Any help would be appreicated. Thanks.
First query :
Select distinct B.Proj_Nbr,c.proj_cc,h.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, A.Amount
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1'
RESULT of 2 rows:
9005459 0358080 0358080 4-2-0-0-5-2 Global Sales.com (iSell) 179777.09
9005459 0358080 0358057 4-2-0-0-5-5 Global Sales.com (iSell) 2257.3**
When I want to sum the data I use this query below. This gives me the two rows i'm looking for, but proj_hier 4-2-0-0-5-2 has the wrong amount because it has multiple rows.
Select B.Proj_Nbr,c.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, sum(A.Amount)
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1'
group by B.Proj_Nbr,c.proj_cc,f.dim_acct_id, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per
having Sum(A.Amount) <> 0
Order By H.Proj_Hier, B.Proj_Nbr, D.Fscl_Per
Please Generalize the Question and then ask, If i understood your problem Here is solution:
General Query :
select sum(a.amountColumn) from your_table
group by agrrColumnName;
If i change your query :
Select distinct B.Proj_Nbr,c.proj_cc,h.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, sum(A.Amount)
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1' group by B.Proj_Nbr;