Where clause on custom column - sql

select c.base_id,case when c.type is not null then c.type else g.type end as type, c.function_id
from cust c
left join category cg on c.cat_id=cg.id
where c.type='privelleged'; --- where clause is not working as expected
What am I missing in the above query.The where clause is not working as expected.
I need to apply the where clause on the derived 'type' column. How do I acheive that in Oracle.
Thanks in advance

I suspect that you just want coalesce() -- in both the select and where:
select c.base_id, coalesce(c.type, g.type) as type, c.function_id
from cust c left join
category cg
on c.cat_id = cg.id
where coalesce(c.type, g.type) = 'privileged';

You can't use that derived column the way you wanted - you need to use the same CASE in WHERE as well:
select c.base_id,
case when c.type is not null then c.type
else g.type
end as type,
c.function_id
from cust c
left join category cg on c.cat_id = cg.id
where case when c.type is not null then c.type --> here
else g.type
end = 'privelleged';
Alternatively, use current query as a CTE (or a subquery) and apply filter on it:
with temp as
(select c.base_id,
case when c.type is not null then c.type
else g.type
end as type,
c.function_id
from cust c
left join category cg on c.cat_id = cg.id
)
select *
from temp
where type = 'privelleged';

Related

Avoid NULL value in CASE SQL SERVER

How to avoid NULL values in CASE and SUM by P.Id. Problem is that i have more than one DPB.ProductTypeId in DPB table
SELECT P.[Id],
CASE
WHEN DPB.ProductTypeId = 1 THEN SUM(DPB.BonusAmount)
END AS [CasinoBonus]
FROM Player P
JOIN PlayerBonus DPB ON P.[Id] = DPB.[PlayerId]
group by P.[Id],DPB.ProductTypeId
use case when inside sum
SELECT P.[Id],
sum(CASE
WHEN DPB.ProductTypeId = 1 THEN DPB.BonusAmount
else 0
END) AS [CasinoBonus]
FROM Player P
JOIN PlayerBonus DPB ON P.[Id] = DPB.[PlayerId]
where P.[Id] is not null and DPB.[PlayerId] is not null
group by P.[Id],DPB.ProductTypeId
The case should be the argument to the sum(). You query should look like this:
SELECT P.[Id],
SUM(CASE WHEN DPB.ProductTypeId = 1 THEN DPB.BonusAmount
END) AS [CasinoBonus]
FROM Player P JOIN
PlayerBonus DPB
ON P.[Id] = DPB.[PlayerId]
GROUP BY P.[Id];
Note that you don't want DPB.ProductTypeId in the GROUP BY.
That said, you may simply want:
SELECT P.[Id],
SUM(DPB.BonusAmount) AS [CasinoBonus]
FROM Player P LEFT JOIN
PlayerBonus DPB
ON P.[Id] = DPB.[PlayerId] AND
DPB.ProductTypeId = 1
GROUP BY P.[Id];
Moving the condition to the WHERE clause removes the need for the CASE entirely. The LEFT JOIN keeps all players, even those that don't have that product type.

Select an ID where there is only one row and that row is a specific value

I have this query. There's a lot of joins because I am checking if an ID is linked to any of those tables.
Currently, this query shows me any ID's that are not linked to any of those tables. I would like to add to it so that it also shows any IDs that are linked to the d table, but only if there is only 1 row in the D table and the type in the D field is 'member'.
SELECT
c.ID,
c.location,
c.pb,
c.name,
c.surname
FROM c
LEFT JOIN l on c.rowno = l.rowno
LEFT JOIN d on c.rowno = d.rowno
LEFT JOIN t on c.rowno = t.rowno
LEFT JOIN cj ON (c.rowno = cj.rowno OR c.rowno = cj.rowno2)
LEFT JOIN dj ON c.rowno = d.rowno
LEFT JOIN lg ON c.rowno = lg.rowno
LEFT JOIN tj ON c.rowno = tj.rowno
WHERE
c.status != 'closed'
AND l.rowno IS NULL
AND d.rowno IS NULL
AND t.rowno IS NULL
AND cj.rowno IS NULL
AND dj.rowno IS NULL
AND lg.rowno IS NULL
AND tj.rowno IS NULL
My first thought is to just add
WHERE D.type = 'member'
But that gives me all IDs that have a row with D.type = member (they could have 10 rows with all different types, but as long as 1 of those has type = member it shows up). I want to see ID's that ONLY have d.type = member
I'm sorry if I'm wording this badly, I'm having trouble getting this straight in my head. Any help is appreciated!
I would use exists for all conditions except the one on the D table:
SELECT c.*
FROM c JOIN
(SELECT d.rownum, COUNT(*) as cnt,
SUM(CASE WHEN d.type = 'Member' THEN 1 ELSE 0 END) as num_members
FROM t
GROUP BY d.rownum
) d
ON c.rownum = d.rownum
WHERE c.status <> 'closed' AND
NOT EXISTS (SELECT 1 FROM t WHERE c.rowno = t.rowno) AND
NOT EXISTS (SELECT 1 FROM l WHERE c.rowno = l.rowno) AND
. . .
I find NOT EXISTS is easier to follow logically. I don't think there is a big performance difference between the two methods in SQL Server.

Tree Like Query On SQL Server

