I have the following query that having a sub-query to select from dual. Both result of main and subquery need to be display in the output.
SELECT
a.ROW_EXISTS AS CLIENT_EXIST,
c.AP_Before AS AP_before,
c.AP_TIMESTAMP AS AP_TIMESTAMP,
cd.AAM_FLAG AS AAM_FLAG,
cd.SSM_FLAG AS SSM_FLAG
FROM
(
select
case when exist (select 1 from c.clients where client_id='c-001' then 'Y' else 'N' end as ROW_EXISTS
from dual
) AS a
INNER JOIN CLIENT_DYN cd ON c.CLIENT_ID = cd.CLIENT_ID
WHERE c.CLIENT_ID = 'c-001';
Error ORA-00933: SQL command not properly ended encounters near line ) AS A when execute the query.
After you fix the syntax errors (EXISTS not EXIST, missing closing brace and don't use the AS keyword for table aliases), your outer query is
SELECT <some columns>
FROM (SELECT 'Y/N Value' AS row_exists FROM DUAL) a
INNER JOIN client_dyn cd
ON (c.CLIENT_ID = cd.CLIENT_ID)
There is no c table or alias in the outer-query as the sub-query is aliased to a not c and the sub-query only contains one row_exists column and not a CLIENT_ID column; so on both these points, c.CLIENT_ID is invalid.
What you probably want is something like:
If you want to check the client_id matches the current row:
SELECT CASE WHEN c.client_id IS NOT NULL THEN 'Y' ELSE 'N' END AS CLIENT_EXIST,
c.AP_Before AS AP_before,
c.AP_TIMESTAMP AS AP_TIMESTAMP,
cd.AAM_FLAG AS AAM_FLAG,
cd.SSM_FLAG AS SSM_FLAG
FROM clients c
RIGHT OUTER JOIN CLIENT_DYN cd
ON (c.CLIENT_ID = 'c-001' AND c.CLIENT_ID = cd.CLIENT_ID);
or, if you want to check if the client_id matches in the set of returned rows:
SELECT CASE
WHEN COUNT(CASE WHEN c.client_id = 'c-001' THEN 1 END) OVER () > 0
THEN 'Y'
ELSE 'N'
END AS CLIENT_EXIST,
c.AP_Before AS AP_before,
c.AP_TIMESTAMP AS AP_TIMESTAMP,
cd.AAM_FLAG AS AAM_FLAG,
cd.SSM_FLAG AS SSM_FLAG
FROM clients c
INNER JOIN CLIENT_DYN cd
ON (c.CLIENT_ID = cd.CLIENT_ID);
or, if you want to check if the client_id exists anywhere in the clients table:
SELECT CASE
WHEN EXISTS(SELECT 1 FROM clients WHERE client_id = 'c-001')
THEN 'Y'
ELSE 'N'
END AS CLIENT_EXIST,
c.AP_Before AS AP_before,
c.AP_TIMESTAMP AS AP_TIMESTAMP,
cd.AAM_FLAG AS AAM_FLAG,
cd.SSM_FLAG AS SSM_FLAG
FROM clients c
INNER JOIN CLIENT_DYN cd
ON (c.CLIENT_ID = cd.CLIENT_ID);
Depending on how you want to check if the client exists.
exists, not exist
missing closing subquery bracket
table aliases don't accept the as keyword (as opposed to columns)
SELECT a.ROW_EXISTS AS CLIENT_EXIST,
c.AP_Before AS AP_before,
c.AP_TIMESTAMP AS AP_TIMESTAMP,
cd.AAM_FLAG AS AAM_FLAG,
cd.SSM_FLAG AS SSM_FLAG
FROM client c
INNER JOIN CLIENT_DYN cd ON c.CLIENT_ID = cd.CLIENT_ID
CROSS JOIN (SELECT CASE
WHEN EXISTS
(SELECT 1
FROM clients c
WHERE client_id = 'c-001')
THEN
'Y'
ELSE
'N'
END AS ROW_EXISTS
FROM DUAL) a
WHERE c.CLIENT_ID = 'c-001';
Related
I am trying to select values from three different tables.
When I select all columns it works well, but if I select specific column, the SQL Error [42000]: JDBC-8027:Column name is ambiguous. appear.
this is the query that selected all that works well
SELECT
*
FROM (SELECT x.*, B.*,C.* , COUNT(*) OVER (PARTITION BY x.POLICY_NO) policy_no_count
FROM YIP.YOUTH_POLICY x
LEFT JOIN
YIP.YOUTH_POLICY_AREA B
ON x.POLICY_NO = B.POLICY_NO
LEFT JOIN
YIP.YOUTH_SMALL_CATEGORY C
ON B.SMALL_CATEGORY_SID = C.SMALL_CATEGORY_SID
ORDER BY x.POLICY_NO);
and this is the error query
SELECT DISTINCT
x.POLICY_NO,
x.POLICY_TITLE,
policy_no_count ,
B.SMALL_CATEGORY_SID,
C.SMALL_CATEGORY_TITLE
FROM (SELECT x.*, B.*,C.* , COUNT(*) OVER (PARTITION BY x.POLICY_NO) policy_no_count
FROM YIP.YOUTH_POLICY x
LEFT JOIN
YIP.YOUTH_POLICY_AREA B
ON x.POLICY_NO = B.POLICY_NO
LEFT JOIN
YIP.YOUTH_SMALL_CATEGORY C
ON B.SMALL_CATEGORY_SID = C.SMALL_CATEGORY_SID
ORDER BY x.POLICY_NO);
I am trying to select if A.POLICY_NO values duplicate rows more than 18, want to change C.SMALL_CATEGORY_TITLE values to "ZZ" and also want to cahge B.SMALL_CATEGORY_SID values to null.
that is why make 2 select in query like this
SELECT DISTINCT
x.POLICY_NO,
CASE WHEN (policy_no_count > 17) THEN 'ZZ' ELSE C.SMALL_CATEGORY_TITLE END AS C.SMALL_CATEGORY_TITLE,
CASE WHEN (policy_no_count > 17) THEN NULL ELSE B.SMALL_CATEGORY_SID END AS B.SMALL_CATEGORY_SID,
x.POLICY_TITLE
FROM (SELECT x.*, B.*,C.* , COUNT(*) OVER (PARTITION BY x.POLICY_NO) policy_no_count
FROM YIP.YOUTH_POLICY x
LEFT JOIN
YIP.YOUTH_POLICY_AREA B
ON x.POLICY_NO = B.POLICY_NO
LEFT JOIN
YIP.YOUTH_SMALL_CATEGORY C
ON B.SMALL_CATEGORY_SID = C.SMALL_CATEGORY_SID
ORDER BY x.POLICY_NO);
If i use that query, I got SQL Error [42000]: JDBC-8006:Missing FROM keyword. ¶at line 3, column 80 of null error..
I know I should solve it step by step. Is there any way to select specific columns?
That's most probably because of SELECT x.*, B.*,C.* - avoid asterisks - explicitly name all columns you need, and then pay attention to possible duplicate column names; if you have them, use column aliases.
For example, if that select (which is in a subquery) evaluates to
select x.id, x.name, b.id, b.name
then outer query doesn't know which id you want as two columns are named id (and also two names), so you'd have to
select x.id as x_id,
x.name as x_name,
b.id as b_id,
b.name as b_name
from ...
and - in outer query - select not just id, but e.g. x_id.
I'm trying to create an update query that concatenates 3 fields from a table to 1 field in another table
The first table called table1
ID DESC
12 left:Middle:Right
The second table Table 2
ID FLD1 FLD2 FLD3
12 left Middle Right
Trying to update all the desc field on Table1 with the values of table2 where table1.id = table2.id
update table1 A SET A.DESC = (SELECT CONCAT(B.fld1, ':', B.fld2, ':', B.fld3)
from table2 B
where A.ID = B.ID)
Where A.id = 12;
However, I'm getting an error from the above query saying "invalid number of arguments" Any idea what am I doing wrong? or how can I get this done in a better way?
CONCAT accepts only two parameters, which means that you have to use nested CONCATs.
Though, you'd rather use the double pipe || operator which doesn't have such a restriction. So:
update table1 A SET A.DESC = (SELECT B.fld1 ||':'|| B.fld2 ||':'|| B.fld3 --> this
from table2 B
where A.ID = B.ID)
Where A.id = 12;
To update all matching rows, you could
update table1 A SET A.DESC = (SELECT B.fld1 ||':'|| B.fld2 ||':'|| B.fld3 --> this
from table2 B
where A.ID = B.ID)
Where exists (select null
from table2 b
where a.id = b.id);
or MERGE:
merge into table1 a
using table2 b
on (b.id = a.id)
when matched then update set a.desc = b.fld1 ||':'|| b.fld2 ||':'|| b.fld3;
As you got duplicates, DISTINCT might help, e.g.
update table1 a set
a.desc = (select distinct b.fld1 ||':'|| b.fld2 ||':'|| b.fld3
from table2 b
where a.id = b.id
)
where exists ...
If not, then you'll have to see what to do with these duplicates. If possible, use yet another column(s) in WHERE clause. Or, if you don't really care which concatenated combination fits, use aggregate function(s) such as MIN or MAX, e.g.
update table1 a set
a.desc = (select max(b.fld1 ||':'|| b.fld2 ||':'|| b.fld3)
from table2 b
where a.id = b.id
)
where exists ...
I have a query like this;
SELECT * FROM A
WHERE ID IN(
SELECT ID FROM B WHERE STATUS=1
)
I want to get all rows if sub query is null
How can i do this?
You Should use LEFT JOIN
SELECT A.* FROM A LEFT JOIN B ON A.ID = B.ID AND B.Status = 1
You can use LEFT JOIN and DISTINCT as the following:
SELECT DISTINCT A.* FROM A LEFT JOIN B
ON (A.ID = B.ID AND B.STATUS= 1)
Cheers!!
If you mean I want to get all rows if sub query returns no rows
use a three step approach
1 Check Subquery
select count(*) FROM B WHERE STATUS=1
If you get result > 0 the follow with step 2 otherwise with three
2 Get Subquery Result
-- your original query
SELECT * FROM A
WHERE ID IN(
SELECT ID FROM B WHERE STATUS=1
)
3 Get All Data
SELECT * FROM A
Alternative One Query Approach
Using OR you writes the query as you say: if the query returns no rows get all data.
SELECT * FROM A
WHERE ID IN(
SELECT ID FROM B WHERE STATUS=1
)
OR (SELECT count(*) FROM B WHERE STATUS=1) = 0
I am trying to get all the customers whether they have install service or not from TRANS_TABLE.
NOA- query to get only the MAX product and join again with TRANS_TABLE by email id to get the all the MAX customers details (wwhther they have install service by adding Y OR N, but this query return duplicate with REP Product as well
Below is my Oracel Query which give duplicated
with CTE as (SELECT NOA.*,
CASE
WHEN TRANS_TABLE.product_name LIKE '%Installation%' THEN 'Y'
ELSE 'N'
END AS Installaion ,
ROW_NUMBER() OVER (PARTITION BY TRANS_TABLE.email_address ORDER BY TRANS_TABLE.email_address) AS rn
FROM (SELECT DISTINCT email_address
FROM TRANS_TABLE
WHERE email_address IS NOT NULL
and pdct_name like '%MAX%'
) NOA
LEFT JOIN TRANS_TABLE
ON NOA.email_address = TRANS_TABLE.email_address
select * from cte where rn='1'
The following code will help:
CTE AS (
SELECT
NOA.*,
CASE
WHEN TRANS_TABLE.PDCT_NAME LIKE '%INSTALLATION%' THEN 'Y' -- case sensitive name is used
ELSE 'N'
END AS INSTALLAION,
ROW_NUMBER() OVER(
PARTITION BY TRANS_TABLE.EMAIL_ADDRESS
ORDER BY
TRANS_TABLE.EMAIL_ADDRESS
) AS RN
FROM
(
SELECT DISTINCT
PDCT_NAME,
EMAIL_ADDRESS
FROM
TRANS_TABLE
WHERE
EMAIL_ADDRESS IS NOT NULL
AND PDCT_NAME LIKE '%MAX%'
) NOA
LEFT JOIN TRANS_TABLE ON NOA.EMAIL_ADDRESS = TRANS_TABLE.EMAIL_ADDRESS
WHERE TRANS_TABLE.PDCT_NAME NOT LIKE '%REP%') -- added this WHERE condition
SELECT
PDCT_NAME, EMAIL_ADDRESS, INSTALLAION
FROM
CTE
WHERE
RN = '1'
db<>fiddle demo
Cheers!!
select distinct p.id,
format_name(p.fname, p.lname,'local000000000000001') full_name,
p.username,
p.person_no,
jobinfo.name,
company.name2,
company.name,
dom.name,
per_mgr.username,
a.name
from cmt_person p
inner join fgt_locale loc on loc.id='local000000000000001'
left outer join tpt_company company on p.company_id = company.id
left outer join tpt_ext_job_type jobinfo on p.jobtype_id = jobinfo.id AND jobinfo.locale_id=loc.id
inner join fgt_domain dom on p.split = dom.id
left outer join fgt_gen gen on gen.id1 = p.id and gen.TYPE = 301 and gen.str2 IS NULL
left outer join fgt_ext_admin_managed_lov a on a.id = gen.id2 and a.locale_id = loc.id
left outer join cmt_person per_mgr on per_mgr.id = p.manager_id
inner join fgt_address a on a.owner_id = p.id
where ( p.terminated_on is null or p.terminated_on >= sysdate)
and( (p.type = 100 and p.split in ('domin000000000000007','domin000000000001107','domin000000000001108','domin000000000001109','domin000000000001104','domin000000000001103','domin000000000001106','domin000000000001105','domin000000000000001','domin000000000001102','domin000000000001110'))
or (p.type = 200 and p.split in ('domin000000000000007','domin000000000001107','domin000000000001108','domin000000000001109','domin000000000001104','domin000000000001103','domin000000000001106','domin000000000001105','domin000000000000001','domin000000000001102','domin000000000001110')) )
AND 1=1
AND lower(p.status) = lower('A')
AND lower(a.country) like lower('USA' || '%')
AND p.type in (decode('1','1',100,'2',200,'0',p.type))
AND p.manager_id in ('emplo000000000034578')
ORDER BY 2,3,4,5,6,7,8,9,10
This is the query I have defined table alias for all tables
Do I need column aliases for following columns for 10g?
jobinfo.name ,
company.name2 ,
company.name ,
dom.name
Two tables share the same alias ("a"): fgt_ext_admin_managed_lov and fgt_address. Change it, as that won't work:
SQL> select a.deptno
2 from dept a, emp a;
select a.deptno
*
ERROR at line 1:
ORA-00918: column ambiguously defined
SQL>
Look at below code :-
left outer join fgt_ext_admin_managed_lov a <<<
..
..
inner join fgt_address a <<<<
You have used same alias name for both tables. Change it to any other alias name.