I have two tables like below:
table1:
StoreId SKU
------------
1 abc
2 abc
3 abc
1 xyz
4 xyz
table2:
StoreId
--------
1
2
3
4
5
I want to select missing storeid from the table1 which are in table 2. But condition is that in above example for SKU abc storeid 4 and 5 are missing and for sku xyz 2,3,5 are missing. So I want below table as output
SKU,ID
------
abc 4
abc 5
xyz 2
xyz 3
xyz 5
I am able to pull only the overall missing store which is 5 using below query.
SELECT
SKU, t2.StoreId
FROM
#table1 t1
FULL OUTER JOIN
#table2 t2 ON t1.StoreId = t2.StoreId
WHERE
t1.StoreId IS NULL
Below is test create and insert query.
Declare #table1 As table
(
StoreId varchar(4),
SKU varchar(5)
)
Declare #table2 As table
(
StoreId int
)
BEGIN
Insert Into #table1(SKU,StoreId) values('abc',1)
Insert Into #table1(SKU,StoreId) values('abc',2)
Insert Into #table1(SKU,StoreId) values('abc',3)
Insert Into #table1(SKU,StoreId) values('xyz',1)
Insert Into #table1(SKU,StoreId) values('xyz',4)
Insert Into #table2(StoreId) values(1)
Insert Into #table2(StoreId) values(2)
Insert Into #table2(StoreId) values(3)
Insert Into #table2(StoreId) values(4)
Insert Into #table2(StoreId) values(5)
END
Thank you
You need to get a list of all skus and tables, and then show only rows which do not appear in table1:
select SKU, StoreID
from #table2 t2
cross join (select distinct sku from #table1) t1
where not exists (select 1 from #table1 table1
where table1.SKU = t1.SKU
and table1.StoreId = t2.StoreId)
Here is an alternative solution with the same result.
Syntax is very similar to the answer from #BeanFrog:
SELECT
t3.SKU, t2.StoreID
FROM
#table2 t2
CROSS JOIN
(SELECT distinct SKU
FROM #table1) t3
LEFT JOIN
#table1 t1
ON
t1.SKU = t3.SKU
and t1.StoreId = t2.StoreId
WHERE
t1.sku is null
Related
I am using SQL Database. I am having three tables like T1,T2,T3. I want to get a column values from a table by excluding the values exists in another table.
SELECT T3 THEN
SELECT T2 NOT in T3 THEN
SELECT T1 NOT in T3 and T2
CREATE TABLE T1(CID INT,NAME VARCHAR(100),EMAIL VARCHAR(50), MOIBLE VARCHAR(20))
CREATE TABLE T2(CID INT,NAME VARCHAR(100),EMAIL VARCHAR(50), MOIBLE VARCHAR(20))
CREATE TABLE T3(CID INT,NAME VARCHAR(100),EMAIL VARCHAR(50), MOIBLE VARCHAR(20))
Insert value
INSERT INTO T1 VALUES (1,'TEST1','a#gmail','123456')
INSERT INTO T1 VALUES (2,'TEST2','b#gmail','123456')
INSERT INTO T1 VALUES (3,'TEST3','c#gmail','123456')
INSERT INTO T1 VALUES (4,'TEST4','d#gmail','123456')
INSERT INTO T2 VALUES (1,'TEST1','updateda#gmail','123456')
INSERT INTO T2 VALUES (2,'TEST2','updatedb#gmail','77777')
INSERT INTO T3 VALUES (1,'TEST1','updateda#gmail','999999')
Expected output
SELECT T3 and
SELECT T2 record NOT in T3 and
SELECT T1 record NOT in T3 and T2
cid Name email moible
1 TEST1 updateda#gmail 999999 From T3
2 TEST2 updatedb#gmail 77777 From T2
3 TEST3 c#gmail 123456 From T1
4 TEST4 d#gmail 123456 From T1
I have written query for this
SELECT * FROM T2 where cid not in ( SELECT cid from T3)
UNION
SELECT * FROM T3
Here How to include T1 table?
You can add anther 1 union cid not in T2 and T3
SELECT * from T1 where cid not in(SELECT cid FROM T2 where cid not in ( SELECT
cid from T3)
UNION
SELECT cid FROM T3)
UNION
SELECT * FROM T2 where cid not in ( SELECT cid from T3)
UNION
SELECT * FROM T3
This is the Scenario : I have a duplicate rows in my table with the same Id , Name and so on .
1) I have to find the duplicate row matching all the criteria ( this is done)
2) Delete them only if the criteria match
3) Use the id of the deleted record and update the existing row in the table
For this i have created a 2 temp table. Temp1 is the table with all the record. Temp2 consist of duplicated row.
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
DROP TABLE #Temp1
IF OBJECT_ID('tempdb..#Temp2') IS NOT NULL
DROP TABLE #Temp2
IF OBJECT_ID('tempdb..#Temp3') IS NOT NULL
DROP TABLE #Temp3
CREATE Table #Temp1 (
Id int,
Name NVARCHAR(64),
StudentNo INT NULL,
ClassCode NVARCHAR(8) NULL,
Section NVARCHAR(8) NULL,
)
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(1,'Joe',123,'A1', 'I')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(1,'Joe',123,'A1', 'I')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(2,'Harry',113,'X2', 'H')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(2,'Harry',113,'X2', 'H')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(3,'Elle',121,'J1', 'E1')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(3,'Elle',121,'J1', 'E')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(8,'Jane',191,'A1', 'E')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(5,'Silva',811,'S1', 'SE')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(6,'Juan',411,'S2', 'SE')
INSERT INTO #Temp1 (Id, Name,StudentNo,ClassCode,Section) Values(7,'Carla',431,'S2', 'SE')
;WITH CTE AS (
select
ROW_NUMBER() over (partition by Id
, StudentNo
order by Id, StudentNo)as Duplicate_RowNumber
, * from #Temp1 )
select t1.Id,t1.Name,t1.StudentNo,t1.Section,t1.ClassCode
INTO #Temp2
from CTE as c INNER JOIN #Temp1 as t1 ON t1.Id = c.Id
and t1.StudentNo = t1.StudentNo
and c.Duplicate_RowNumber >1
-- this will have 6 rows all the duplicates are included
--select * from #Temp2
-- this is for output clause
DECLARE #inserted Table (Id int,
Name NVARCHAR(64),
StudentNo INT NULL,
ClassCode NVARCHAR(8) NULL,
Section NVARCHAR(8) NULL)
DELETE FROM #temp1
OUTPUT deleted.Id , deleted.Name ,deleted.StudentNo ,deleted.ClassCode ,deleted.Section into #inserted
WHERE EXISTS ( SELECT * FROM #Temp2 as t2
where #temp1.Id = t2.Id
and #temp1.Name = t2.Name
and #temp1.StudentNo = t2.StudentNo
and #temp1.ClassCode = t2.ClassCode
and #temp1.Section = t2.Section)
-- this is to check what is delete so that i can join it and update the table temp1
select * from #inserted
You can see below the query should not delete the last two highlighted column because the Section does not match. It should only delete matching criteria from Temp1 and Temp2.
Scenario 2 : Delete the duplicate record in Temp1 and use the key in order to update the data to NULL for Section and Classcode . This is what i expect with the highlighted to be NULLs .
You can run this query yourself - just copy and paste.
Yes, for scenario #1 it is going to delete the rows because the problem is in this section.
I added this table for references.
Added this #temp2 table to clarify for later use.
CREATE Table #Temp2 (
Id int,
Name Varchar(64),
StudentNo INT NULL,
ClassCode Varchar(8) NULL,
Section Varchar(8) NULL,
)
IF OBJECT_ID('tempdb..#tmp4') IS NOT NULL
DROP TABLE #tmp4
select t1.Id,t1.Name,t1.StudentNo,t1.Section,t1.ClassCode,
Duplicate_RowNumber
INTO #Duplicatedata
from CTE as c INNER JOIN #Temp1 as t1 ON t1.Id = c.Id
and t1.StudentNo = t1.StudentNo
and c.Duplicate_RowNumber >1
select * from #Duplicatedata
This is going to satisfy both condition as #temp 1 will have both rows for Elle as your join condition is only on ID and Student No.
I added row number column for clarity.
Id Name StudentNo Section ClassCode Duplicate_RowNumber
1 Joe 123 I A1 2
1 Joe 123 I A1 2
2 Harry 113 H X2 2
2 Harry 113 H X2 2
3 Elle 121 E1 J1 2
3 Elle 121 E J1 2
As your Partition is based by Student No and ID, every duplicate row will have 2 or more row numbers.
You can use this approach to delete.
select
ROW_NUMBER() over (partition by Id
, StudentNo
order by Id, StudentNo, section)as Duplicate_RowNumber
, * into #tmp4 from #Temp1
--You can add section in your order as well for consistency purpose.
delete
from #tmp4
output deleted.id, deleted.Name, deleted.StudentNo, deleted.ClassCode,
deleted.Section into #Temp2
where Duplicate_RowNumber > 1
After that it seems like you want to keep one row in your final table and put the other one in you deleted table. For Elle it will delete one of the rows from Final table and keep only one since your partition is not based on section.
To make sure that you delete 1 row from your final table you can use this.
DELETE t
OUTPUT deleted.Id , deleted.Name ,deleted.StudentNo ,deleted.ClassCode
,deleted.Section into #inserted FROM
(select *, row_number() over (Partition by tm.name, tm.studentNo Order by ID,
StudentNo, section ) rownum from #temp1 tm) t
join #Temp2 t2 on t.Id = t2.Id
and t.Name = t2.Name
and t.StudentNo = t2.StudentNo
and t.ClassCode = t2.ClassCode
and t.Section = t2.Section
where t.rownum > 1
If you notice I added this row number, so that it will not two delete the rows from final table, since Joe and Harry has all the matching attributes, and it will delete two rows.
select * from #inserted
Output you get:
Id Name StudentNo ClassCode Section
3 Elle 121 J1 E1
2 Harry 113 X2 H
1 Joe 123 A1 I
Finally you can update final table in this way. #Scenario 2
update TMP
SET ClassCode = NULL, SECTION = NULL
FROM
#Temp1 TMP
JOIN #INSERTED I ON TMP.Id = I.Id
AND TMP.StudentNo = I.StudentNo
SELECT * FROM #Temp1
Final Output:
Id Name StudentNo ClassCode Section
1 Joe 123 NULL NULL
2 Harry 113 NULL NULL
3 Elle 121 NULL NULL
8 Jane 191 A1 E
5 Silva 811 S1 SE
6 Juan 411 S2 SE
7 Carla 431 S2 SE
Please note that I have added scripts and output only for the parts where it required change, and rest part is same script provided by you.
I have two tables like below.
table 1
id rem
1 2
2 1
table 2
id value
1 abc
1 xyz
1 mno
2 mnk
2 mjd
EDIT:
#output
id value
1 abc
1 xyz
2 mnk
What i want to do is select top 2 rows of table2 with id one as rem value is 2 for id 1 and top 1 row with id 2 as its rem value is 1 and so on. I am using MS sqlserver 2012 My whole scenario is more complex than this. Please help.
Thank you.
EDIT : I know that i should have given what i have done and how i am doing it but for this particular part i don't have idea for starting. I could do this by using while loop for each unique id but i want to do it in one go if possible.
First, SQL tables represent unordered sets. There is no specification of which values you get, unless you include an order by.
For this purpose, I would go with row_number():
select t2.*
from table1 t1 join
(select t2.*,
row_number() over (partition by id order by id) as seqnum
from table2 t2
) t2
on t1.id = t2.id and t2.seqnum <= t1.rem;
Note: The order by id in the windows clause should be based on which rows you want. If you don't care which rows, then order by id or order by (select null) is fine.
Try This:
DECLARE #tbl1 TABLE (id INT, rem INT)
INSERT INTO #tbl1 VALUES (1, 2), (2, 1)
DECLARE #tbl2 TABLE (id INT, value VARCHAR(10))
INSERT INTO #tbl2 VALUES (1, 'abc'), (1, 'xyz'),
(1, 'mno'), (2, 'mnk'), (2, 'mjd')
SELECT * FROM #tbl1 -- your table 1
SELECT * FROM #tbl2 -- your table 2
SELECT id,value,rem FROM ( SELECT ROW_NUMBER() OVER (PARTITION BY T.ID ORDER BY T.ID) rowid,
T.id,T.value,F.rem FROM #tbl2 T LEFT JOIN #tbl1 F ON T.id = F.id ) A WHERE rowid = 1
-- your required output
Hope it helps.
Hi stackoverflow community,
I'm trying to do a self join if the unique ID in Col 1 is the same.
Table code:
CREATE TABLE #table (
Unique_ID int, Product_code varchar(10)
)
INSERT INTO #table (Unique_ID, Product_code) VALUES (1111111111, 1)
INSERT INTO #table (Unique_ID, Product_code) VALUES (1111111111, 2)
INSERT INTO #table (Unique_ID, Product_code) VALUES (1111111111, 3)
INSERT INTO #table (Unique_ID, Product_code) VALUES (2222222222, 4)
INSERT INTO #table (Unique_ID, Product_code) VALUES (2222222222, 4)
INSERT INTO #table (Unique_ID, Product_code) VALUES (3333333333, 5)
INSERT INTO #table (Unique_ID, Product_code) VALUES (3333333333, 6)
INSERT INTO #table (Unique_ID, Product_code) VALUES (3333333333, 6)
INSERT INTO #table (Unique_ID, Product_code) VALUES (3333333333, 3)
#table Input:
Unique_ID Product_code
1111111111 1
1111111111 2
1111111111 3
2222222222 4
2222222222 4
3333333333 5
3333333333 6
3333333333 6
3333333333 3
Desired #table Output:
Unique_ID Product_code Product_code1 Product_code2 Product_code3
1111111111 1 2 3 (Null)
2222222222 4 4 (Null) (Null)
3333333333 5 6 6 3
Current code (Unsure how to compare each row by Unique_ID):
SELECT t1.Unique_ID, t1.Product_code, t2.Product_code AS [Product_code1]
FROM #temp AS t1
JOIN #temp AS t2 ON t1.Unique_ID = t2.Unique_ID
ORDER BY t1.Unique_ID
Any hints and/or help would be much appreciated thanks
Try this. You'll need an intermediate step to relate the different value through an identical column:
select *, seq=identity(int) into #temp from #table order by Unique_ID, Product_code
go
SELECT t1.Unique_ID, t1.Product_code as p1, t2.Product_code as p2, t3.Product_code as p3, t4.Product_code as p4
FROM #temp AS t1
LEFT JOIN #temp AS t2 ON t1.Unique_ID = t2.Unique_ID and t2.seq = t1.seq+1
LEFT JOIN #temp AS t3 ON t2.Unique_ID = t3.Unique_ID and t3.seq = t2.seq+1
LEFT JOIN #temp AS t4 ON t1.Unique_ID = t4.Unique_ID and t4.seq = t3.seq+1
where t1.seq = (select min(seq) from #temp where Unique_ID = t1.Unique_ID)
ORDER BY t1.Unique_ID
go
Since you want 3 product codes per result row, you must do a 3-way self join. Right now you have a 2-way self join, so you must join with #table once more
I have two tables as below:
Table1:
Col1 Col2
834 2
834 3
834 5
877 1
877 2
877 5
900 10
900 2
900 3
Table2:
Col3
1
10
Expected Output:
Col1 Col3
834 1
834 10
877 10
900 1
This is what I have done so far:
select distinct t1.Col1,A.Col3
from Table1
cross apply
(select * from Table2 left join Table1 on Col2 = Col3) A
order by t1.Col1,A.Col3
I have been trying lot using join, cross apply and other sql function to get me the expected output. Any help is appreciated.
Logic:
I want to get the values of Col1 of Table1 for which Col3 does not matches with col2 of Table1.
For Eg: Values 1 and 10 of Col3 of table2 is not there for value 834 of col1 of table1. Hence there are two rows for 834, one with value 1 and other with 10.
Please try with the below code snippet.
DECLARE #Table1 TABLE(
Col1 INT NOT NULL,
Col2 INT NOT NULL
);
INSERT INTO #Table1 VALUES(834 , 2)
INSERT INTO #Table1 VALUES(834 , 3)
INSERT INTO #Table1 VALUES(834 , 5)
INSERT INTO #Table1 VALUES(877 , 1)
INSERT INTO #Table1 VALUES(877 , 2)
INSERT INTO #Table1 VALUES(877 , 5)
INSERT INTO #Table1 VALUES(900 , 10)
INSERT INTO #Table1 VALUES(900 , 2)
INSERT INTO #Table1 VALUES(900 , 3)
DECLARE #Table2 TABLE(
Col3 INT NOT NULL
);
INSERT INTO #Table2 VALUES(1)
INSERT INTO #Table2 VALUES(10)
SELECT a.Col1,a.Col3 FROM (SELECT DISTINCT a.Col1,b.Col3 FROM #Table1 a,#Table2 b
WHERE a.Col2 <> b.Col3) a
LEFT JOIN #Table1 c on a.Col1 = c.Col1 and a.Col3 = c.Col2
WHERE c.Col1 is null
I doubt you need any join in here. All you want to select from table1 are the rows with matching value in table2. Something like this :
Select distinct col1, col2 from table1
Where col2 not in (select col3 from table2)
select a.col1, a.col2
from Table1 a
where not exists(select * from Table2 b where a.col1 = b.col3)
This may work...