Oracle: column ambigously defined - database

I am getting the following error. As far as I can see are all columns defined by table name, so I do not see why I get this error from my Oracle database.
OCIError: ORA-00918: column ambiguously defined: SELECT * FROM (
SELECT raw_sql_.*, rownum raw_rnum_
raw_sql_
WHERE rownum <= 25
)
WHERE raw_rnum_ > 0

Only thing that throws a red flag, the
ORDER BY offsakid desc
You alias one field to that name in your select:
OFFSAK.id offsakid,
But it could be an actual field name on one of your tables, and you should order by the underlying field - not the alias.

Related

SQL Server changes the value in the float column when converting to varchar

I have a column in my table that is of float type. The table was automatically generated when I imported the spreadsheet (Excel) data to my database. Thus there is a column I wish to change from float to varchar, but when I try to do this, I get an error:
'tblInvoices' table
Unable to create index 'IX_tblInvoices'.
The CREATE UNIQUE INDEX statement terminated because a duplicate key was found for the object name 'dbo.tblInvoices' and the index name 'IX_tblInvoices'.
The duplicate key value is (1.00001e+006). The statement has been terminated.
It is a unique column, and set that way (not set as the primary key for reasons). I have already run queries to search for and delete duplicate fields but there are none. The query I ran as follows:
WITH CTE AS
(
SELECT
Invoice,
RN = ROW_NUMBER()OVER(PARTITION BY Invoice ORDER BY Invoice)
FROM
dbo.tblInvoices
)
DELETE FROM CTE
WHERE RN > 1
So the value within the Invoice column is 1000010 and when I run the following query a single row is found.
SELECT *
FROM [TradeReceivables_APR_IFRS9].[dbo].[tblInvoices]
WHERE Invoice = 1.00001e+006
Note that I have searched for the value in the error, 1.00001e+006, and not 1000010.
So my question is why does the DBMS do this? Why does it change the value like that? When I remove the column, it does it with another column and so on and so on (about 40 000 rows in total). How can I change the column from float to varchar without changing the data and getting errors?
Any help will be greatly appreciated!
It seems that the field is an integer so you can Cast it to BIGINT before cast to VARCHAR
Declare #Invoice as float = 1.00001e+006
print cast(#Invoice as varchar) -->> Result : 1.00001e+006
print cast(cast(#Invoice as bigint) as varchar) -->> Result : 1000010

Understanding an ambiguous column name for inner query

I ran into a weird query today that I thought would be failed, but it succeeded in an unexpected way. Here's a minimal reproduction of it.
Tables and data:
CREATE TABLE Employee(ID int, Name varchar(max))
CREATE TABLE Engineer(ID int, Title varchar(max))
GO
INSERT INTO Employee(ID, Name) VALUES (1, 'Bobby')
INSERT INTO Employee(ID, Name) VALUES (2, 'Sue')
INSERT INTO Engineer(ID, Title) VALUES (1, 'Electrical Engineer')
INSERT INTO Engineer(ID, Title) VALUES (2, 'Network Engineer')
Queries:
--Find all Engineers with same title as Bobby has
SELECT * FROM Engineer WHERE Title IN (select Title from Employee WHERE Name = 'Bobby')
This returns all rows in Engineer table (unexpected, I thought it would fail). Note that the above query is incorrect. The inner query uses a column "Title" which doesn't exist in the table being selected from ("Employee"). So it must be binding the Title column value from Engineer in the outer query....which is always equal to itself so all rows are returned I think.
I can force it too if I fully qualify the column name, and that would fail as expected:
SELECT * FROM Engineer WHERE Title IN
(select Empl.Title from Employee Empl WHERE Name = 'Bobby')
This fails with "Invalid column name 'Title'."
Apparently if I were to add the Title column to the Employee table, it uses the Employee.Title column value instead.
ALTER TABLE Employee ADD Title varchar(max)
GO
UPDATE Employee SET Title = 'Electrical Engineer' WHERE ID = 1
UPDATE Employee SET Title = 'Network Engineer' WHERE ID = 2
SELECT * FROM Engineer WHERE Title IN
(select Title from Employee WHERE Name = 'Bobby')
This returns just one row (as expected).
I kind of understand what is happening here, what I'm looking for is a link to some documentation or some keyword that would help me read up and understand it fully (or even some explanation).
Of course it fails. There is no column named Title in your Employee table. In the query that does work it is a subquery so it is pulling Title from Engineer.
You can avoid this entirely if you develop the habit of ALWAYS referencing columns with 2 part naming instead of just the column name.
But in your queries you should start learning how to use joins instead of subqueries for everything. Your code would be far less confusing.
Since Title is not qualified it uses the Title from table Engineer
SELECT * FROM Engineer WHERE Title IN (select Title from Employee WHERE Name = 'Bobby')
In the last it uses the closest Title (from Employee) .
If you use alias and 2 part name then you stay out of this confusion.
As far as documentation. Finding closest column is probably an undocumented feature.
I found the documentation on the behavior: Qualifying Column Names in Subqueries
The general rule is that column names in a statement are implicitly qualified by the table referenced in the FROM clause at the same level. If a column does not exist in the table referenced in the FROM clause of a subquery, it is implicitly qualified by the table referenced in the FROM clause of the outer query.

Determine if columns have duplicate values sql

I am trying to figure out a way to check if their is repeated values in rows that are shared.
Example:
HMOID Name Addon10 Addon15 Addon20
RFFF Blah img path1 img path2 img path1
For my example, I would like to check if any of the addons for RFFF have any repeated value. In my example above, 'RFFF' has two images that are the same in Addon10 and Addon20 (The images have a path. so currently, they look like
http://oc2-reatest.regalmed.local/ocupgrade52/images/NDL_SCAN_SR.PNG).
I would like to be able to do this for multiple rows. I thought the following would give me an idea how to begin:
select * from HlthPlan
Group By HMO1A, HMONM
Having COUNT(*) > 1
However, it throughs the following error:
Msg 8120, Level 16, State 1, Line 1
Column 'HlthPlan.HMOID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.*
I am fairly new to SQL and any suggestions would be appreciated.
Don't include * for your select query. Only include the columns that you are using in GROUP BY
SELECT HMO1A, HMONM, COUNT(*) from HlthPlan
GROUP BY HMO1A, HMONM
HAVING COUNT(*) > 1;
With only three columns to check, assuming non-null values across a single row:
select * from HlthPlan
where Addon10 in (Addon15, Addon20) or Addon15 = Addon20
You can also use cross apply to pivot the values for grouping:
select HMOID, addon
from HlthPlan cross apply (
select addon
from (values (Addon01), (Addon02), (Addon03), ... (Addon20)) as pvt(addon)
) a
where addon is not null
group by HMOID, addon
having count(*) > 1;
http://rextester.com/QWIW87618
You'll get multiple rows for each HMOID where the are different groups of columns having the same value. By the way, reporting on the names of specific columns involved would add another degree of difficulty to the query.
One way you can check for this is using UNPIVOT to compare your results:
create table #hmo (hmoid varchar(6), name varchar(25), Addon10 varchar(25),
Addon15 varchar(25), addon20 varchar(25));
insert into #hmo
values ('RFFF', 'Blah','img path1', 'img path2', 'img path1');
select hmoid, name, addval, addcount = count(adds)
FROM #hmo
UNPIVOT
(
addval FOR adds IN
(addon10, addon15, addon20)
) as unpvt
group by hmoid, name, addval having count(*) > 1
Will give results:
hmoid name addval addcount
RFFF Blah img path1 2
This way you can check against every row in the table and will see any row that has any two or more columns with the same value.
This does have the potential to get tedious if you have a lot of columns; the easiest way to correct for that is to build your query dynamically using info from sys.tables and sys.columns.

vertica: set row number in columns value

Problem: to set row number in columns' value in Vertica.
For example:
Table T has two columns: Id, name
I want to use a script to add the row number in the value of the name. In mySQl, I run the following script to update:
set #i=0;
update T set name = (CONCAT(name, (#i:=#i+1)));
However, Vertica doesn't support variables.
Could you please provide a way to reach the target?
As Vertica supports window functions, something like this can be used to retrieve this data:
select name,
row_number() over (order by name) as rn
from T;
I am not sure how this could be moved into an UPDATE statement though - I don't have a vertica installation available:
update T
set name = name || tx.rn
from (
select id,
row_number() over (order by name) as rn
from T
) as tx
where tx.id = t.id;
I don't know if that qualifies as a "self-join" which isn't allowed. But maybe that points you into the right direction.

SQL Server: select without order

I am using where in condition in SQL Server. I want to get result without order, because I gave a list into the 'where in' condition.
For example
select * from blabla where column in ('03.01.KO61.01410',
'03.02.A081.15002',
'03.02.A081.15016',
'03.02.A081.15003',
'02.03.A081.57105')
How can I do?
If you want the rows returned such that they're in the same order as the items in your IN, you need to find some way to specify that in an ORDER BY clause - the only way to get SQL Server to define an order. E.g.:
select * from blabla where column in ('03.01.KO61.01410',
'03.02.A081.15002',
'03.02.A081.15016',
'03.02.A081.15003',
'02.03.A081.57105')
order by
CASE column
when '03.01.KO61.01410' then 1
when '03.02.A081.15002' then 2
when '03.02.A081.15016' then 3
when '03.02.A081.15003' then 4
when '02.03.A081.57105' then 5
end
Due to my experience, SQL Server randomly order the result set for WHERE-IN Clause if you does not specify how to order it.
So, if you want to order by your WHERE-IN conditions, you must define some data item to order it as you passed. Otherwise, SQL Server will randomly order your resultset.
You're already doing it - if you don't explicitly specify an order by using ORDER BY, then there is no implied order.
If you want to totally randomize the output, you could add an ORDER BY NEWID() clause:
SELECT (list of columns)
FROM dbo.blabla
WHERE column IN ('03.01.KO61.01410', '03.02.A081.15002',
'03.02.A081.15016', '03.02.A081.15003', '02.03.A081.57105')
ORDER BY NEWID()
If you have an autoincrement id in your table, use it in an order clause. And if you don't, consider adding one...
Try this:
CREATE TYPE varchar20_list_type AS TABLE (
id INT IDENTITY PRIMARY KEY,
val VARCHAR(20) NOT NULL UNIQUE
)
DECLARE #mylist varchar20_list_type
INSERT #mylist (val) VALUES
('03.01.KO61.01410'),
('03.02.A081.15002'),
('03.02.A081.15016'),
('03.02.A081.15003'),
('02.03.A081.57105')
SELECT
*
FROM
blabla
JOIN #mylist AS t
ON
blabla.col = t.val
ORDER BY
t.id
More information from http://www.sommarskog.se/arrays-in-sql-2008.html
By the way, this can be easily done in PostgreSQL with VALUES: http://www.postgresql.org/docs/9.0/static/queries-values.html

Resources