How to remove common fields in two tables - sql

I have two tables , table 1 and table 2.
The fields of table 1 are :
book,pen,pencil,bag
The fields of table 2 are :
car,van,book,bike,pencil
When I run the query I want the query to ignore the duplicate or common fields and return the other field.
The output should be as follows,
car,van,bike,pen,bag

Perhaps:
SELECT x.thing FROM
(
SELECT thing FROM dbo.Table1
UNION ALL
SELECT thing FROM dbo.Table2
) X
GROUP BY x.thing
Having Count(*) = 1
Demo
However, this will also remove items that are duplicates in their table which might or might not be desired.

Have you tried sth like this:
delete form X
where (car =
Select distinct car
from X
where x);
distinct--> return the differents values.

try this one:
declare #table1 table (col1 varchar(max))
declare #table2 table (col1 varchar(max))
insert into #table1 values
('book'),('pen'),('pencil'),('bag')
insert into #table2 values ('car'),('van'),('book'),('bike'),('pencil')
;with cte
as (
select COUNT(1) as total_item, col1 from (
select col1 from #table1
union all
select col1 from #table2
)a group by col1
)
select col1 from cte where total_item = 1

WITH uniontables AS (
SELECT NULL AS car,
NULL AS van,
book,
NULL AS bike,
pen,
pencil,
bag
FROM [Table 1 ]
UNION
SELECT car,
van,
book,
bike,
NULL AS pen,
pencil,
NULL AS bag
FROM [Table 2 ] )
SELECT DISTINCT * FROM uniontables

Related

Sum union values