i have a query join 4 tables
SELECT
a.Id AS KelompokInformasi, d.Name AS Domain, d.Id AS Dimension, e.Text AS Description FROM XBRLNamespaces a
INNER JOIN Hypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN HypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
INNER JOIN Items d
ON c.XBRLItem_ItemId = d.ItemId
INNER JOIN Labels e
ON d.ItemId = e.XBRLItem_ItemId
WHERE a.Id like '%AAKX%'
the query result is
KelompokInformasi Domain Dimension Description
AAKX JWAAKT dim_JWAAKT Jangka Waktu Aset
AAKX KOKOLT dim_KOKOLT Kolektibilitas
AAKX SNOUPL dim_SNOUPL Status Operasional Usaha Pihak Lawan
AAKX is a parent from the other data in Domain, Dimension, and Description.
So, i want to change the query and in the end have an output query result like this:
KelompokInformasi Domain Dimension Description
AAKX NULL NULL NULL
NULL JWAAKT dim_JWAAKT Jangka Waktu Aset
NULL KOKOLT dim_KOKOLT Kolektibilitas
NULL SNOUPL dim_SNOUPL Status Operasional Usaha Pihak Lawan
I think you must use Group by with cube and having. Or grouping sets.
http://technet.microsoft.com/en-us/library/bb522495(v=SQL.105).aspx
SELECT
'KelompokInformasi' =
CASE
WHEN a.Id like '%AAKX%' THEN a.Id
ELSE NULL
END,
'Domain' =
CASE
WHEN a.Id like '%AAKX%' THEN NULL
ELSE d.Name
END,
'Dimension' =
CASE
WHEN a.Id like '%AAKX%' THEN NULL
ELSE d.Id
END,
'Description' =
CASE
WHEN a.Id like '%AAKX%' THEN NULL
ELSE e.Text
END,
FROM XBRLNamespaces a
INNER JOIN Hypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN HypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
INNER JOIN Items d
ON c.XBRLItem_ItemId = d.ItemId
INNER JOIN Labels e
ON d.ItemId = e.XBRLItem_ItemId
WHERE a.Id like '%AAKX%'
You can use Common table Expression(CTE),ROW_NUMBER() and Same Case statement used as above:
WITH cte AS
SELECT
a.Id AS KelompokInformasi,d.Name AS DOMAIN,d.Id AS Dimension,e.Text AS Description ,
ROW_NUMBER() OVER (PARTITION BY a.Id ORDER BY a.ID) AS COL5
FROM XBRLNamespaces a
INNER JOIN Hypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN HypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
INNER JOIN Items d
ON c.XBRLItem_ItemId = d.ItemId
INNER JOIN Labels e
ON d.ItemId = e.XBRLItem_ItemId
WHERE a.Id LIKE '%AAKX%' )
SELECT CASE
WHEN COL5 >1 THEN NULL ELSE KelompokInformasi END AS KelompokInformasi,
CASE
WHEN COL5=1 THEN NULL ELSE DOMAIN END AS DOMAIN,
CASE
WHEN COL5=1 THEN NULL ELSE Dimension END AS Dimension,
CASE
WHEN COL5=1 THEN NULL ELSE Description END AS Description
FROM cte

How to compare with Case in Where clause

Here am having Person and Address Tables .Some Persons may have address or not.If they have address then want to join address table otherwise no need to join.Please help to solve this case.
select p.name,nvl(a.address,'address not available') from person p,address a
where p.id = 2 and case
when p.addid is not null
then p.addid = a.id
else 0=0 end
The general solution - use Boolean logic. You cannot choose between complete expressions using CASE, so you should rewrite it to use a combination of AND and OR. Using the logic from your question, you would rewrite it as:
WHERE p.id = 2
AND
(
(p.addid IS NOT NULL AND p.addid = a.id)
OR (p.addid IS NULL AND 0=0)
)
Which ultimately simplifies down to:
WHERE p.id = 2
AND (p.addid IS NULL OR p.addid = a.id)
The specific solution for your query - use better JOIN syntax, and simply leverage a LEFT JOIN:
SELECT p.name, nvl(a.address,'address not available')
FROM person p
LEFT OUTER JOIN address a ON p.addid = a.id
WHERE p.id = 2
Try to use coalesce function as below
select p.name,nvl(a.address,'address not available') from person p,address a
where p.id = 2
and coalesce(p.addid,a.id)=a.id
select p.name, nvl(a.address, 'address not available')
from person p left outer join address a
on (p.addid = a.id )
where p.id = 2;
You can't use case, but you can achieve the same effect with combination of ors sand ands
select p.name,
nvl(a.address,'address not available')
from person p,
address a
where p.id = 2 and
( p.addid is not null AND p.addid = a.id
OR
p.addid is null
)
try this:
select p.name,nvl(a.address,'address not available') from person p,address a
where p.id = 2 and a.id = case when p.addid is not null then p.addid else a.id end;

Why does inequality test eliminate NULL values?

After I added c.category <> 'AGILE' to the query below, the results set stopped including NULL values for c.category. How can I get rows with a NULL c.category back in my result set, without doing a UNION?
select
p.number,
p.method
,sum(p.amount) AS amount
,count(*) AS count,c.category
from payments p
inner join headers a
on p.name = a.name
inner join customer c
on c.number = p.number
and a.status = 'APPROVED'
and a.type IN ('REGULAR', 'TRANSFER', 'OTHER')
and c.category <> 'AGILE'
group by
p.payment_method
,p.cust_number
,c.u_cust_category
NULL is neither equal to nor unequal to any particular value. If you want to include NULL values, you would want something like
and( c.category <> 'AGILE'
or c.category IS NULL)
Here's one way:
AND (c.category IS NULL OR c.category <> 'AGILE')
Here's another:
AND NVL(c.category, 'foo') <> 'AGILE'
This simply works:
(c.category <> 'AGILE' OR c.category IS NULL)