Subquery has too many columns - sql

I have two tables with same structure: tmp_grn and grn.
I have to delete rows from table tmp_grn which already exists in table grn.
Problem is I don't have a unique or primary key but I can determine a unique row with the combination of two columns. Let's say column names are grn_code and item_skucode.
My query:
DELETE FROM tmp_grn
WHERE grn_code AND item_skucode IN
(SELECT grn_code , item_skucode FROM grn);
I am getting this error:
ERROR: subquery has too many columns
What should be the right way to do this?

If you want to combine two columns, you need to put them into parenthesis:
DELETE FROM tmp_grn
WHERE (grn_code, item_skucode) IN (SELECT grn_code, item_skucode
FROM grn);
But suslov's answer using an exists is most probably faster - you need to check the execution plan to verify that.

You can use exists (if you want to check the pair of values):
delete from tmp_grn t
where exists ( select *
from grn
where grn_code = t.grn_code
and item_skucode = t.item_skucode);

delete * from tmp_grn intersect select * from grn

Related

Removing duplicates and keeping one copy

I have been going through the threads about removing duplicates from a table and keeping one copy .I have seen an illustration in the case one have a table with composite key.anyone with the idea ?
table contr with composite key checkno,salary_month,sal_year
delete (select * from CONTR t1
INNER JOIN
(select CHECKNO, SALARY_YEAR,SALARY_MONTH FROM CONTR
group by CHECKNO, SALARY_YEAR,SALARY_MONTH HAVING COUNT(*) > 1) dupes
ON
t1.CHECKNO = dupes.CHECKNO AND
t1.SALARY_YEAR= dupes.SALARY_YEAR AND
t1.SALARY_MONTH=dupes.SALARY_MONTH);
I expected one duplicate to be removed and one maintained.
You can use this query below to remove duplicates by using rowid as having a unique valued column :
delete contr t1
where rowid <
(
select max(rowid)
from contr t2
where t2.checkno = t1.checkno
and t2.salary_year = t1.salary_year
and t2.salary_month = t1.salary_month
);
Demo
Another way to achieve this assuming you have dupes with 3 columns you have mentioned is
Create a temp table with distinct values
Drop your table
Rename the temp table
Especially if you are dealing huge volume of data this way would be a lot faster than delete.
If the dup data you are working on is subset of your main table the steps would be
Create a temp table with distinct values
Delete all dup columns from main table
Insert data from temp table to main table
The SQL for the first step would be
create table tmp_CONTR AS
select distinct CHECKNO, SALARY_YEAR,SALARY_MONTH -- this part can be modified to match your needs
from CONTR t1;

Postgres SQL: Find exceptions when using an in clause

I am running the following (Postgres) SQL against a table containing a list of ids. The SQL below will return all the ids found in the list* below.
select id from table
where id in (1,2,3,5,8,11,13,22,34,55);
How can I return ids which are contained in the list but not in the table? I realise I can do this using a temp table (with the list in it) and a left outer join but is there a quicker/cleverer way?
To check if arbitrary ids exist in your table, use a CTE and exists
WITH ids (id) AS ( VALUES (1),(2),(3),(5),(8),(11),(13),(22),(34),(55)
)
SELECT id
FROM ids
WHERE NOT EXISTS(SELECT TRUE FROM table WHERE table.id = ids.id)
note1: alternatively use a left join instead of WHERE NOT EXISTS
note2: it may be necessary to add the appropriate type casts
Or you can use EXCEPT
WITH ids (id) AS ( VALUES (1),(2),(3),(5),(8),(11),(13),(22),(34),(55)
)
SELECT id
FROM ids
EXCEPT ALL
SELECT id FROM ids

Delete records in a table observing its primary keys using a select statement

