Fetching multiple rows based on two comparisons in each row - sql

I have a table as follows
col1 col2 col3
a 01/01/2001 1.1
a 01/02/2001 1.2
a 01/03/2001 1.3
b 02/03/2004 2.1
b 02/04/2004 2.2
b 02/05/2004 2.3
I want to be able to fetch rows based on multiple comparisons on each row. That is, fetch rows where I have (a,01/01/2001) and (b,02/05/2004). Something that would look like,
Select * from table where col1,col2 in (('a','01/01/2001'),('b','02/05/2004'))
How can I do this?

SELECT *
FROM table
WHERE
(col1 = 'a' AND col2 = '01/01/2001')
OR
(col1 = 'b' AND col2 = '02/05/2004')

Your original code was so close but not quite there. You just needed to put the fields on the left hand side of the condition in brackets
Select * from table where (col1,col2) in (('a','01/01/2001'),('b','02/05/2004'))

Related

How to check array values using IN operator?

I have a table where each cell in columns has an array list.
COL1 COL2
row1: ('hi','hello') ('hi','hello')
row2: ('hihi','below') ('pi','by')
I am trying to use an in operator on such data but my query is not returning anything.
Query: select * from table where col1 in ('hi')
Also, if I have another table (table2) that looks like this:
col3
____
'hi'
'bye'
'guy'
and I want to use the same concept where I'll be checking if 'hi','bye','guy' from col3 exists in col1 row1
My Query: select * from table2 where col3 in (select col1 from table1);
The first argument is the "inside" one, the second one is the group of values.
You are comparing col1 (a tuple of 2 values) to a unique value:
I think that could help you: col1[0] -> gets the first value
select * from table where col1[0] in ('hi')
Whether you want to compare both, you can use:
select * from table where col1[0] in ('hi') or col1[1] in ('hi')

sql query help, don't know how to term this

I'm not too sure how to term this question. Stay with me.
I want to create a query to retrieve the rows with x's in the row column in the table(this is a dummy table):
row col1 col2 col3
x 1 a c
x 2 b c
x 3 a c
4 b d
x 5 f g
So the way I want my query to work is to retrieve all rows where the value for col2 doesn't have a row in col3 where the value is d. Ie. value 'a' will be retrieved because it only has c's for col3, but value 'b' wont be retrieved because it has a d in col3 on the 4th row down.
I hope this is easy to understand.
Ps. Once I know how to do the query I expect I'll know how to phrase the title and will redo it. (although now I think about it, maybe this title is best for all those with questions like mine)
Based on everything you've provided, I'll have to make a few assumptions. Short of doing a self-join on the table, you could take advantage of an identity key on the table to use a simple query as such:
SELECT * FROM TABLE_NAME
WHERE id NOT IN (SELECT id FROM TABLE_NAME WHERE col3 = 'd');
If you don't have an identity key on the table, you could do something more like this:
SELECT * FROM TABLE_NAME
WHERE col2 NOT IN (SELECT col2 FROM TABLE_NAME WHERE col3 = 'd');
Both of these queries will return all tuples in the relation that have elements of col2 that are not in tuples where col3 contains 'd'.
Think of how you might do this manually, and put that into your query.
To get all the col3 values you'd write:
SELECT DISTINCT col3 FROM TABLE_NAME
Use that to filter rows from your selection via a not in clause:
SELECT
col1, col2, col3 FROM TABLE_NAME
WHERE col2 not in (SELECT DISTINCT col3 FROM TABLE_NAME);

Avoid duplicates on import of updated excel-sheets. Unique-Index can only hold 10 fields max