I am trying to sum two values across a UNION. Like:
SELECT
sum(target_value) FROM table
UNION ALL
SELECT
sum(target_value) FROM table_2
But rather than getting the 2 sum values, I want them to also be summed.
How should I go about doing this?
You can try using this in a subquery and calculate at the outer query. Ensure you use UNION ALL to evade the duplicate check
SELECT SUM(a) target_value
FROM
(SELECT
sum(target_value) a FROM table
UNION ALL
SELECT
sum(target_value) a FROM table_2) ;
You can use the WITH clause to do this:
WITH CTE AS (SELECT SUM(target_value) as FirstSum
FROM table
UNION
SELECT
SUM(target_value) as FirstSum
FROM table_2)
SELECT SUM(FirstSum) AS TotalSum FROM CTE
Please see the example below:
create table #temp (x int)
create table #temp2 (x2 int)
insert into #temp values (2)
insert into #temp values (3)
insert into #temp2 values (5)
insert into #temp2 values (6)
select t.col1,t.col2,t.col1+t.col2 as Total
from (
SELECT (select sum(x) FROM #temp) as col1,
(select sum(x2) FROM #temp2) as col2
) t

Issue with NOT IN

SELECT *
FROM table -> 35 records
SELECT *
FROM table
WHERE x IN (SELECT x
FROM table1) -> 34 records
SELECT *
FROM table
WHERE x NOT IN (SELECT x
FROM table1) -> 0 records
Any ideas as to how this could be possible?
The simple fix for the NULL value is:
SELECT *
FROM table
WHERE x NOT IN (SELECT x
FROM table1
WHERE x is not null);
However, it is recommended to use not exists rather than not in because of the NULL issue:
select t.*
from table t
where not exists (select 1 from table1 t1 where t1.x = t.x);
One of your x values is NULL. NULL values will never evaluate to true in any comparison (since the value is unknown).
As others have said, 1 of your values is likely to be NULL. You can test for this using IS NULL in your WHERE clause. For example:
SELECT *
FROM MyTable
WHERE MyColumn IS NULL
This simple example would find all records in MyTable that have NULL in MyColumn.
"Any null values returned by subquery or expression that are compared to test_expression using IN or NOT IN return UNKNOWN. Using null values in together with IN or NOT IN can produce unexpected results.
"
NOT/IN MSDN
for a Note, NOT IN is appropriate when you know the number of rows coming from sub-query will remain always small and finite values.
it is not advisable if that list items are uncertain. instead use the LEFT JOIN type query.
EDIT-1 For #John Gibb
DECLARE #t TABLE
(
id INT NULL
)
DECLARE #t1 TABLE
(
id INT NULL
)
INSERT INTO #t (id) SELECT 1 UNION ALL SELECT NULL UNION ALL SELECT 2
INSERT INTO #t1 (id) SELECT 1 UNION ALL SELECT NULL
SELECT *
FROM #t
WHERE id NOT IN (SELECT id FROM #t1)
SELECT *
FROM #t t
LEFT JOIN #t1 t1
ON t.id=t1.id
WHERE t1.id IS NULL
AND t.id IS NOT NULL

SQL select Distinct with where clause

I have i table like this.
PersonID, KvalifikationId
1 1
1 2
1 3
2 1
2 3
I want to write SQL querye returning all persons, that have not kvalifikation 2.
i Wrote
SELECT DISTINCT PersonID where NOT KvalifikationID = 2
But this return both person 1 and person 2.
How do i make select that only return personId's that not have kval2 ?
Try this,
SELECT DISTINCT PersonID
FROM tableName
WHERE PersonID NOT IN
(
SELECT PersonID
FROM tableName
WHERE KvalifikationId = 2
)
SQLFiddle Demo
Declare #t table(PersonID int,KvalifikationId int)
Insert Into #t Select 1 ,1
Insert Into #t Select 1, 2
Insert Into #t Select 1,3
Insert Into #t Select 2 ,1
Insert Into #t Select 2,3
Select PersonId From #t
Except
Select PersonID From #t where KvalifikationId = 2
Result
PersonId
2
By using your Person table rather than your N:N table in the outer query you can skip the distinct and the anti semi join to the sub query will have better performance since it is on a clustered index. (assuming PersonID is pk in the Person table)
SELECT PersonID
FROM tblPerson
WHERE NOT EXISTS
(
SELECT NULL
FROM tblPersonKvalifikation
WHERE KvalifikationId = 2 AND
tblPerson.PersonID = tblPersonKvalifikation.PersonID
)
SELECT DISTINCT person_id
FROM tableName t1
WHERE not exists
(
select 1
from tableName
where person_id = t1.person_id and KvalifikationId = 2
)
try this.
SELECT DISTINCT PersonID from tableName
WHERE KvalifikationId NOT IN ('2');

Select values from a table that are not in a list SQL

If I type:
SELECT name FROM table WHERE name NOT IN ('Test1','Test2','Test3');
I can get the entries from the table that are not in the list. I want to do the opposite: Get the values from the list that are not in the table. For example, if table has a column named name that has the values 'Test1' and 'Test3' I want to compare that to ('Test1','Test2','Test3') and return Test2. Or as another example, if the table is empty, then return everything in the list: Test1, Test2, and Test3.
Is there a way to do this WITHOUT creating a new table with all of the values in the list?
Depending on how many values you have, you could do a few unions.
See: http://www.sqlfiddle.com/#!5/0e42f/1
select * from (
select 'Test 1' thename union
select 'Test 2' union
select 'Test 3'
)
where thename not in (select name from foo)
I usually use SELECT 'FOO' AS COL UNION SELECT 'BAR' etc and then use the standard idiom of left joining and checking for NULL to find missing elements.
CREATE TABLE #YourTable(
name nvarchar(50)
)
insert into #YourTable (name) values ('Test1'), ('Test3')
-- ALL
select * from #YourTable
--MISSING
select t1.* from (
select 'Test1' testName
union select 'Test2'
union select 'Test3') as t1
left outer join #YourTable yt on t1.testName = yt.name
where yt.name is null
DROP TABLE #YourTable
Gives output
name
--------------------------------------------------
Test1
Test3
(2 row(s) affected)
testName
--------
Test2
(1 row(s) affected)
Select a.value from (
SELECT 'testvalue' value UNION
SELECT 'testvalue2' value UNION
SELECT 'testvalue3' value UNION
SELECT 'testvalue4' value UNION
) a
left outer join othertable b
on a.value=b.value
where b.value is null
This is perfect for my problem without temp table#
Assuming "othertable" holds the table in question...
select a.value from
(select 'test1' value
union
select 'test2' value
union
select 'test3' value) a
left outer join othertable b
on a.value=b.value
where b.value is null
In SQL server, the below query works well.
SELECT v.val FROM (VALUES
('A'),
('B'),
('C'),
('D'),
('E')
) v (val)
LEFT JOIN dbo.TABLE_NAME t ON t.COLUMN_NAME = v.val
WHERE t.COLUMN_NAME IS NULL;
Can find the below output:
val
-------
A
B
C
D

How to create a view which merges two tables?

I have two tables which have the exact same structure. Both tables can store the same data with different primary keys (autoincremented integers). Therefore, there is a third table which lists which two primary keys list the same data. However, there also exist rows which don't exist in the other. Therefore, a simple join won't work since you will have two rows with the same primary key but different data. Therefore, is there a way of reassigning primary keys to unused values in the view?
Table1
ID name
1 Adam
2 Mark
3 David
4 Jeremy
Table2
ID name
1 Jessica
2 Jeremy
3 David
4 Mark
Table3
T1ID T2ID
2 4
3 3
4 2
I am looking for a result table like the following:
Result
ID name
1 Adam
2 Mark
3 David
4 Jeremy
5 Jessica
The real heart of the question is how i can assign the temporary fake id of 5 to Jessica and not just some random number. The rule I want for the ids is that if the row exists in the first table, then use its own id. Otherwise, use the next id that an insert statement would have generated (the column is on autoincrement).
Answer to edited question
select id, name from table1
union all
select X.offset + row_number() over (order by id), name
from (select MAX(id) offset from table1) X
cross join table2
where not exists (select * from table3 where t2id = table2.id)
The MAX(id) is used to "predict" the next identity that would occur if you merged the data from the 2nd table into the first. If Table3.T2ID exists at all, it means that it is already included in table1.
Using the test data below
create table table1 (id int identity, name varchar(10))
insert table1 select 'Adam' union all
select 'Mark' union all
select 'David' union all
select 'Jeremy'
create table table2 (id int identity, name varchar(10))
insert table2 select 'Jessica' union all
select 'Jeremy' union all
select 'David' union all
select 'Mark'
create table table3 (t1id int, t2id int)
insert table3 select 2,4 union all
select 3,3 union all
select 4,2
Answer to original question below
So the 3rd table is the one you want to build (a view instead of a table)?
select newid=row_number() over (order by pk_id), *
from
(
select a.*
from tblfirst a
UNION ALL
select b.*
from tblsecond b
) X
The data will contain a unique newid value for each record, whether from first or second table. Change pk_id to your primary key column name.
Assuming you have below data, as I understand reading your question:
Table: T1
ID name
--------
1 a
2 b
3 c
Table: T2
ID name
--------
2 b
3 c
4 d
Table: Rel
ID1 ID2
--------
2 2
3 3
T1 has some data which is not in T2 and vice versa.
Following query will give all data unioned
SELECT ROW_NUMBER() OVER (order by name) ID, Col
from
(
SELECT ISNULL(T1.name,'') name
FROM T1 t1 LEFT JOIN Rel TR ON TR.ID1 = T1.ID
union
SELECT ISNULL(T2.name,'') name
FROM T2 t2 LEFT JOIN Rel TR ON TR.ID2 = T2.ID
) T
If I understand you correct, following might work
Select everything from your first table
Select everything from your second table that is not linked to your third table
Combine the results
Test data
DECLARE #Table1 TABLE (ID INTEGER IDENTITY(1, 1), Value VARCHAR(32))
DECLARE #Table2 TABLE (ID INTEGER IDENTITY(1, 1), Value VARCHAR(32))
DECLARE #Table3 TABLE (T1ID INTEGER, T2ID INTEGER)
INSERT INTO #Table1 VALUES ('Adam')
INSERT INTO #Table1 VALUES ('Mark')
INSERT INTO #Table1 VALUES ('David')
INSERT INTO #Table1 VALUES ('Jeremy')
INSERT INTO #Table2 VALUES ('Jessica')
INSERT INTO #Table2 VALUES ('Jeremy')
INSERT INTO #Table2 VALUES ('David')
INSERT INTO #Table2 VALUES ('Mark')
INSERT INTO #Table3 VALUES (2, 4)
INSERT INTO #Table3 VALUES (3, 3)
INSERT INTO #Table3 VALUES (4, 2)
SQL Statement
SELECT ROW_NUMBER() OVER (ORDER BY ID), t1.Value
FROM #Table1 t1
UNION ALL
SELECT ROW_NUMBER() OVER (ORDER BY ID) + offset, t2.Value
FROM #Table2 t2
LEFT OUTER JOIN #Table3 t3 ON t3.T2ID = t2.ID
CROSS APPLY (
SELECT Offset = COUNT(*)
FROM #Table1
) offset
WHERE t3.T2ID IS NULL