in SQLDeveloper, Build Where clause from excel sheet - sql

I have spread sheet of one column has nearly half million records. To use that single column in a where clause, how smart or easily we can built? FYI - I'm using SQLDEV it allow only 1000 records in a single where clause.
Appreciate your help or suggestion.
Example :
Excel Column - SYS_ID
12
1
3
4
..
..
nearly half million sys_ID, i have to use this SYS_ID in a tableA in the where clause.
select * from tableA where sys_id in (12,1,3,4....)
Please suggest.

In excel, in the next column over, put this formula:
="UNION ALL SELECT "&B1&"
(where B1 is the cell where the first value is)
fill that down.
Now create a table variable:
declare #sysid table (sysid int)
insert into #sysid
-- paste your excel result here
-- remove the first "union all" manually
now you can use :
select * from tableA INNER JOIN #sysid s on sys_id=sysid

Related

Using Excel File in SQL Query Or Batch Select in SQL

I am using ms access database to do some queries at my job. I couldn't find a way to do a bulk select query within this table.
I have a "tblData" table with about 2 million rows. The table looks like this:
ID
Name
Phone
1
Jone Doe
555555555
2
Name2
555555555
3
Name3
555555555
4
Name4
555555555
I have an excel file containing ID of about 800 thousand lines and I am trying to print the name and phone number next to the id's in this excel file. I will use Vba and ADO for this.
What is the easiest way?
The first method I tried was to put the IDs in an array in Excel and use the IN operator in SQL. It took about 5 minutes when I tried with 5000 id. When I tried with more ids, I got an error. I think the reason for the error is that the query string is too long.
qry = "SELECT * FROM tblData WHERE ID IN (" & Join(myBatchLocalList, ", ") & ")"
'myBatchLocalList is array. It include IDs from local excel file.
Another way I can think of is to select all the data, loop it in VBA and print out the matches. However, since the data is 2 million rows, I used ADODB and get an out of memory warning.
There are 2 methods I want try but I can't succeed.
INNER JOIN: First get customer numbers from excel, then query from DB and join 2 tables. However, I do not know whether data is imported from Excel in a query. Like this:
select Local.Id, T.Name, T.Phone
from (select ID from "Column A from xlsx file." ) Local
inner join (select ID, Name, Phone from tblData ) T
on T.ID = Local.ID
INSERT INTO: First, loading the entire list in Excel into a table named tblTemp in the DB with INSERT INTO, then pulling tblTemp again with another query and getting the data from the tblData table using LEFT JOIN. However, I don't know how to implement the insert into part. Like this:
DELETE FROM tblTemp;
INSERT INTO tblTemp VALUES "bulk from Excel Files"
SELECT ID, tblData.Name, tblData.Phone
FROM tblTemp
LEFT JOIN tblData on tblTemp.ID = tblData.ID
I hope I was able to explain clearly. Thanks in advance for any help.

Oracle insert select max + 1 into same table

I thought this would be easy, but i am not able to get my head around this. I want to avoid pl/sql, preferably want this done in plain sql. So in the below sql i am trying to insert into agreement_tbl, by selecting from another table employee_agreement. The employee agreement table returns about 6000 rows. So for each row insert what i want is unique max(agreement_nbr) + 1 inserted in the AGREEMENT_NBR column.
The problem is, since the sql executes first, the max(agreement_nbr) is always the same say 5000, and when i try to insert max(agreement_nbr) it throws 'Unique constraint exception' as it tries to insert value 5000 for all the 6000 inserts. How do i get the unique max+1 for each row from the select query? This is probably like inserting and selection from the same table. Any help is appreciated. Thanks
Edit: This is a one time script, and the agreement_tbl is already populated with thousands of records.
INSERT
INTO
Agreement_tbl
(
AGREEMENT_NBR,
Employee_id,
AGREEMENT_TEXT
)
select
(select max(AGREEMENT_NBR)+1 from Agreement_tbl) as AGREEMENT_NBR,
a.Employee_id ,
a.AGREEMENT_TEXT
from employee_agreement
-- some where conditions
Use rownum instead of +1.
Rownum is 1 for the first row , 2 for the second etc.:
INSERT
INTO
Agreement_tbl
.......
select
rownum + (select max(AGREEMENT_NBR) from Agreement_tbl) as AGREEMENT_NBR,
a.Employee_id ,
a.AGREEMENT_TEXT
from employee_agreement
-- some where conditions

