union of two table - intersection of two table - sql

I have following tables;
A B A B
_____ _____
1 t 7 a
2 r 5 d
3 e 3 e
4 f 9 a
5 d 10 c
6 s 11 a
7 a
And, output should be ;
A B
_____
1 t
2 r
4 f
6 s
9 a
10 c
11 a
In other words I want really different thing. I can only tell with this figure, take a look at. I want (A union B).
How can I do that ?

This query will do it. It loads up all the records from both tables, then displays all those that exist once
SELECT
A, B
FROM
(SELECT A, B FROM TABLE1
UNION ALL
SELECT A, B FROM TABLE2)
AS COMBINED
GROUP BY
A, B
HAVING
COUNT(*) = 1
ORDER BY A;

SELECT f.A, f.B
FROM firstTable f
LEFT JOIN secondTable s ON (f.A = s.A)
WHERE (s.A IS NULL)
UNION
SELECT s.A, s.B
FROM firstTable f
RIGHT JOIN secondTable s ON (f.A = s.A)
WHERE (f.A IS NULL)

SELECT iResult.*
FROM
(SELECT A, B
FROM tableA
WHERE A NOT IN
(SELECT Distinct A FROM tableB)
UNION
SELECT A, B
FROM tableB
WHERE A NOT IN
(SELECT Distinct A FROM tableB)) as iResult

SELECT A, B
FROM Table1
UNION
SELECT A, B
FROM Table2
EXCEPT
SELECT t1.A, t1.B
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.A = t2.A AND t1.B = t2.B

Edit Removed prior "solution" since I realised it's the same as the one proposed by Gary.
(select a, b from table_1 minus
select a, b from table_2) union
(select a, b from table_2 minus
select a, b from table_1);
This seemed to work with the followoing data on Oracle:
create table table_1 (
a number,
b varchar(2)
);
create table table_2 (
a number,
b varchar(2)
);
insert into table_1 values (1 ,'t');
insert into table_1 values (2 ,'r');
insert into table_1 values (3 ,'e');
insert into table_1 values (4 ,'f');
insert into table_1 values (5 ,'d');
insert into table_1 values (6 ,'s');
insert into table_1 values (7 ,'a');
insert into table_2 values (7 ,'a');
insert into table_2 values (5 ,'d');
insert into table_2 values (3 ,'e');
insert into table_2 values (9 ,'a');
insert into table_2 values (10 ,'c');
insert into table_2 values (11 ,'a');

Simply
SELECT a, b FROM table1 UNION SELECT a, b FROM table2;

Related

How can I override rows from another table?

I have two tables:
TableA
ID Name
-- ----
1 aaa
2 bbb
3 ccc
4 ddd
TableB
ID Name
-- --------
3 WWXXYYZZ
I want to select from both tables, but skip the rows which exist in TableB. The result should look like this:
ID Name
-- --------
1 aaa
2 bbb
3 WWXXYYZZ
4 ddd
I have tried union and join but did not figure out how to achieve this.
-- Did not work
select *
from TableA
union
select *
from TableB
-- Did not work
select *
from
(
select *
from TableA
) x
join
(
select *
from TableB
) y
on x.ID = y.ID
You could left join b on to a, and use coalesce to prefer b's rows:
SELECT a.id, COALESCE(b.name, a.name) AS name
FROM a
LEFT JOIN b ON a.id = b.id
You can do:
select a.id, coalesce(b.name, a.name)
from a left join b on a.id = b.id
One method is union all:
select b.*
from b
union all
select a.*
from a
where not exists (select 1 from a where a.id = b.id);
You can also choose from a and override with values from b:
select a.id, coalesce(b.name, a.name) as name
from a left join
b
on a.id = b.id;
A more complex method uses ROW_NUMBER which might be necessary if your query is significantly more complex than shown. It also handled the case where a row exists in TableB but not TableA (which is not clear from your question).
DECLARE #TableA TABLE (id INT, [Name] VARCHAR(12));
DECLARE #TableB TABLE (id INT, [Name] VARCHAR(12));
INSERT INTO #TableA (id, [Name])
VALUES
(1, 'aaa'),
(2, 'bbb'),
(3, 'ccc'),
(4, 'ddd');
INSERT INTO #TableB (id, [Name])
VALUES
(3, 'WWXXYYZZ'),
(5, 'TTTGGG');
SELECT id, [Name]
FROM (
SELECT id, [Name]
, ROW_NUMBER() OVER (PARTITION BY id ORDER BY [Priority] DESC) Rn
FROM (
SELECT id, [Name], 0 [Priority]
FROM #TableA
UNION ALL
SELECT id, [Name], 1 [Priority]
FROM #TableB
) X
) Y
WHERE Rn = 1;
Returns:
1 aaa
2 bbb
3 WWXXYYZZ
4 ddd
5 TTTGGG

