Case expression Issue - oracle

I am trying to run this below select query
select c.customer_id ,
c.customer_name,
c.city
from
customers c
where
case when c.customer_name = 'Sai' then c.city is null
and c.city!=null
Which is resulting in
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
*Cause:
*Action:
Error at Line: 9 Column: 47
Can you please let me know how to fix this error ?

!= NULL will never be true and the CASE expression does not have an END.
To fix it , you can just use AND and OR:
select c.customer_id ,
c.customer_name,
c.city
from customers c
where ( c.customer_name = 'Sai' AND c.city IS NULL )
OR ( ( c.customer_name != 'Sai' OR c.customer_name IS NULL )
AND c.city IS NOT NULL )
If you must use a CASE expression then the expression in the THEN/ELSE clauses must be a value (and not a comparison) so you need to put the comparison outside of the CASE expression:
select c.customer_id ,
c.customer_name,
c.city
from customers c
WHERE CASE
WHEN c.customer_name = 'Sai' AND c.city IS NULL
THEN 1
WHEN ( c.customer_name != 'Sai' OR c.customer_name IS NULL )
AND c.city IS NOT NULL
THEN 1
END = 1

Can you explain what you're trying to do in your where clause?
where case when c.customer_name = 'Sai' then c.city is null and c.city!=null
Do you want the city to show null when the customer name is 'Sai'?
If so -
select c.customer_id ,
c.customer_name,
case when c.customer_name = 'Sai' then null else c.city end as city
from customers c
where c.city is not null

Related

Hibernate and H2 no dialect mapping for jdbc type 0