I am facing the following situation:
I import an Excel-Sheet, then some columns are modified (e.g. "comments")
After a while, I would receive an updated Excel-Sheet containing the records from the old Excel-sheet as well as new ones.
I do not want to import the records that already exist in the database.
Step-by-Step:
Initial Excel-sheet
col1 col2 comments
A A
A B
After import, some fields will get manipulated
col1 col2 comments
A A looks good
A B fine with me
Then I receive an excel sheet with updates
col1 col2 comments
A A
A B
A C
After this update-step, the database should look like
col1 col2 comments
A A looks good
A B fine with me
A C
I was planning to simply create a unique index on all fields that won't get manipulated, so only the new records will get imported. (sth like
ALTER TABLE tbl ADD CONSRAINT unique_key UNIQUE (col1,col2)
My problem now is that Access somehow only allows composite indices of max. 10 fields. My tables all have around 11-20 cols...
I could maybe import the updated xls to a temp. table, and do s.th like
INSERT INTO tbl_old SELECT col1,col2, "" FROM tbl_new WHERE (col1,col2) NOT IN (SELECT col1,col2 FROM tbl_old UNION SELECT col1,col2 FROM tbl_new)
But I'm wondering if there isn't a more straigt-forward way...
Any ideas how I can solve that?
Try the EXISTS condition:
INSERT INTO tbl_old (col1, col2, comments)
SELECT col1, col2, Null
FROM tbl_new
WHERE NOT EXISTS (SELECT col1, col2 FROM tbl_old WHERE tbl_old.col1 = tbl_new.col1 AND tbl_old.col2 = tbl_new.col2);
Considering you will use SQL approach:
INSERT INTO table_old (col1, col2)
SELECT col1, col2 FROM table_new
EXCEPT
SELECT col1, col2 FROM table_old
:)
It will insert null in comments column though. Use this:
INSERT INTO table_old
SELECT * FROM table_new
EXCEPT
SELECT * FROM table_old
to avoid null values. Also both tables have to have the same amount of columns. For Oracle go with minus instead of except. Equivalent SQL query would be made with LEFT OUTER JOIN.
INSERT INTO table_old (col1 , col2)
SELECT N.col1, N.col2
FROM table_new N
LEFT OUTER JOIN table_old O ON O.col2 = N.col2
WHERE O.col2 IS NULL
Which will also provide null values to comments column, as we are inserting only col1 and col2. All inserts tested on provided table examples.
I would just put PK ID column in those tables.

How to remove duplicate values from a table

I'm working on pulling data to a table which has two data sets of data loaded to temp table and finally inserts into table. There are 2 records which are duplicates but i need both the records if their value on one column is same else delete it. Col1 and col4 are primary keys
col1 col2 col3 col4
--------------------
a ab abc x
a ab abc y
b ab abc y
b ab abc z
what i want is forget about col 2 and col3, check in col1 if row 1 and row 2 are same it should go check col4 and if row1 and row 2 are different it should display both row1 and row 2 even if row 2 and row 3 in col4 are same. so if the records are as i mentioned it should allow all 4 values but with the logic i wrote it is returning row1,row3,row4 because it is considering row2 and row3 of col 1 with row 2 row 3 of col 4 and displaying only 3 records but i want all records. Please help me how to write a logic in sql for this situation.
Based on what I have understood from your question, you could do something like this..
DELETE i
FROM YourTable i INNER JOIN
(
SELECT col1,col4
FROM YourTable
GROUP BY col1,col4
HAVING count(col2)>1
) t ON t.col1 = i.col1 AND t.col4 = i.col4
Live Demo Here
Or if ou want to keep only one record and remove other duplicate records, you could do like this..
;with cte as
(
SELECT *,row_number() over(partition by col1,col4 order by col1,col4) as rn
FROM YourTable
)
DELETE from cte where rn>1
Live Demo Here

SQL: How to append IDs to the rows with duplicate values

I have a table with some duplicate rows. I want to modify only the duplicate rows as follows.
Before:
id col1
------------
1 vvvv
2 vvvv
3 vvvv
After:
id col1
------------
1 vvvv
2 vvvv-2
3 vvvv-3
Col1 is appended with a hyphen and the value of id column.
This SQL will only update duplicates, but not the one with the lowest id :
update tbl
set col1 = col1 + '-' + convert(varchar, id)
where exists(select * from tbl t where t.col1 = tbl.col1 and t.id < tbl.id)
Check IN out in Oracle Syntax. The query is not tested
update table1 set
col1 = col1 || id
where
id not in (
select min(id) from table1
groupby col1
)
You might be able to do that with a sproc and cursors. I don't think it's possible in any reasonable select query.
You can accomplish this with a 2 step process, although an SQL wizard could probably modify this to give you a solution in one step.
First you need to get all the duplicate values. Here is an SQL query that will do that:
SELECT COUNT(*) AS NumberOfDuplicates, col1
FROM Table1
GROUP BY col1
HAVING (COUNT(*) > 1)
This will give you a resultset listing the number of duplicates and the duplicate value.
In step 2 you would loop through this resultset, fetch the col1 value, return all the records containing that value and (possibly using a loop counter variable) alter the value as per your example.
Note: you don't really need to return the number of duplicates to achieve your goal, but it will help you to test the query and be satisfied that it works.