count of row by row from another table holding some conditions on both tables in sql

There are two tables Table1 and Table2
A B C S
a 1 21 Summer
b 2 22 Summer
c 3 34 Summer
D E F S
a 1 21 Summer
d 5 22 Summer
f 2 34 Summer
I wanted to fetch all columns of Table first and count of column F from table second based on conditions such as column B OF table first is less than values of column E of table second.
I tried this query
select a.*,
(select count(F) from Table2 JOIN Table1 on table1.S=table2.S where table1.B<table2.E ) AS Cnt
from Table1 a
However it is giving me same count for all rows which is incorrect
I need count based on condition fulfilled.
This will work
DECLARE #T1 TABLE (A Varchar(10), B INT, C INT, S Varchar(10))
DECLARE #T2 TABLE (D Varchar(10), E INT, F INT, S Varchar(10))
INSERT INTO #T1 VALUES
('a', 1, 21,'Summer'),
('b', 2 ,22,'Summer'),
('c', 3, 34,'Summer')
INSERT INTO #T2 VALUES
('a', 1, 21,'Summer'),
('d', 5 ,22,'Summer'),
('f', 2 ,34,'Summer')
SELECT
T1.A,T1.B,T1.C,T1.S,
COUNT(T2.S) as Counts
FROM #T1 T1
left JOIN #T2 T2
ON T1.S = T2.S AND T1.B < T2.E
GROUP BY T1.A,T1.B,T1.C,T1.S
Output
A B C S Counts
a 1 21 Summer 2
b 2 22 Summer 1
c 3 34 Summer 1
select *,
(select count(F)
from T2
where T1.S = T2.S AND T1.B < T2.E
) as Cnt from T1
I think you just want a correlated subquery:
select a.*,
(select count(t2.F)
from Table2 t2
where a.S = t2.S and t1.B < t2.E
) as Cnt
from Table1 a

SQL Statement with 3 select statements