Im running this Query via JpaRepository on MSSQL Server and it works fine
SELECT TOP(8) * FROM (
SELECT distinct a.id as source_id
, null as f_name
, null as m_name
, null as last_name
, null as full_name
, a.name as business_name
, a.dba_name as dba_name
, ad.id as address_id
, ad.line_1 as address_line_1
, ad.city_town as city
, right(tr.code,2) as state
, ad.zip_postal_code as postal_code
, co.name as country_name
, a.national_tax_ident as id_number
, 'T' as id_number_type
, null as date_of_birth
, 'SuretyVP' as data_source_id
, 'AGENT' as role_id
, getdate() as cycle_date
, 299 as create_user_id
, getdate() as create_date
, null as update_date
, null as attention
, 'agency' as entity_name
from dbo.Agency a
inner join dbo.agency_address ag on a.id = ag.agency_id
inner join dbo.address ad on ad.id = ag.address_id
inner join [AdminDB].[dbo].[countries] co
on ad.country_id = co.id
inner join [AdminDB].[dbo].[territories] tr
on ad.state_province_territory_id = tr.id
Where a.ofac_processed_ind = 0
AND ag.address_type_id = 2
AND ag.exp_date is null
AND a.agency_status_id = 1
UNION ALL
SELECT distinct c.id as source_id
, c.first_name as f_name
, c.middle_name as m_name
, c.last_name as last_name
, null as full_name
, null as business_name
, null as dba_name
, null as address_id
, null as address_line_1
, null as city
, null as state
, null as postal_code
, 'United States' as country_name
, null as id_number
, null as id_number_type
, null as date_of_birth
, 'SuretyVP' as data_source_id
, 'AGENT' as role_id
, getdate() as cycle_date
, 299 as create_user_id
, getdate() as create_date
, null as update_date
, null as attention,
'contact' as entity_name
from dbo.Contact c
inner join dbo.Agency_contact ac on c.id = ac.contact_id
inner join dbo.agency a on ac.agency_id = a.id
Where c.ofac_processed_ind = 0
AND a.agency_status_id = 1
ANd c.exp_date is null
ANd ac.exp_date is null
AND ac.contact_role_type_id = 12) as data
But when I try to Run integration test with this query against H2 DB I have the following error
No dialect mapping for jdbc type 0
Here is my H2 DB config spring.datasource.url=jdbc:h2:mem:test:SAMINTEGERATIONTEST;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MSSQLServer
I saw similar topics, but unfortunately didn't find solution for my problem.
I would be very grateful for any advice.Thank you!
null as full_name, null as date_of_birth, null as update_date, and null as attention don't have a data type in both first and second queries, therefore UNION ALL also can't determine the data type. H2 by itself doesn't care about this situation and assumes that these columns have a fake NULL data type and can have only NULL value. But your persistence libraries don't like it.
The simplest solution is to add a CAST to all these columns in one of the queries (or in both of them, if you wish, it doesn't matter):
CAST(null AS VARCHAR) as full_name,
…
CAST(null AS DATE) as date_of_birth,
…

Oracle Pivot options

I have the below Pivot and output. I would like to display the below.
Remove the parentheses around the columns?
Add indicator of X and Null in substitute of 1 and 0?
SQL:
SELECT DISTINCT
*
FROM (
SELECT D.ID, D.DI, A.ID
FROM A
LEFT JOIN AD ON A.ID = AD.ID
LEFT JOIN D ON AD.ID = D.ID
WHERE 1=1
AND A.ID = 890929
)
PIVOT
(
COUNT(ID)
FOR DI IN ( 'Low med','Soft','Regular','High Med','Other')
)
Query output:
ID 'Low med' 'Soft' 'Regular' 'High Med' 'Other'
1 1 1 0 0 1
Expected output:
ID LOW_MED SOFT REGULAR HIGH_MED OTHER
1 X X NULL NULL X
You can remove the single quotes (not parentheses, which are ()), by aliasing the pivoted expressions:
FOR DI IN ('Low med' as low_med, 'Soft' as soft, 'Regular' as regular,
'High Med' as high_med,'Other' as other)
You can then use those aliases for the second part, but adding case expressions to your main query:
SELECT id,
case when low_med = 1 then 'X' else null end as low_med,
case when soft = 1 then 'X' else null end as soft,
case when regular = 1 then 'X' else null end as regular,
case when high_med = 1 then 'X' else null end as high_med,
case when other = 1 then 'X' else null end as other
FROM (
SELECT D.ID, D.DI, A.ID
FROM A
LEFT JOIN AD ON A.ID = AD.ID
LEFT JOIN D ON AD.ID = D.ID
WHERE 1=1
AND A.ID = 890929
)
PIVOT
(
COUNT(ID)
FOR DI IN ('Low med' as low_med, 'Soft' as soft, 'Regular' as regular,
'High Med' as high_med,'Other' as other)
)

left outer join - what's the difference?

I sometimes get confused with LEFT JOINS and OR.
Here in the below two code samples, there is only one difference. There is a bracket in the WHERE clause in one sample and no bracket in other sample.
Obviously, I am getting different results. I want to understand what's happening.
Thanks.
SELECT FROM TABLE_A as A
LEFT OUTER JOIN TABLE_B as B
ON
A.col1 = B.col1 AND
A.col2 = B.col2 AND
A.col3 = B.col3
WHERE
B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL AND
B.col4= 'R' AND
B.col5 != 'DR'
SELECT FROM TABLE_A as A
LEFT OUTER JOIN TABLE_B as B
ON
A.col1 = B.col1 AND
A.col2 = B.col2 AND
A.col3 = B.col3
WHERE
(B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL) AND
B.col4= 'R' AND
B.col5 != 'DR'
(B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL)
In second case, first the expression in the bracket is evaluated and then the following "AND" operators are applied. So the results if above bracket expression is ANDed with B.col4= 'R' and then it is ANDed with B.col5 != 'DR'
B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL AND
B.col4= 'R' AND
B.col5 != 'DR'
In first case, it is evaluated like following:
(B.col1 IS NULL) OR (B.col2 IS NULL) OR (B.col3 IS NULL AND B.col4= 'R' AND B.col5 != 'DR')
The AND operator has higher precedence than OR, so your first WHERE clause can be written as this:
WHERE
B.col1 IS NULL OR B.col2 IS NULL OR (B.col3 IS NULL AND
B.col4= 'R' AND
B.col5 != 'DR')
But this may not be what you intended, if the second version of your WHERE clause is any evidence. If you want to check for either of the three columns being NULL ANDed with the other two conditions then you should use parentheses.
I think you've gotten very confused about left joins as well as the AND/OR operator precedence.
In your first query, the order is applied left to right, with ANDS being applied first.
That means that your first query is the equivalent of:
SELECT *
FROM table_a a
LEFT OUTER JOIN table_b b ON (a.col1 = b.col1
AND a.col2 = b.col2
AND a.col3 = b.col3)
WHERE b.col1 IS NULL
OR b.col2 IS NULL
OR (b.col3 IS NULL
AND b.col4 = 'R'
AND b.col5 != 'DR');
However, your second query is checking for nulls in any of the three join conditions (which would either be all null, or all not null, since you haven't catered for null values in your join conditions) as well as checking for the presence of values in the remaining two columns. Which doesn't make sense - if col1, col2 and col3 are null, it means that table_b row isn't part of the join, so col4 and col5 would be null as well.
Instead, what I think you meant to do was to make the and b.col4 = 'R' and b.col5 != 'DR' part of the left outer join conditions - ie. only join the rows from table_b where col4 = 'R' and col5 != 'DR' - like so:
WITH table_a AS (SELECT 1 col1, 1 col2, 1 col3 FROM dual UNION ALL
SELECT 2 col1, 2 col2, 2 col3 FROM dual UNION ALL
SELECT 3 col1, 3 col2, 3 col3 FROM dual),
table_b AS (SELECT 1 col1, 1 col2, 1 col3, 'R' col4, 'DP' col5 FROM dual UNION ALL
SELECT 2 col1, 2 col2, 2 col3, 'R' col4, 'DR' col5 FROM dual)
SELECT *
FROM table_a a
LEFT OUTER JOIN table_b b ON (a.col1 = b.col1
AND a.col2 = b.col2
AND a.col3 = b.col3
AND b.col4 = 'R'
AND b.col5 != 'DR');
COL1 COL2 COL3 COL1 COL2 COL3 COL4 COL5
---------- ---------- ---------- ---------- ---------- ---------- ---- ----
1 1 1 1 1 1 R DP
2 2 2
3 3 3
Your second query is not a LEFT OUTER JOIN:
SELECT *
FROM TABLE_A A
LEFT OUTER JOIN TABLE_B B
ON ( A.col1 = B.col1
AND A.col2 = B.col2
AND A.col3 = B.col3 )
WHERE ( B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL )
AND B.col4= 'R'
AND B.col5 != 'DR'
The WHERE clause will only accept rows where B.col4 and B.col5 are NOT NULL and this will only ever be the case when the tables are joined and this means the join condition is effectively an INNER JOIN.
However, the conditions ( B.col1 IS NULL OR B.col2 IS NULL OR B.col3 IS NULL ) and ( A.col1 = B.col1 AND A.col2 = B.col2 AND A.col3 = B.col3 ) can never be fulfilled simultaneously since a NULL value cannot equal any other value (including another NULL). So the query should never return any rows.
The first query is:
SELECT *
FROM TABLE_A A
LEFT OUTER JOIN TABLE_B B
ON ( A.col1 = B.col1
AND A.col2 = B.col2
AND A.col3 = B.col3 )
WHERE B.col1 IS NULL
OR B.col2 IS NULL
OR ( B.col3 IS NULL AND B.col4= 'R' AND B.col5 != 'DR' )
This will return rows when B.col1 IS NULL OR B.col2 IS NULL but will never match on ( B.col3 IS NULL AND B.col4= 'R' AND B.col5 != 'DR' ) since the join condition will enforce the either B.col3 is not NULL (when there is a match in the LEFT OUTER JOIN) or B.col4 and B.col5 are both NULL (when there is no match in the LEFT OUTER JOIN).
What you might actually be trying to achieve (although it is unclear from your question) is:
SELECT *
FROM TABLE_A A
LEFT OUTER JOIN TABLE_B B
ON ( A.col1 = B.col1
AND A.col2 = B.col2
AND A.col3 = B.col3
AND B.col4 = 'R'
AND B.col5 != 'DR' )

Oracle SQL query performance

I have 3 tables trader, city_state, city_present.
I have 4million rows in trader table and my query is taking atleast 20sec. Few records in city_present and cities table.
Below is my query.
select t.trader_id, t.name, t.city, t.state from
(
SELECT distinct c.city, c.state
FROM city_present p,city_state c
WHERE p.name = 'TEST_TEST'
AND c.city = p.city
AND c.state = p.state
)
cs, trader t
where
AND t.city = cs.city
AND t.state = cs.state
AND t.name = 'john test'
AND t.is_valid= 1
I have index on customer (city, state, name, valid_customer)
Subquery is taking less than a second .. it is outer query that is taking around 20sec.
Can someone please help me how to reduce the query time.
I assume you have an index on trader.name, possibly including trader.is_valid as well?
And is the distinct really required? Does that really need to be an in-line view, or could it be a regular join?
There are some things you can try without adding anything to your schema: in your subquery you never select anything from city_present, so you can turn it into IN / EXISTS
select t.trader_id, t.name, t.city, t.state from
(
SELECT c.city, c.state
FROM city_state c
WHERE EXISTS (
select null
from city_present p
where
p.name = 'TEST_TEST'
AND c.city = p.city
AND c.state = p.state)
)
cs, trader t
where
AND t.city = cs.city
AND t.state = cs.state
AND t.name = 'john test'
AND t.is_valid= 1
Then, the same thing applies to cs. So you could rewrite to:
select t.trader_id, t.name, t.city, t.state from
trader t
where
exists (
SELECT null
FROM city_state c
WHERE EXISTS (
select null
from city_present p
where
p.name = 'TEST_TEST'
AND c.city = p.city
AND c.state = p.state)
AND t.city = c.city
AND t.state = c.state
)
AND t.name = 'john test'
AND t.is_valid= 1
You can also try flattening the subqueries:
select t.trader_id, t.name, t.city, t.state from
trader t
where
exists (
SELECT null
FROM city_present p,city_state c
WHERE p.name = 'TEST_TEST'
AND c.city = p.city
AND c.state = p.state
AND t.city = c.city
AND t.state = c.state
)
AND t.name = 'john test'
AND t.is_valid= 1
From here, you should investigate about indexing:
trader.name and / or trader.id
(city_state.city, city_state.state) and (city_present.city, city_present.state)

Dynamic query to dynamic data

I am new to the oracle database, I am trying to execute the following query
select o.id as ovaid ,
(case when(select count(m.cid) from ovamapper m where m.id = o.id and m.solutionid = 1)>0 then 1 else 0 end) as sol1,
(case when(select count(m.cid) from ovamapper m where m.id = o.id and m.solutionid = 2)>0 then 1 else 0 end) as sol1,
(case when(select count(m.cid) from ovamapper m where m.id = o.id and m.solutionid = 3)>0 then 1 else 0 end) as sol1 from ovatemplate o order by o.id
Instead of static values for solutionid , I would like to select it from other table.
Any help on this is really appreciated
you could use
join
to table that contain the solutionid. ex
Select * from ovatemplate JOIN solutiontable ON (solutiontable.ovaid=ovatempate.ovaid)
after that, change the static values to solutionid
Try this query
select o.id as ovaid ,
count(case when solutionid = 1 then m.cid else null end) as sol1 ,
count(case when solutionid = 2 then m.cid else null end) as sol2 ,
count(case when solutionid = 3 then m.cid else null end) as sol3
from ovamapper m , ovatemplate o
where m.id = o.id
group by o.id
order by o.id
If you dont need the aggregations as columns you should probably do that instead
select o.id as ovaid , solutionid , count(*) as sol
from ovamapper m , ovatemplate o
where m.id = o.id
and m.solutionid in (1,2,3)
group by o.id , solutionid
order by o.id

Resources