Show Difference between two tables in SQL - sql-server

I have two tables and i want to get the difference between them based on the name and the version of the book:
Table 1
id Name version
1 B5077 A
2 B5077 A
4 B5077 B
5 B5077 C
Table 2
id name version
1 B5077 B
2 B5077 C
3 B5077 D
4 B5077 E
SQL command (the result is really fast comparing to a full Join):
( SELECT name, version FROM table 1 where book = 'B5077'
EXCEPT
SELECT name, version FROM table 2 )
UNION ALL
( SELECT name, version FROM table 2 where book = 'B5077'
EXCEPT
SELECT name, version FROM table 1)
It gives me this output:
id name version
1 B5077 A
2 B5077 D
3 B5077 E
but how i can get the id of the line that has the difference and in which table ? so i can have something like this :
id name version idtable1 idtable2
1 B5077 A 1 NULL
2 B5077 A 2 NULL
3 B5077 D NULL 3
3 B5077 E NULL 4
Thanks,

Just select first the rows on Table 1 not present on Table 2, and then add the rows on Table 2 not present on Table 1.
select Name, Version, id as idtable1, null as idtable2
from Table1
where not exists (select * from Table2 where Table2.Name = Table1.Name and Table2.Version = Table1.version)
union
select Name, Version, null as idtable1, id as idtable2
from Table2
where not exists (select * from Table1 where Table1.Name = Table2.Name and Table1.Version = Table2.version)

Related

How to select the value from the table based on category_id USING SQL SERVER

How to select the value from the table based on category_id?
I have a table like this. Please help me.
Table A
ID Name category_id
-------------------
1 A 1
2 A 1
3 B 1
4 C 2
5 C 2
6 D 2
7 E 3
8 E 3
9 F 3
How to get the below mentioned output from table A?
ID Name category_id
--------------------
1 A 1
2 A 1
4 C 2
5 C 2
7 E 3
8 E 3
Give a row number for each row based on group by category_id and sort by ascending order of ID. Then select the rows having row number 1 and 2.
Query
;with cte as (
select [rn] = row_number() over(
partition by [category_id]
order by [ID]
), *
from [your_table_name]
)
select [ID], [Name], [category_id]
from cte
where [rn] < 3;
Kindly run this query It really help You Out.
SELECT tbl.id,tbl.name, tbl.category_id FROM TableA as tbl WHERE
tbl.name IN(SELECT tbl2.name FROM TableA tbl2 GROUP BY tbl2.name HAVING Count(tbl2.name)> 1)
Code select all category_id from TableA which has Name entries more then one. If there is single entry of any name group by category_id then such data will be excluded. In above example questioner want to eliminate those records that have single Name entity like wise category_id 1 has name entries A and B among which A has two entries and B has single entry so he want to eliminate B from result set.

Order by Specific id first then By rest

Consider a Sample Table with two Column RoleId and User Name
Role | Name
1 AB
3 A
1 ABC
2 D
2 B
3 Abb
1 E
4 TE
How can i use SQL queries to get following Output.
Role | Name
3 A
3 Abb
1 AB
1 ABC
1 E
2 B
2 D
4 TE
I just want to Order by Role Id 3 first then by remaining Roleid.
Currently i am using Union to achieve so //
SELECT * FROM (SELECT * From #temp
Where roleid=3
UNION ALL
SELECT * From #temp
Where roleid != 3
) as X
You can use case to make more complex ordering:
select *
from #temp
order by case when Role = 3 then 0 else 1 end, Role, Name
select *
from #temp
order by CASE WHEN Role = 3 THEN 0 ELSE Role END, Name
I usually use NULLIF, but case might be faster?
SELECT *
FROM #temp
ORDER BY NULLIF(Role,3), Name

Using Recursive CTE with GroupBy

I am new to the recursive CTE concept and a problem at hand, I got a tiny feeling that the problem can be solved by using recursive CTE. Let me know what you guys think.
Two tables:
Table one is a self referencing Location table with ID, ParentID, Level and Description.
Table two is an asset table which records individual assets and has a foreign key to Location table ID field.
Table1:
ID Description ParentID Level
1 Site1 NULL 1
2 Site2 NULL 1
3 Building1 1 2
4 Building2 1 2
5 Floor1 3 3
6 Floor2 3 3
7 Floor3 4 3
8 Place1 5 4
9 Place2 7 4
Table2:
ID Description Quantity LocationID
1 Desk 3 8
2 Lamp 1 8
3 PC 10 9
I would like to create a stored procedure with a input parameter of #Level and returns all the Location records at that level and the number of assets within the location (including sub levels).
For example, if #Level = 3, the stored procedure should return:
ID Description AssetCount
5 Floor1 4
6 Floor2 0
7 Floor3 10
If #Level = 2, the stored procedure should return:
ID Description AssetCount
3 Building1 4
4 Building2 10
If the problem is not clear, please let me know.
Well, nothing special here, just a recursive CTE joined with the other table, and the results are what you expected:
declare #level int = 3
;with CTE as (
select id as origid, id, Description, parentid
from table1 where level = #level
union all
select CTE.origid, t1.id, CTE.Description, t1.parentid
from CTE join table1 t1 on
CTE.id = t1.parentid
)
select origid, CTE.description, isnull(sum(t2.Quantity),0) as Quantity
from CTE left outer join table2 t2 on CTE.id = t2.locationid
group by origid, CTE.description
SQL Fiddle