I am trying to combine the data of three tables but running into a minor issue.
Let's say we have 3 tables
Table A
ID | ID2 | ID3 | Name | Age
1 2x 4y John 23
2 7j Mike 27
3 1S1 6HH Steve 67
4 45 O8 Carol 56
Table B
| ID2 | ID3 | Price
2x 4y 23
7j 8uj 27
x4 Q6 56
Table C
|ID | Weight|
1 145
1 210
1 240
2 234
2 110
3 260
3 210
4 82
I want to get every record from table A of everyone who weighs 200 or more but they cannot be in table B. Table A and C are joined by ID. Table A and B are joined by either ID2 or ID3. ID2 and ID3 don't both have to necessarily be populated but at least 1 will. Either can be present or both and they will be unique. So expected result is
3 | 1S1 | 6HH | Steve| 67
Note that a person can have multiple weights but as long as at least one record is 200 or above they get pulled.
What I have so far
Select *
From tableA x
Where
x.id in (Select distinct y.id
From tableA y, tableC z
Where y.id = z.id
And z.weight >= '200'
And y.id not in (Select distinct h.id
From tableA h, tableB k
Where (h.id2 = k.id2 or h.id3 = k.id3)))
When I do this it seems to ignore the check on tableB and I get John, Mike and Steve. Any ideas? Sorry it's convoluted, this is what I have to work with. I am doing this in oracle by the way.
This sounds like exists and not exists. So a direct translation is:
select a.*
from tableA a
where exists (select 1 from tableC c where c.id = a.id and c.weight >= 200) and
not exists (select 1 from tableB b where b.id2 = a.id2 or b.id3 = a.id3);
Splitting the or into two separate subqueries can often improve performance:
select a.*
from tableA a
where exists (select 1 from tableC c where c.id = a.id and c.weight >= 200) and
not exists (select 1 from tableB b where b.id2 = a.id2) and
not exists (select 1 from tableB b where b.id3 = a.id3);
Here's what I came up with.
SELECT DISTINCT
A.ID,
A.ID2,
A.ID3,
A.Name,
A.Age
FROM
A
LEFT OUTER JOIN C ON C.ID = A.ID
LEFT OUTER JOIN B ON
B.ID2 = A.ID2
OR B.ID3 = A.ID3
WHERE
C.Weight >= 200
AND B.Price IS NULL
BELOW is test data
CREATE TABLE A
(
ID INT,
ID2 VARCHAR(3),
ID3 VARCHAR(3),
Name VARCHAR(10),
Age INT
);
INSERT INTO A VALUES (1, '2x', '4y', 'John', 23);
INSERT INTO A VALUES (2, '7j', NULL , 'Mike', 27);
INSERT INTO A VALUES (3, '1S1', '6HH', 'Steve', 67);
INSERT INTO A VALUES (4, '45', 'O8', 'Carol', 56);
CREATE TABLE B
(
ID2 VARCHAR(3),
ID3 VARCHAR(3),
Price INT
);
INSERT INTO B VALUES ('2x', '4y', 23);
INSERT INTO B VALUES ('7j', '8uj', 27);
INSERT INTO B VALUES ('x4', 'Q6', 56);
CREATE TABLE C
(
ID INT,
Weight INT
);
INSERT INTO C VALUES (1, 145);
INSERT INTO C VALUES (1, 210);
INSERT INTO C VALUES (1, 240);
INSERT INTO C VALUES (2, 234);
INSERT INTO C VALUES (2, 110);
INSERT INTO C VALUES (3, 260);
INSERT INTO C VALUES (3, 210);
INSERT INTO C VALUES (4, 82);
Select a.id, a.id2, a.id3
From table_a a
Left join table_c c on a.id = c.id
Where c.weight >=200
And not exists
(Select 1
From table_b b
Where a.id = b.id2
Or a.id = b.id3
);
I was beating to the answers, but I used INNER JOIN on tables a and c and a NOT EXISTS on table b.
--This first section is creating the test data
with Table_A (id, id2, id3, Name, age) as
(select 1, '2x', '4y', 'John', 23 from dual union all
select 2, '7j', null, 'Mike', 27 from dual union all
select 3, '1S1', '6HH', 'Steve', 67 from dual union all
select 4, '45', 'O8', 'Carol', 56 from dual),
Table_B(id2, id3, price) as
(select '2x', '4y', 23 from dual union all
select '7j', '8uj', 27 from dual union all
select 'x4', 'Q6', 56 from dual),
Table_C(id, weight) as
(select 1, 145 from dual union all
select 1, 210 from dual union all
select 1, 240 from dual union all
select 2, 234 from dual union all
select 2, 110 from dual union all
select 3, 260 from dual union all
select 3, 210 from dual union all
select 4, 82 from dual)
--Actual query starts here
select distinct a.*
from table_a a
--join to table c, include the weight filter
inner join table_c c on (a.id = c.id and c.weight >= 200)
where not exists -- The rest is the NOT EXISTS to exclude the values in table b
(select 1 from table_b b
where a.id2 = b.id2
or a.id3 = b.id3);

