Find Set of record rowno from multiple column - sql

I have two sql temp table #Temp1 and #Temp2, and I want to get rowid which contain set of temp table two
E.g. In table Temp2 have 4 record i want to search in temp table #Temp1 which contain userid departmentid set of record
CREATE TABLE #Temp1(rowid INT, userid INT, departmentid int)
CREATE TABLE #Temp2(userid INT, deparetmentid int)
INSERT INTO #Temp1 (rowid,userid,departmentid )
VALUES (1,1,1),(1,2,2),(1,3,3),(1,4,4),(1,2,1),
(2,2,1),(2,2,2),(2,3,3),(2,4,4),
(3,3,1),(3,2,2),(3,3,3),(3,4,4)
INSERT INTO #Temp2 (userid,departmentid )
VALUES (2,1),(2,2),(3,3),(4,4)
DROP TABLE #Temp1
DROP TABLE #Temp2
i want output rowid 2 because it contain set of (2,1),(2,2),(3,3),(4,4)
one thing in rowid also contain same set of record it its have one more row mean
when i search in temp1 table based on rowid 1 then i found 4 record and when i search rowid 2 then it contain 4 record so that it is same set of record which i found
Thanks

You could use:
SELECT rowid
FROM #Temp1 t1
WHERE NOT EXISTS(SELECT userid, departmentid
FROM #Temp1 tx
WHERE tx.rowid=t1.rowid
EXCEPT
SELECT userid, departmentid
FROM #Temp2)
GROUP BY rowid
HAVING COUNT(*) = (SELECT COUNT(*) FROM #Temp2);
Output:
2
Rextester Demo

Let's assume the rows in table1 are unique. Then you can do this using join and group by:
select t1.rowid
from #table1 t1 left join
#table2 t2
on t1.userid = t2.userid and t1.departmentid = t2.departmentid
group by t1.rowid
having count(*) = (select count(*) from #table2 t2) and
count(*) = count(t2.userid) ;
This assumes no duplicates in either table.
Note: This returns rows that are identical to or a superset of the values in the second table.

Related

SQL: JOIN problem using temp tables and one column

I am created two temp tables in which TABLE1 contains all the items and TABLE2 only has the partial list of TABLE1. How can I find out which parts TABLE 1 has that TABLE2 doesn't have or vice versa? Please keep in mind, the temp table only has one column due to the DISTINCT statement.
I do have to use Joins but my thought is if I JOIN on the individual columns of each table and then in the Where clause state that e.g. column 1 is not equal column 2, it's contradicting.
IF EXISTS (
SELECT *
FROM tempdb.dbo.sysobjects
WHERE id = Object_id(N'tempdb..#TABLE1')
)
BEGIN
DROP TABLE #TABLE1
END
IF EXISTS (
SELECT *
FROM tempdb.dbo.sysobjects
WHERE id = Object_id(N'tempdb..#TABLE2')
)
BEGIN
DROP TABLE #TABLE2
END
------------------------------------------------
select distinct 1.parts as #TABLE1 from List1 1 --- MAIN LIST
select distinct 2.parts as #TABLE2 from List2 2 --- ADDITIONAL LIST
select *
from #TABLE2 left join
#TABLE1
on 2.parts = 1.parts
where 2.parts <> 1.parts
Your where clause is undoing the left join. I would recommend not exists:
select t1.*
from #table1 t1
where not exists (select 1 from #table2 t2 where t2.parts = t1.parts);

Insert into each column of a table values based on conditions

I have a table of products like this:
I want to delete duplicate rows in this table and use the Ids in other tables, so I used a temporary table to add just the Ids to delete and the Ids to keep:
-- create tmp table
create table #tmp (ProductId_ToKeep int, ProductId_ToDelete int);
-- collect the Products that have a lower id with the same name in the temp table
insert into #tmp (ProductId_ToKeep)
select [ProductId]
from dbo.[Product] t1
where exists
(
select 1
from dbo.[Product] t2
where t2.name = t1.name
and t2.[ProductId] > t1.[ProductId]
);
-- collect the Products that have a higher id with the same name in the temp table
insert into #tmp (ProductId_ToDelete)
select [ProductId]
from dbo.[Product] t1
where exists
(
select 1
from dbo.[Product] t2
where t2.name = t1.name
and t2.[ProductId] < t1.[ProductId]
);
select * from #tmp
After getting what I have in my temp table, I got this result:
I'm asking if any can one help me to put the Ids in each column as I want.
If I followed you correctly, you could use a window function to feed the transcodification table in a single query, like so:
insert into #tmp (ProductId_ToKeep, ProductId_ToDelete)
select *
from (
select
ProductId ProductId_ToDelete,
min(ProductId) over(partition by name) ProductId_ToKeep
from dbo.[Product]
) t
where ProductId_ToDelete != ProductId_ToKeep
The inner query pulls out the smallest ProductId for the given name; the outer query filters on record that should be deleted (ie whose ProductId is not the minimum ProductId for the same name).

How do i count occurences that were joined SQL

I am joining two tables:
DECLARE #Temp TABLE (
id INT)
INSERT INTO #Temp
VALUES (5)
,(2)
,(3)
DECLARE #Temp2 TABLE (
member_id INT)
INSERT INTO #Temp2
VALUES (5)
,(1)
,(3)
How do i count the number of rows that can be LEFT joined and the ones that can't.
In this example: 5 & 3 from #Temp can be joined to #Temp2 and only 2 from #Temp can't be joined.
I would like my output to show the following:
+--------+------------+
| Joined | Not_Joined |
+--------+------------+
| 2 | 1 |
+--------+------------+
You can do this in a single query using COUNT and SUM. This should produce the results you are looking for.
DECLARE #Temp TABLE (
id INT)
INSERT INTO #Temp
VALUES (5)
,(2)
,(3)
DECLARE #Temp2 TABLE (
member_id INT)
INSERT INTO #Temp2
VALUES (5)
,(1)
,(3)
select Joined = count(t2.Member_id)
, NotJoined = sum(case when t2.Member_id is null then 1 end)
from #Temp t
left join #Temp2 t2 on t2.member_id = t.id
The count from #Temp that EXISTS in #Temp2:
SELECT COUNT(*) FROM #TEMP WHERE ID IN(SELECT MEMBER_ID FROM #TEMP2)
The count from #Temp2 not in #Temp:
SELECT COUNT(*) FROM #TEMP2 WHERE MEMBER_ID NOT IN(ID FROM #TEMP)
Now to create a single result set, there are many ways but here is a simple one:
SELECT
(SELECT COUNT(*) FROM #TEMP2 WHERE MEMBER_ID IN(ID FROM #TEMP)) AS [Joined],
(SELECT COUNT(*) FROM #TEMP WHERE ID NOT IN(SELECT MEMBER_ID FROM #TEMP2)) AS [NotJoined]
#Sean Lange's answer is more specific to the JOIN question, my answer simply counts what exists in the lists.
Select count(*) as 'NOT Joined ',
(Select t1.count(*) from table1
t1)-count(*) as 'Joined'
from table1 where id NOT IN (Select member_id from table2);
Its basically how a left join works that is Common values of both the
tables plus the value of table 1 which doesnt exists in table 2.

My SQL loop takes to long to complete. Is there a better way to do what I'm trying to achieve?

I am trying to de-duplicate a set of data based on certain columns. That is it isn't as easy as just SELECT DISTINCT.
I want to select from my set all rows where a column is unique. I have sorted my set in a way that I just want the loop to grab the first occurrence of the "proxy" key column. I'm saying proxy as it isn't the actual primary key of the table.
I'm using a while loop and using a counter variable based on the count of rows in a temp table. I delete each row from my temp table after processing so this should reduce the base table by the one record which was processed and any duplicate rows.
Although my code works it is seems 'cowboyish' and would like your opinion on how to do it 'cleaner' thanks
Here is my code:
declare #cnt int
set #cnt = (select COUNT(*) from #temp)
while #cnt > 0
begin
select top 1 * into #temp2 from #temp
insert into #temp3 (Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
select #temp2.*
from #temp2
left outer join #temp3 on #temp2.Member_ID = #temp3.Member_ID
where #temp3.Member_ID is null
delete #temp
from #temp
inner join #temp2 on #temp.Member_ID = #temp2.Member_ID
drop table #temp2
set #cnt = (select COUNT(*) from #temp)
end
OPTION 1:
Use below code:
WITH uniqueRecords AS(
SELECT *,ROW_NUMBER()OVER(PARTITION BY T.Member_ID ORDER BY (SELECT 1)) AS RowNum
FROM #Temp AS T
)
INSERT INTO #temp3(Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
SELECT U.Member_ID, U.email, U.meeting_status,U.member_type,U.firstname,U.lastname,U.address1, U.Match_Method, U.Match_Score
FROM uniqueRecords AS U
LEFT OUTER JOIN #temp3 T3 on U.Member_ID = T3.Member_ID
WHERE U.RowNum=1
AND T3.Member_ID is null;
OPTION 2:
i) create UNIQUE INDEX on #temp3 ON Member_ID column WITH IGNORE_DUP_KEY=ON
CREATE UNIQUE INDEX UX_temp3 ON #temp3 (Member_ID) WITH (IGNORE_DUP_KEY=ON);
ii) insert result from left join of #temp and #temp3. duplicates will be ignored by IGNORE_DUP_KEY option
INSERT INTO #temp3(Member_ID, email, meeting_status,member_type,firstname,lastname,address1, Match_Method, Match_Score)
SELECT T.Member_ID, T.email, T.meeting_status,T.member_type,T.firstname,T.lastname,T.address1, T.Match_Method, T.Match_Score
FROM #temp AS T
LEFT OUTER JOIN #temp3 T3 on T.Member_ID = T3.Member_ID
WHERE T3.Member_ID is null;
If I understand your requirement correctly, you want to insert rows from #temp into #temp3, but you want to make sure that only one row from the same Member_ID gets inserted. In that case, you can use ROW_NUMBER and filter for ROW_NUMBER = 1 to make sure that only one row from duplicate Member_IDs will be inserted. Then add a NOT EXISTS filter to avoid inserting already existing rows:
INSERT INTO #temp3 (Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
SELECT
Member_ID,
email,
meeting_status,
member_type,
firstname,
lastname,
address1,
Match_Method,
Match_Score
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER (PARTITION BY Member_ID ORDER BY (SELECT NULL))
FROM #temp
) t
WHERE
t.Rn = 1
AND NOT EXISTS (
SELECT 1
FROM #temp3 t3
WHERE t3.Member_ID = t.MEMBER_ID
)
You do not have to re-count your table every time in a loop. You can simply decrement #cnt.
You should not re-create #temp2 every time in the loop. You can re-use it
You do not have to use #temp2 at all. You can just use select top 1 * from #temp instead
You do not have to use loop at all, just use following script instead:
insert into #temp3(Member_ID, email, meeting_status, member_type, firstname, lastname, address1, Match_Method, Match_Score)
select *
from #temp
where Member_ID not in (select Member_ID from #temp3)

Update table value by adding from other table

Can you please help me out with the below issue?
I have a table like below.
Table-1
Sales_RepID-- Name-- Products_Count
1-- ABC-- 2
2-- XYZ-- 4
3-- XXX-- 3
Table-2
Order_ID-- Sales_RepID-- Products_Count
1001-- 2 -- 2
1002-- 1 -- 1
1003-- 2 -- 1
1004-- 3 -- 3
1005-- 2 -- 2
Table - 1 Result
Sales_RepID, --Name, --Products_Count
1-- ABC --3
2-- XYZ --9
3-- XXX --6
I want to add table-2 Products_Count to Table-1 Products_Count for each Sale_RepID in the table-1
Can you please help with SQL Query?
My database is MS SQL SERVER
For MS SQL Server, please try:
UPDATE T
SET T.Products_Count=T.Products_Count+x.VSum
FROM Table1 T JOIN
(
SELECT DISTINCT
Sales_RepID,
SUM(Products_Count) OVER (PARTITION BY Sales_RepID) VSum
FROM
Table2
)x ON T.Sales_RepID=x.Sales_RepID
create table table1(sales_repId int,name varchar(10),product_count int);
create table table2(order_id int,sales_repId int,product_count int);
insert into table1 values(1,'ABC',2);
insert into table1 values(2,'XYZ',4);
insert into table1 values(3,'XXX',3);
insert into table2 values(1001,2,2);
insert into table2 values(1002,1,1);
insert into table2 values(1003,2,1);
insert into table2 values(1004,3,3);
insert into table2 values(1005,2,2);
select a.sales_repid,name,a.product_count+sum(b.product_count)
from table1 a
inner join table2 b
on a.sales_repid=b.sales_repid
group by a.sales_repid,name,a.product_count
order by a.sales_repid
UPDATE
update table1
set product_count = netProduct
from (
select a.sales_repid,name,a.product_count+sum(b.product_count) as netProduct
from table1 a
inner join table2 b
on a.sales_repid=b.sales_repid
group by a.sales_repid,name,a.product_count
) z
inner join table1 x
on z.sales_repid=x.sales_repid
TRY THIS
DECLARE #TABLE1 AS TABLE( Sales_RepID INT,Name VARCHAR(100), Products_Count int)
DECLARE #TABLE2 AS TABLE( Order_ID INT,Sales_RepID INT, Products_Count int)
INSERT INTO #TABLE1
VALUES(1,'ABC',2),(2,'XYZ',4),(3,'XXX',3)
INSERT INTO #TABLE2
VALUES(1001,2,2),(1002,1,1),(1003,2,1),(1004,3,3),(1005,2,2)
SELECT * FROM #TABLE1
SELECT * FROM #TABLE2
UPDATE T1
SET T1.Products_Count = T1.Products_count + total
FROM #TABLE1 T1
CROSS APPLY (
SELECT total= sum(Products_count)
FROM #Table2 T2
WHERE T1.Sales_RepID =t2.Sales_RepID ) Z
To output as a select:
select
t1.Sales_RepID,
t1.Name,
t1.Products_Count + sum(t2.Products_Count)
from table1 t1
left join table2 t2 on t2.Sales_RepID = t1.Sales_RepID
To update the total in table1, adding the total from table2:
update table1 set
Products_Count = Products_Count + (
select sum(Products_Count)
from table2
where Sales_RepID = table1.Sales_RepID)
These queries will work in all SQL dialects.
MS SQL Server has a special syntax for updating using a join, which will perform much better than the universal update syntax above:
update t1 set
t1.Products_Count = t1.Products_Count + t2.Products_Count
from table1 t1
join (select Sales_RepID, sum(Products_Count) Products_Count
from table2
group by Sales_RepID) t2
on t2.Sales_RepID = t1.Sales_RepID;
See a live demo of this update statement executing on SQLFiddle.
Note that this is an unusual query. Typically, such denormalized values are not cumulative: they are a determinable calculated value, which in this case wold be simply the sum, not the existing value plus the sum. Your design means that the query can only be executed once. After than you'll be repeatedly re-adding the total from table2.
Consider redesigning your tables to have the straight sum from table2 in table1, ie:
update t1 set
t1.Products_Count = t2.Products_Count
from table1 t1
join (select Sales_RepID, sum(Products_Count) Products_Count
from table2
group by Sales_RepID) t2
on t2.Sales_RepID = t1.Sales_RepID;