SQL Update row column with random lookup value

I am trying to update a lead table to assign a random person from a lookup table. Here is the generic schema:
TableA (header),
ID int,
name varchar (30)
TableB (detail),
ID int,
fkTableA int, (foreign key to TableA.ID)
recordOwner varchar(30) null
other detail colums..
TableC (owners),
ID int,
fkTableA int (foreign key to TableA.ID)
name varchar(30)
TableA has 10 entries, one for each type of sales lead pool. TableB has thousands of entries for each row in TableA. I want to assign the correct recordOwners from TableC to and even number of rows each (or as close as I can). TableC will have anywhere from one entry for each row in tableA or up to 10.
Can this be done in one statement? It doesn't have to be. I can't seem to figure out the best approach for speed. Any thoughts or samples are appreciated.
Updated:
TableA has a 1 to many relation ship with TableC. For every record of TableA, TableC will have at least one row, which represents an owner that will need to be assigned to a row in TableB.
TableA
int name
1 LeadSourceOne
2 LeadSourceTwo
TableC
int(id) int(fkTableA) varchar(name)
1 1 Tom
2 1 Bob
3 2 Timmy
4 2 John
5 2 Steve
6 2 Bill
TableB initial data
int(id) int(fkTableA) varchar(recordOwner) (other detail columns)
1 1 NULL ....
2 1 NULL ....
3 1 NULL ....
4 2 NULL ....
5 2 NULL ....
6 2 NULL ....
7 2 NULL ....
8 2 NULL ....
9 2 NULL ....
TableB end result
int(id) int(fkTableA) varchar(recordOwner) (other detail columns)
1 1 TOM ....
2 1 BOB ....
3 1 TOM ....
4 2 TIMMY ....
5 2 JOHN ....
6 2 STEVE ....
7 2 BILL ....
8 2 TIMMY ....
9 2 BILL ....
Basically I need to randomly assign a record from tableC to tableB based on the relationship to tableA.
UPDATE TabB SET name = (SELECT TOP 1 coalesce(tabC.name,'') FROM TabC INNER JOIN TabA ON TabC.idA = TabA.id WHERE tabA.Id = TabB.idA )
Should work but its not tested.
Try this:
UPDATE TableB
SET recordOwner = (SELECT TOP(1) [name]
FROM TableC
ORDER BY NEWID())
WHERE recordOwner IS NULL
I ended up looping thru and updating x percent of the detail records based on how many owners I had. The end result is something like this:
create table #tb_owners(userId varchar(30), processed bit)
insert into #tb_owners(
userId,
processed)
select userId = name,
processed = 0
from tableC
where fkTableA = 1
select #percentUpdate = cast(100 / count(*) as numeric(8,2))
from #tb_owners
while exists(select 1 from #tb_owners o where o.processed = 0)
begin
select top 1
#userFullName = o.name
from #tb_owners o
where o.processed = 0
order by newId()
update tableB
set recordOwner = #userFullName
from tableB ptbpd
inner join (
select top (#percentUpdate) percent
id
from tableB
where recordOwner is null
order by newId()
) nd on (ptbpd.id = nd.id)
update #tb_owners
set processed = 1
where userId = #oUserId
end
--there may be some left over, set to last person used
update tableB
set recordOwner = #userFullName
from tableB
where ptbpd.recordOwner is null

How to get multiple repeated using Joins?

I have a temp table with the following structure:
StudentID VALUE
1 5
2 NULL
and need to map the values from it to the table below:
StudentID DEPT
1 1
1 2
2 3
2 4
So the output should be like this:
StudentID DEPT VALUE
1 1 5
1 2 5
2 3 NULL
2 4 NULL
Do I need to use join or merge my table consisits of million record?
I have tried using joins but i am not getting exact what i need?
a JOIN. like this:
SELECT S.StudentId, S.Dept, V.Value
FROM Student AS S
JOIN #TEMP AS V
ON V.StudentId = S.StudentId
ORDER BY V.StudentId
SELECT table2.StudentID
,table2.DEPT
,#TEMP.Value
FROM table2
LEFT JOIN #TEMP
ON table2.StudentID = #TEMP.StudentID

Resources