Query to count the entries

I have two tables like this.
A B
1 12
2 13
3 12
4 13
5 15
B C
12 APPLE
13 ORANGE
14 MANGO
15 BANANA
I need output as below...
count(A) B C
2 12 APPLE
2 13 ORANGE
0 14 MANGO
1 15 BANANA
I have written the query using joins but I am stuck at displaying the count as zero in case of empty value.
Use a left join to get the values of table2 even if there are no records for them in table1
select T2.B, T2.C, count(T1.A)
from table2 T2
left join table1 T1 on T1.B = T2.B
group by T2.B, T2.C
Try this:
SELECT COUNT(T1.A) as Cnt,T2.B,T2.C
FROM Table2 T2 LEFT JOIN
Table1 T1 ON T1.B=T2.B
GROUP BY T2.B,T2.C
Result:
CNT B C
2 12 APPLE
1 15 BANANA
0 14 MANGO
2 13 ORANGE
See result in SQL Fiddle.
Just to give you another option. You don't need a join, as you only want to show table2 records along with another value which you can get in a sub-query.
select (select count(*) from table1 where table1.B = table2.B) as cnt, B, C
from table2
order by B;
There are other ways to do it (using subquery), but I would use this following one:
-- SETUP
CREATE TABLE #TABLE1 (A INT, B INT);
CREATE TABLE #TABLE2 (B INT, C CHAR(10));
INSERT #TABLE1
SELECT 1, 12 UNION ALL
SELECT 2, 13 UNION ALL
SELECT 3, 12 UNION ALL
SELECT 4, 13 UNION ALL
SELECT 5, 15
INSERT #TABLE2
SELECT 12, 'APPLE' UNION ALL
SELECT 13, 'ORANGE' UNION ALL
SELECT 14, 'MANGO' UNION ALL
SELECT 15, 'BANANA'
-- query
SELECT COUNT(qty.A), dsc.B, dsc.C
FROM #TABLE2 dsc
LEFT JOIN #TABLE1 qty ON (dsc.B = qty.B)
GROUP BY dsc.B, dsc.C
ORDER BY dsc.B, dsc.C;
DECLARE #TABLE1 TABLE (A INT, B INT)
INSERT INTO #TABLE1 VALUES
(1, 12),
(2, 13),
(3, 12),
(4, 13),
(5, 15)
DECLARE #TABLE2 TABLE (B INT, C VARCHAR(20))
INSERT INTO #TABLE2 VALUES
(12,'APPLE'),
(13,'ORANGE'),
(14,'MANGO'),
(15,'BANANA')
SELECT t2.C
,ISNULL(COUNT(t1.B), 0) total_Count
FROM #TABLE2 t2 LEFT JOIN #TABLE1 t1
ON t2.B = t1.B
GROUP BY t2.C
C total_Count
APPLE 2
BANANA 1
MANGO 0
ORANGE 2

taking difference of tables

I have following tables;
A B A B
_____ _____
1 t 7 a
2 r 5 d
3 e 3 e
4 f
5 d
6 s
7 a
And, output should be ;
A B
_____
1 t
2 r
4 f
6 s
In other words I want difference of these two tables . I want region A in this figure.
How can I do that ?
Try this:
SELECT t1.*
FROM t1
LEFT JOIN t2 USING (A, B)
WHERE t2.A IS NULL
without using JOIN
SELECT A, B
FROM tableA
WHERE A NOT IN
(SELECT Distinct A FROM tableB)
This should do the trick:
SELECT
A,
B
FROM Table_1
WHERE NOT EXISTS
(
SELECT Table_2.A AS Test
FROM Table_2
INNER JOIN Table_1 AS T ON Table_2.A = Table_1.A
)
SELECT A, B
FROM Table1
EXCEPT
SELECT A, B
FROM Table2;