I'm unable to delete the rows of table A where its keys are WO_NO and ROW_NO.
I wrote the following query but giving an error saying, invalid relational operation.
This is what I tried.
begin
DELETE FROM A
WHERE WO_NO,ROW_NO in (SELECT WO_NO,ROW_NO
FROM G1614617_1
MINUS
SELECT WO_NO,ROW_NO
FROM hirplk_test1);
dbms_output.put_line(SQL%ROWCOUNT);
end;
/
The select query returns the row values WO_NO and ROW_NO. but I cannot delete the records from tab A. Can someone please correct me.
You need to put the two columns between parentheses if you want to compare them with a two column sub-query:
DELETE FROM A
WHERE (WO_NO,ROW_NO) in (SELECT WO_NO,ROW_NO
FROM G1614617_1
MINUS
SELECT WO_NO,ROW_NO
FROM hirplk_test1);

SQL Query to match if data is not present in another table

I have two tables named tblStockManagement and tblFolding in my database. i have column Name in tblFolding table and column FoldingID as Foreign Key in tblStockManagement table. now i have comboBox in my Winform and i want Names of Items in combobox from tblFolding Table but only those items that are not in tblStockManagement Table.
(because i dont want to select data again if it is already in tblStockManagement table . instead i will update the quantity later).
these are the screenshots of both of tables. please tell me how can i do that
NOT EXISTS version:
select *
from tblFolding f
where not exists (select * from tblStockManagement SM
where sm.FoldingID = f.FoldingID)
NOT EXISTS is "NULL safe", which NOT IN isn't.
This is you need.Basically a sub query which gets all folding id and using not in operator I exclude those matching sets.
SELECT Name
FROM tblFolding
WHERE FoldingID NOT IN (
SELECT FoldingID
FROM tblStockManagement
)
;
You can use SQL NOT condition
Select Name
From tblFolding
Where FoldingId Not In (Select FoldingId From tblStockManagement)
Order By Name

Select values from one table depending on referenced value in another table

I have two tables in my SQLite Database (dummy names):
Table 1: FileID F_Property1 F_Property2 ...
Table 2: PointID ForeignKey(fileid) P_Property1 P_Property2 ...
The entries in Table2 all have a foreign key column that references an entry in Table1.
I now would like to select entries from Table2 where for example F_Property1 of the referenced file in Table1 has a specific value.
I tried something naive:
select * from Table2 where fileid=(select FileID from Table1 where F_Property1 > 1)
Now this actually works..kind of. It selects a correct file id from Table1 and returns entries from Table2 with this ID. But it only uses the first returned ID. What I need it to do is basically connect the returned IDs from the inner select by OR so it returns data for all the IDs.
How can I do this? I think it is some kind of cross-table-query like what is asked here What is the proper syntax for a cross-table SQL query? but these answers contain no explaination of what they are actually doing so I'm struggeling with any implementation.
They are using JOIN statements, but wouldn't this mix entries from Table1 and Table2 together while only checking matching IDs in both tables? At least that is how I understand this http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
As you may have noticed from the style, I'm very new to using databases in general, so please forgive me if not everything is clear about what I want. Please leave a comment and I will try to improve the question if neccessary.
The = operator compares a single value against another, so it is assumed that the subquery returns only a single row.
To check whether a (column) value is in a set of values, use IN:
SELECT *
FROM Table2
WHERE fileid IN (SELECT FileID
FROM Table1
WHERE F_Property1 > 1)
The way joins work is not by "mixing" the data, but sort of combining them based on the key.
In your case (I am assuming the key field in Table 1 is unique), if you join those two tables on the primary key field, you will end up with all the entries in table2 plus all corresponding fields from table1. If you were doing this:
select * from table1, table2 where table1.fieldID=table2.foreignkey;
then, providing your key fields are set up right, you will end up with the following:
PointID ForeignKey(fileid) P_Property1 P_Property2 FileID F_Property1 F_Property2
The field values from table1 would be from matching rows.
Now, if you do this:
select table1.* from table 1, table2 where
table1.fieldID=table2.foreignkey and F_Property1>1;
Would essentially get the same set of records, but will only show the columns from the second table, and only those that satisfy the where condition for the first one.
Hope this helps :)
If I understood your question correctly this will get the job done.
Select t2.*
from table1 t1
inner join table2 t2 on t2.id = t1.id
where t1.Prop = 'SomeValue'