Error: column reference is ambiguous - oracle

I have two tables from which i want to get the date without using joins.
id ProductVersion productName productDate
1 p1.1 product1 2017-3-11
2 p1.2 product1 2017-3-11
3 p2.1 product2 2017-5-12
4 p2.2 product2 2017-5-12
5 p2.3 product2 2017-5-12
6 p3.1 product3 2017-11-21
7 p3.1 product3 2017-11-21
Table2
tid productVersion comments status AvailableDate
101 p1.1 Good Sold 2017-3-11
102 p1.1 Good Available 2017-3-12
1009 p1.1 Good Available 2017-3-12
4008 p3.1 Average NA 2017-11-11
106 p3.2 Good Sold 2017-5-14
6 p3.1 Average Available 2017-11-12
I have two tables as shown above.
I want to get productVersion,productName,productDate,Comments,status column details from the above two tables.
SQL Query(without joins):
select productversion t1,productName t1,productDate t1,comments t2,status t2 from table1 t1,table2 t2
where t1.productVersion = t2.productversion
Error message:
Error: column reference "productDate" is ambiguous.
Any inputs?

[TL;DR] Your main issue is that you appear to be putting the table aliases after the column name where an alias for the column is expected when they should be prefixing the column name to identify which table the columns belong to.
Your query is equivalent to:
select productversion AS columnalias1,
productName AS columnalias2,
productDate AS columnalias3,
comments AS columnalias4,
status AS columnalias5
from table1 t1,
table2 t2
where t1.productVersion = t2.productversion
And all your column aliases are either t1 or t2 so you will get multiple columns with the same name. I do not think this is what you intended as both tables have a productVersion column so the query parser does not know which you intended to use. You probably want the table aliases before the column name to identify which table each column is from:
select t1.productversion,
t1.productName,
t1.productDate,
t2.comments,
t2.status
from table1 t1,
table2 t2
where t1.productVersion = t2.productversion
The second problem is that, while you say it is a query "without joins", you are using a legacy Oracle comma-join syntax and your query can be rewritten to have exactly the same functionality using ANSI/ISO SQL syntax and is equivalent to:
select t1.productversion,
t1.productName,
t1.productDate,
t2.comments,
t2.status
from table1 t1
INNER JOIN table2 t2
ON ( t1.productVersion = t2.productversion )
If you want something without joins then use UNION ALL:
SELECT productVersion,
productName,
productDate,
NULL AS Comments,
NULL AS status
FROM table1
UNION ALL
SELECT productVersion,
NULL AS productName,
NULL AS productDate,
Comments,
status
FROM table2
But it will not correlate the values in the two tables.

To refer to a specific table column, you use this syntax:
table_name.column_name
Your query should be:
select t1.productversion, t1.productName, t1.productDate,
t2.comments, t2.status
from table1 as t1
join table2 as t2 on t1.productVersion = t2.productversion

Related

update set value based on another value of another column and/or same column in another row:-ORA 1427