SQL - Finding duplicates based on 3 columns with different data types

SQL noob here, let me know if I'm not wording anything right. I'm trying to find all entries where there is more than one instance of the same data in 3 columns. Below is some sample data from the 3 columns.
formatid type_from call_desc_code
20 002694W0:USAGE V9
20 013030W0:USAGE OM
20 013030W0:USAGE NULL
From what I understand checksum can be used for this but the output from the below query doesn't seem right. The first part of the query that I'm putting into the #temp table has 29824 results which tells me there should be only 29824 unique combinations of the 3 columns but when I've run the full query then tried removing duplicates in Excel based on only those 3 columns to sanity check the results I have a whole lot more then 29824 entries left.
The formatid is a smallint data type so when I've tried just concatenating the cells with + it returns a conversion failed error. I'm running SQL Server 2012 but I don't think the database is on the same as it doesn't recognise the concat function.
select checksum(formatid,type_from,call_desc_code) & checksum(reverse(formatid),reverse(type_from),reverse(call_desc_code)) as [checksum], count(*) as [Blah]
into #temp
from Table
group by checksum(formatid,type_from,call_desc_code) & checksum(reverse(formatid),reverse(type_from),reverse(call_desc_code))
having count(*) > 1
select * from
Table
where checksum(formatid,type_from,call_desc_code) & checksum(reverse(formatid),reverse(type_from),reverse(call_desc_code)) in (select [checksum] from #temp)
drop table #temp
this will get you everything from your source table which has duplicates
select *
from table t
inner join
(select formatid,type_from,call_desc_code
from Table
group by formatid,type_from,call_desc_code
having count(*) > 1) dup
on dup.formatid = t.formatid
and dup.type_from = t.type_from
and dup.call_desc_code = t.call_desc_code

Insert records into a table based on value of a record in another table

I am trying to create a quotation system using Microsoft Access 2013.
Currently, my main issue to trying to write a query that selects all records from a table (itemquote) that have a certain quoteID matching the quoteID coming from another table (currentquote), and then inserts the results into a new table (quoteditems).
Here is a basic example of the tables:
ItemQuote
UniqueID ItemID QuoteID BuyPrice SellPrice
1 1 1 10.00 11.00
2 8 2 07.00 14.00
3 4 5 01.12 03.00
CurrentQuote
CurrentQuoteID
1
My current attempt at writing the query looks like this:
INSERT INTO tblQuotedItems
SELECT *
FROM tblQuoteAsBuiltAndLabelling
INNER JOIN tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;
The resulting error message is "The INSERT INTO statement contains the following unknown field name: 'CurrentQuoteID'. Make sure you have typed the name correctly, and try the operation again." (Error 3127)
What should I do to my query to make it achieve the desired result? Thanks in advance.
The problem may be because your tblQuotedItems does not have the same number of column what your Select Query Returns.
So to resolve this, You can specified individual columns in INSERT Statement, and that will solve your problem.
You can not specify column names in the insert if the columns in the select are in the same order as in the table definition. Possibly, the columns in the current quote might be the same. If so, this might work:
INSERT INTO tblQuotedItems
SELECT tblCurrentQuote.*
FROM tblQuoteAsBuiltAndLabelling INNER JOIN
tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;
However, I strongly recommend that you include column names explicitly when you do inserts:
INSERT INTO tblQuotedItems(col1, col2, . . .)
SELECT col1, col2, . . .
FROM tblQuoteAsBuiltAndLabelling INNER JOIN
tblCurrentQuote
ON tblQuoteAsBuiltAndLabelling.QuoteID = tblCurrentQuote.CurrentQuoteID;

comparing 2 consecutive rows in a recordset

Currently,I have this objective to meet. I need to query the database for certain results. After done so, I will need to compare the records:
For example: the query return me with 10 rows of records, I then need to compare: row 1 with 2, row 2 with 3, row 3 with 4 ... row 9 with 10.
The final result that I wish to have is 10 or less than 10 rows of records.
I have one approach currently. I do this within a function, hand have the variables call "previous" and "current". In a loop I will always compare previous and current which I populate through the record set using a cursor.
After I got each row of filtered result, I will then input it into a physical temporary table.
After all the results are in this temporary table. I'll do a query on this table and insert the result into a cursor and then returning the cursor.
The problem is: how can I not use a temporary table. I've search through online about using nested tables, but somehow I just could not get it working.
How to replace the temp table with something else? Or is there other approach that I can use to compare the row columns with other rows.
EDIT
So sorry, maybe I am not clear with my question. Here is a sample of the result that I am trying to achieve.
TABLE X
Column A B C D
100 300 99 T1
100 300 98 T2
100 300 97 T3
100 100 97 T4
100 300 97 T5
101 11 11 T6
ColumnA is the primary key of the table. ColumnA has duplicates because table X is an audit table that keep tracks of all changes.column D acts as the timestamp for that record.
For my query, I am only interested in changes in column A,B and D. After the query I would like to get the result as below:
Column A B D
100 300 T1
100 100 T4
100 300 T5
101 11 T6
I think Analytics might do what you want :
select col1, col2, last(col1) over (order by col1, col2) LASTROWVALUE
from table1
this way, LASTROWVALUE will contain de value of col1 for the last row, which you can directly compare to the col1 of the current row.
Look this URL for more info : http://www.orafaq.com/node/55
SELECT ROW_NUMBER() OVER(ORDER BY <Some column name>) rn,
Column1, <Some column name>, CompareColumn,
LAG(CompareColumn) OVER(ORDER BY <Some column name>) PreviousValue,
LEAD(CompareColumn) OVER(ORDER BY <Some column name>) NextValue,
case
when CompareColumn != LEAD(CompareColumn) OVER(ORDER BY <Some column name>) then CompareColumn||'-->'||LEAD(CompareColumn) OVER(ORDER BY <Some column name>)
when CompareColumn = LAG(CompareColumn) OVER(ORDER BY <Some column name>) then 'NO CHANGE'
else 'false'
end
FROM <table name>
You can use this logic in a loop to change behaviour.
Hi It's not very clear what exactly yuo want to accomplish. But maybe you can fetch the results of the original query in a PLSQL collection and use that to do your comparison.
What exactly are you doing the row comparison for? Are you looking to eliminate duplicates, or are you transforming the data into another form and then returning that?
To eliminate duplicates, look to use GROUP BY or DISTINCT functionality in your SELECT.
If you are iterating over the initial data and transforming it in some way then it is hard to do it without using a temporary table - but what exactly is your problem with the temp table? If you are concerned about the performance of a cursor then maybe you could do one outer SELECT that compares the results of two inner SELECTs - but the trick is that the second SELECT is offset by one row, so you achieve the requirement of comparing row 1 against row2, etc.
I think you are complicating things with the temp table.
It can be made using a cursor and 2 temporary variables.
Here is the pseudo code:
declare
v_temp_a%xyz;
v_temp_b%xyz;
i number;
cursor my_cursor is select xyz from xyz;
begin
i := 1;
for my_row in my_cursor loop
if (i = 1)
v_temp_a := my_row;
else
v_temp_b := v_temp_a;
v_temp_a := my_row;
/* at this point v_temp_b has the previous row and v_temp_a has the currunt row
compare them and put whatever logic you want */
end if
i := i + 1;
end loop
end