I'm trying to set a column to reset to zero or increment by +1 based on a pass or fail in another column, and/or the value of that same column in the previous weeks row.
There are two other variable columns which must match those in the previous weeks row.
Table is something like:
WEEK | ID1 | ID2 | FLAG | INCREMENT_COUNT |
--------------------------------------------------------
--------------------------------------------------------
I have been trying to get this part of the procedure to work, and the best I've got so far is:
ID_IN and ID_IN3 are passed in the procedure call
OLD_DATE and NEW_DATE are set as the previous week and current week
----------------------------------------------------------------------
update table1
set table1.INCREMENT_COUNT = CASE
WHEN table1.FLAG is null then null
WHEN table1.FLAG = 1 then 0
WHEN table1.FLAG = 0 then (NVL(INCREMENT_COUNT,0)+ 1)
END
where (select INCREMENT_COUNT
from table1
where WEEK=NEW_DATE
and ID1=ID_IN
and exists (select (1)
from table2
where table1.ID2=table2.ID2
and table2.ID3=ID_IN3))
=
(select INCREMENT_COUNT
from table1
where WEEK=OLD_DATE
and ID1=ID_IN
and exists (select (1)
from table2
where table1.ID2=table2.ID2
and table2.ID3=ID_IN3));
When this procedure is called I get the error
ORA-01427: single-row subquery returns more than one row
Additionally, in MySQL I could do it something like this and get it working...
update table1 as t01
left join(select ID3, ID2, INCREMENT_COUNT as prev_count from table1 as t10 inner join table2 as t2 on t10.ID2=t2.ID2 where ID1=ID_IN and ID3=ID_IN3 and t10.WEEK=OLD_DATE) as prev_date on t01.WEEK=NEW_DATE and prev_date.ID2=t01.ID2 and t01.ID1=ID_IN
set t01.INCREMENT_COUNT = if(t1.FLAG is null, null, if(t1.FLAG,0, IFNULL(prev_date.prev_count,0)+1))
where t01.ID1=ID_IN
and t1.WEEK=NEW_DATE
and prev_date.ID3=ID_IN3;
Similarl to your mySQL example, you can do something like this in oracle. This may not work for you depending on your data model. I've put together a crude basic version based on your information, but you've not provided enough information about your data model and your tables/aliases/column names are poor for readability...
(more on update with a subquery here -> https://docs.oracle.com/database/121/SQLRF/statements_10008.htm#i2067871)
update
(select t01.increment_count, t01.flag, prev_date.prev_count
from table1 t01
left join(select ID3, ID2, INCREMENT_COUNT as prev_count
from table1 t10
inner join table2 t2 on t10.ID2=t2.ID2
where ID1=ID_IN
and ID3=ID_IN3
and t10.WEEK=OLD_DATE) prev_date on t01.WEEK=NEW_DATE and prev_date.ID2=t01.ID2 and t01.ID1=ID_IN
where t01.ID1=ID_IN
and t1.WEEK=NEW_DATE
and prev_date.ID3=ID_IN3)
set INCREMENT_COUNT = if(FLAG is null, null, if(FLAG,0, IFNULL(prev_count,0)+1));
One of the queries in where condition returns more than 1 record
This seems to have done the job.
Thanks for the help, it got me thinking in a different way.
UPDATE TABLE1 T01
SET INCREMENT_COUNT = CASE
WHEN T01.FLAG IS NULL THEN NULL
WHEN T01.FLAG = 1 THEN 0
WHEN T01.FLAG = 0 THEN (NVL((SELECT INCREMENT_COUNT
FROM TABLE1 T10
WHERE T10.WEEK=OLD_DATE
AND T01.WEEK=NEW_DATE
AND T01.ID2=T10.ID2
AND ID1=ID_IN),0)+ 1)
END
WHERE EXISTS (SELECT (1)
FROM TABLE2
WHERE TABLE1.ID2=TABLE2.ID2
AND TABLE2.ID3=ID_IN3);

Oracle 11g - Selecting multiple records from a table column

I was just wondering how you select multiple records from a table column. Please see below the query.
SELECT DISTINCT DEPARTMENT_NAME, CITY, COUNTRY_NAME
FROM OEHR_DEPARTMENTS
NATURAL JOIN OEHR_EMPLOYEES
NATURAL JOIN OEHR_LOCATIONS
NATURAL JOIN OEHR_COUNTRIES
WHERE JOB_ID = 'SA_MAN' AND JOB_ID = 'SA_REP'
;
Basically, I want to be able to select records from the table column I have, however when you use AND it only displays SA_MAN and not SA_REP. I have also tried to use OR and it displays no rows selected. How would I actually be able to select both Job ID's without it just displaying one or the other.
Sorry this may sound like a stupid question (and probably not worded right), but I am pretty new to Oracle 11g SQL.
For your own comfort while debugging, I suggest you to use inner joins instead of natual joins.
That where clause is confusing, if not utterly wrong, because you don't make clear which tables' JOB_ID should be filtered. Use inner joins, give aliases to tables, and refer to those aliases in the where clause.
select distinct DEPARTMENT_NAME, CITY, COUNTRY_NAME
from OEHR_DEPARTMENTS t1
join OEHR_EMPLOYEES t2
on ...
join OEHR_LOCATIONS t3
on ...
join OEHR_COUNTRIES t4
on ...
where tn.JOB_ID = 'SA_MAN' AND tm.JOB_ID = 'SA_REP'
After rephrasing your query somehow like this, you'll have a clearer view on the logical operator you'll have to use in the where clause, which I bet will be an OR.
EDIT (after more details were given)
To list the departments that employ staff with both 'SA_MAN' and 'SA_REP' job_id, you have to join the departments table with the employees twice, once with the filter job_id='SA_MAN' and once with job_id='SA_REP'
select distinct DEPARTMENT_NAME, CITY, COUNTRY_NAME
from OEHR_DEPARTMENTS t1
join OEHR_EMPLOYEES t2
on t1.department_id = t2.department_id --guessing column names
join OEHR_EMPLOYEES t3
on t1.department_id = t3.department_id --guessing column names
join OEHR_LOCATIONS t4
on t1.location_id = t4.location_id --guessing column names
join OEHR_COUNTRIES t5
on t4.country_id = t5.country_id --guessing column names
where t2.job_id = 'SA_MAN' and t3.job_id = 'SA_REP'
order by 1, 2, 3

How to use aliases in an Oracle correlated subquery join?

I'm using a subquery for a join operation. When I hard-code parameters, things work fine. But those parameters must come from outer sql which I believe is referred to as correlated query. I would like to pass them in using table aliases but this results in invalid identifier.
Example invented for the purpose of question:
SELECT
PR.PROVINCE_NAME
,CO.COUNTRY_NAME
FROM
PROVINCE PR
JOIN (
SELECT COUNTRY_ID, COUNTRY_NAME
FROM COUNTRY
WHERE COUNTRY_ID=PR.COUNTRY_ID
) CO ON CO.COUNTRY_ID=PR.COUNTRY_ID
WHERE
PR.PROVINCE_ID IN (1,2)
This is typed in, so I hope I haven't introduced any syntax issues here. The question is specifically about COUNTRY_ID=PR.COUNTRY_ID following the WHERE clause. Are aliases legal in such subqueries?
You are using the alias in two different locations. For one it is legal, for the other it is not:
SELECT pr.province_name, co.country_name
FROM province pr
JOIN (
SELECT country_id, country_name
FROM country
WHERE country_id = pr.country_id --<< this reference to the outer table/alias is invalid
) co ON co.country_id = pr.country_id -- this is valid
WHERE pr.province_id IN (1,2)
With a (standard) join to a derived table, the inner select can't access an alias or table from the outer select. The "invalid identifier" that you get is cause by the line WHERE country_id = pr.country_id.
Given your JOIN condition you can safely remove that without changing the result. And the Oracle optimizer is smart enough to push that condition into the derived table.
In fact the optimizer will rewrite the query to:
SELECT pr.province_name, co.country_name
FROM province pr
JOIN country co ON co.country_id = pr.country_id
WHERE pr.province_id IN (1,2);
There is however a way of accessing table (or aliases) from the outer query in a derived table: it's called a lateral join.
This is part of the SQL standard, but you need Oracle 12 in order to be able to use it:
The following is legal:
SELECT pr.province_name,co.country_name
FROM province pr
JOIN LATERAL (
SELECT country_id, country_name
FROM country
WHERE country_id = pr.country_id
) co ON co.country_id = pr.country_id
WHERE pr.province_id IN (1,2)

Extracting different fields and tables ORACLE R12 TABLES

I have a problem of joining the tables of Oracle r12 tables. I have tried something like this..
SELECT
part.party_name,
custA.account_number,
headAll.cust_po_number,
headAll.order_number,
trans.NAME,
headAll.ordered_date,
sales.person_name,
headAll.flow_status_code,
items.segment1,
lineAll.ordered_quantity,
lineAll.order_quantity_uom,
lineAll.unit_selling_price,
lineAll.tax_code
FROM
oe_order_headers_all headAll,
oe_order_lines_all lineAll,
hz_cust_accounts custA,
hz_parties part,
oe_transaction_types_tl trans,
hz_person_profiles sales,
mtl_system_items_b items
WHERE
headAll.Header_ID = lineAll.Header_ID
AND custA.Application_ID = part.Application_ID
AND custA.Application_ID = sales.Application_ID
AND items.inventory_item_id = lineAll.inventory_item_id;
It is running but I know it is wrong because it is multiplying tables. Any Ideas of r12 tables in Oracle and combining this sample r12 tables?
-oe_order_headers_all
-oe_order_lines_all
-hz_cust_accounts
-hz_parties
-oe_transaction_types_tl
-hz_person_profiles
-mtl_system_items_b
I Tried this..
Updated:
from oe_order_headers_all headAll
INNER JOIN
oe_order_lines_all lineAll
ON headAll.Header_ID = lineAll.Header_ID
INNER JOIN
hz_cust_accounts custA
ON headAll.sold_to_org_id = custA.cust_account_id
INNER JOIN
hz_parties part
ON custA.party_id = part.party_id
INNER JOIN
oe_transaction_types_tl trans
ON headAll.order_type_id = trans.transaction_type_id
INNER JOIN
hz_person_profiles sales
ON part.party_id = sales.party_id
INNER JOIN
mtl_system_items_b items
ON items.inventory_item_id = lineAll.inventory_item_id
And I Tried Where Clause
where headAll.Header_ID = lineAll.Header_ID AND headAll.order_type_id = trans.transaction_type_id AND custA.party_id = part.party_id
AND part.party_id = sales.party_id AND headAll.sold_to_org_id = custA.cust_account_id AND items.inventory_item_id = lineAll.inventory_item_id;
Still multiplying..
Forget about having Oracle R12 suite. In general any Oracle engine will behave like this.
Let me show you some examples.
TABLE A
- COL1 PK1
- COL2 PK1
- COL3
TABLE B
- COL4 PK2
- COL5 PK2
- COL6
TABLE C
- COL7
- COL8 -PK3
- COL9 -PK3
In this model, whenever we join any tables unless you join on their key combinations or based on the rule that for any given row you retrieve a maximum of one row from the other table.
SELECT A.COL1
FROM TABLEA, TABLEB
WHERE COL1 = COL4
AND COL2 = COL5;
OR in ANSI syntax
SELECT A.COL1
FROM TABLEA
JOIN TABLEB ON COL1 = COL4 AND COL2 = COL5;
So this can be extended on the third table.
SELECT A.COL1
FROM TABLEA, TABLEB, TABLEC
WHERE COL1 = COL4
AND COL2 = COL5
AND COL1 = COL8
AND COL2 = COL9;
PS: The assumption is that the combined primary key on both the tables will always provide one row for the other.
You need to extend your ON clauses to include a condition so that for each entry in TABLE A there is only one entry in TABLE B that matches the condition and that for each entry in TABLE B there is only one entry in TABLE C
You can always try to join tables one by one and keep the query building until and unless you done violate the thumb rule (said above).
If, I change the join condition and any table duplicates while performing the same, then the same will be propagated to the subsequent joins.
There are not all relations between tables. Alias trans isn't related at all, groups headAll, lineAll, items and custA, part, sales are separated. In this case rows will be joined with default cross join.
Add conditions in the WHERE clause:
AND headAll.order_type_id = trans.transaction_type_id
AND headAll.sold_to_org_id = custA.cust_account_id
Please see this example from Oracle tutorial: Query to get the OM Sales Order summary details

need help on sql query

am a newbie to Oracle/PL SQL.I've 2 tables A and B.
A has a column CustId,Age,Location and Date. Table B has 2 columns CustId,CustName.
What would be the sql query to show show CustName and Location for a given age?
Thanks.
your question "What would be the sql query to show show CustName and Location for a given age?" helps define your query pretty well:
SELECT CustName, Location
FROM TableA a
INNER JOIN TableB b
ON b.CustId = a.CustId
WHERE a.Age = #
All we need to do on top of that select for your specific fields is make sure to join the two tables on their common column (CustID).
Another option would be to avoid the WHERE statement:
SELECT CustName, Location
FROM TableB b
INNER JOIN TableA a
ON a.CustID = b.CustID
AND a.Age = #
you need join. something like
SELECT custname, location FROM a JOIN b ON a.custid = b.custid WHERE age = [age];

Resources