I have the following tables
Table A Table B Table C
ColumnA ColumnB ColumnA ColumnB ColumnA ColumnB
1 A 2 X X Value1
2 B 3 Y Y Value2
3 C 5 Z Z Value3
4 D
5 E
The result required is
Column1 Column2 Column3
1 A
2 Value1 B
3 Value2 C
4 D
5 Value3 E
I have been playing with the left outer join. But still not getting close to the result I am looking for. Any help is appreciated.
You need to use the LEFT JOIN twice:
CREATE table tablea (
columna NUMBER,
columnb VARCHAR2(1)
);
CREATE table tableb (
columna NUMBER,
columnb VARCHAR2(1)
);
CREATE table tablec (
columna VARCHAR2(1),
columnb VARCHAR2(10)
);
INSERT INTO tablea VALUES (1, 'A');
INSERT INTO tablea VALUES (2, 'B');
INSERT INTO tablea VALUES (3, 'C');
INSERT INTO tablea VALUES (4, 'D');
INSERT INTO tablea VALUES (5, 'E');
INSERT INTO tableb VALUES (2, 'X');
INSERT INTO tableb VALUES (3, 'Y');
INSERT INTO tableb VALUES (5, 'Z');
INSERT INTO tablec VALUES ('X', 'Value1');
INSERT INTO tablec VALUES ('Y', 'Value2');
INSERT INTO tablec VALUES ('Z', 'Value3');
COMMIT;
SELECT ta.columna, tc.columnb, ta.columnb
FROM tablea ta
LEFT JOIN tableb tb ON (ta.columna = tb.columna)
LEFT JOIN tablec tc ON (tc.columna = tb.columnb)
ORDER BY 1
;
Output:
COLUMNA COLUMNB COLUMNB
---------- ---------- -------
1 A
2 Value1 B
3 Value2 C
4 D
5 Value3 E
SQLFiddle demo
Related
I have a following tables
table1
id name
1 A
3 B
table2
id label value
1 tag a
1 tag b
1 time 10
1 time 20
1 score 20
2 tag a
2 time 30
2 score 40
3 tag b
3 time 50
3 time 55
3 score 60
first I'd like to join table2 as follows
select *
from table1 left join on table2 using(id)
where label in ('tag')
id name tag
1 A a
1 A b
3 B b
and then join table2 with id and pivot and sum up them
id name tag time score
1 A a 10 20
1 A b 10 20
3 B b 50 60
I guess it is very complicated, are there any way to achieve this?
In Redshift it seems that there is no way to pivot them.
Thanks.
This looks to be a pivot query. I think this does what you are looking for:
create table table1 (id int, name varchar(16));
insert into table1 values
(1, 'A'),
(3, 'B')
;
create table table2 (id int, label varchar(16), value varchar(16));
insert into table2 values
(1, 'tag', 'a'),
(1, 'tag', 'b'),
(1, 'time', '10'),
(1, 'score', '20'),
(2, 'tag', 'a'),
(2, 'time', '30'),
(2, 'score', '40'),
(3, 'tag', 'b'),
(3, 'time', '50'),
(3, 'score', '60')
;
select t2.id, a.name, a.tag_value, sum(decode(label, 'time', value::int)) as total_time, sum(decode(label, 'score', value::int)) as total_score
from table2 t2
join (
select id, name, value as tag_value
from table1 t1 left join table2 t2 using(id)
where t2.label in ('tag')
) a
on t2.id = a.id
group by 1, 2, 3
order by 1, 2, 3
;
I want to join two same tables with different data for the same primary key value.
I am performing a full join between the two tables, as I want to see what information has changed for the same ID between two months. I tried using a group by clause as well, but that didn't work.
Select
a.ID, a.Value1,
b.Value
from
TableA a
full join
TableB b on a.ID = b.ID
Input data:
Table A Table B
ID Value ID Value
--------- ----------
1 A 1 A
1 B 1 B
2 A 1 C
Desired output:
ID VALUE1 Value2
-----------------
1 A A
1 B B
1 Null C
Current (wrong) output:
ID VALUE1 Value2
-----------------
1 A A
1 A B
1 A C
1 B A
1 B B
1 B C
I suspect that ALL combinations are desired, thus FULL Join is better.
Select Case When a.ID IS Null Then b.ID Else a.ID End as ID,
a.Value,
b.Value
from UnequalRowsTableA a
full join UnequalRowsTableB b on a.ID=b.ID and a.Value = b.Value
Results
ID Value Value
1 A A
1 B B
2 A NULL
1 NULL C
You can use TableB in FROM then TableA in LEFT JOIN and in your ON clause add the Value matching too, to achieve your expected result:
SELECT B.ID,
A.Value AS Value1,
B.Value AS Value2
FROM TableB B
LEFT JOIN TableA A ON A.ID = B.ID AND A.Value = B.Value;
Demo with sample data:
DECLARE #TableA TABLE (ID INT, [Value] VARCHAR (1));
INSERT INTO #TableA (ID, [Value]) VALUES
(1, 'A'), (1, 'B'), (2, 'A');
DECLARE #TableB TABLE (ID INT, [Value] VARCHAR (1));
INSERT INTO #TableB (ID, [Value]) VALUES
(1, 'A'), (1, 'B'), (1, 'C');
SELECT B.ID,
A.[Value] AS Value1,
B.[Value] AS Value2
FROM #TableB B
LEFT JOIN #TableA A ON A.ID = B.ID AND A.[Value] = B.[Value];
Output:
ID Value1 Value2
----------------------
1 A A
1 B B
1 NULL C
Suppose I have the following (very simplified) schema / data set up in SQL Server:
CREATE TABLE #Ids1 (Id1 VARCHAR(1));
CREATE TABLE #Vals1 (Id1 VARCHAR(1), Id2 VARCHAR(1));
CREATE TABLE #Ids2 (Id1 VARCHAR(1));
CREATE TABLE #Vals2 (Id1 VARCHAR(1), Id2 VARCHAR(1));
INSERT INTO #Ids1 (Id1) VALUES ('a'), ('b'), ('c'), ('d');
INSERT INTO #Vals1 (Id1, Id2) VALUES ('a', '1'), ('b', '2'), ('c', '3'), ('d', '4');
INSERT INTO #Ids2 (Id1) VALUES ('a'), ('b'), ('c'), ('e'), ('f'), ('g');
INSERT INTO #Vals2 (Id1, Id2) VALUES ('a', '1'), ('b', '2'), ('c', '3'), ('e', '5'), ('f', '6'), ('g', '7');
Basically, I have 2 similar datasets - One ending with a 1 suffix, the other ending with a 2 suffix and there is a chance either of the datasets may have data that is not in the other set.
What I would like to do is create a query that returns a single joined dataset that would look as follows:
#Ids1.Id1 #vals1.Id1 #vals1.Id2 #Ids2.Id1 #Vals2.Id1 #Vals2.Id2
a a 1 a a 1
b b 2 b b 2
c c 3 c c 3
d d 4 NULL NULL NULL
NULL NULL NULL e e 5
NULL NULL NULL f f 6
NULL NULL NULL g g 7
I figured the following SQL would accomplish this:
SELECT
*
FROM
#Ids1
FULL JOIN #Vals1
ON #Vals1.Id1 = #Ids1.Id1
FULL JOIN #Ids2
ON #Ids2.Id1 = #Ids1.Id1
FULL JOIN #Vals2
ON #Vals2.Id1 = #Ids2.Id1
AND #Vals2.Id2 = #Vals1.Id2
but it is separating out the last tables rather than joining them, so it ends up looking as follows:
#Ids1.Id1 #vals1.Id1 #vals1.Id2 #Ids2.Id1 #Vals2.Id1 #Vals2.Id2
a a 1 a a 1
b b 2 b b 2
c c 3 c c 3
d d 4 NULL NULL NULL
NULL NULL NULL e NULL NULL
NULL NULL NULL f NULL NULL
NULL NULL NULL g NULL NULL
NULL NULL NULL NULL e 5
NULL NULL NULL NULL f 6
NULL NULL NULL NULL g 7
I've created a link to the prepared Schema and the SQL at the following URL:
http://rextester.com/SAX53638
I'm guessing / hoping I'm just missing something simple, but I just can't seem to get it to work. What's the best way to return the data I want?
Join the tables internally and then join again
Try using the below the query
SELECT
*
FROM
(SELECT
Ids1.Id1 AS Id11,
vals1.Id1 AS Idv11,
vals1.Id2 AS Idv12
FROM
Ids1
FULL JOIN Vals1
ON Vals1.Id1 = Ids1.Id1) Ivs1
FULL JOIN
(SELECT
Ids2.Id1 AS Id21,
vals2.Id1 AS Idv21,
vals2.Id2 AS Idv22
FROM
Ids2
FULL JOIN Vals2
ON Vals2.Id1 = Ids2.Id1) Ivs2
ON Ivs1.Id11 = Ivs2.Id21;
Let's consider two tables:
First:
Id Data
1 asd
2 buu
And Second:
UPD:
Id Data
10 ffu
11 fffuuu
10001 asd
I want to get a 4-column table looking like this:
Id1 Data1 Id2 Data2
1 asd 10 fuu
2 buu 11 fffuuu
-1 [any text] 10001 asd
(if the numbers of rows are not equal ,let's use "-1" for the id)
How to do this?
I'm using sqlite3-3.7.3.
UPD2:
There is no matching criteria between tables,any random matching between them will be sufficient for me.
Assuming that the id columns are unique and not null, you can "zip" your tables by:
Creating a row number for each row that corresponds to the
position of the row when the table is ordered by the unique id (as
polishchuk mentioned in his comment); and,
Simulating a FULL OUTER JOIN with 2 LEFT OUTER JOINS.
To demonstrate, I used two tables with differing row counts:
CREATE TABLE foo (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT);
INSERT INTO foo VALUES (NULL, 'a');
INSERT INTO foo VALUES (NULL, 'b');
INSERT INTO foo VALUES (NULL, 'c');
INSERT INTO foo VALUES (NULL, 'd');
INSERT INTO foo VALUES (NULL, 'e');
INSERT INTO foo VALUES (NULL, 'f');
INSERT INTO foo VALUES (NULL, 'g');
INSERT INTO foo VALUES (NULL, 'h');
INSERT INTO foo VALUES (NULL, 'i');
INSERT INTO foo VALUES (NULL, 'j');
DELETE FROM foo WHERE data IN ('b', 'd', 'f', 'i');
CREATE TABLE bar (id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT);
INSERT INTO bar VALUES (NULL, 'a');
INSERT INTO bar VALUES (NULL, 'b');
INSERT INTO bar VALUES (NULL, 'c');
INSERT INTO bar VALUES (NULL, 'd');
INSERT INTO bar VALUES (NULL, 'e');
INSERT INTO bar VALUES (NULL, 'f');
INSERT INTO bar VALUES (NULL, 'g');
INSERT INTO bar VALUES (NULL, 'h');
INSERT INTO bar VALUES (NULL, 'i');
INSERT INTO bar VALUES (NULL, 'j');
DELETE FROM bar WHERE data IN ('a', 'b');
To obtain a more readable output, I then ran:
.headers on
.mode column
Then you can execute this SQL statement:
SELECT COALESCE(id1, -1) AS id1, data1,
COALESCE(id2, -1) as id2, data2
FROM (
SELECT ltable.rnum AS rnum,
ltable.id AS id1, ltable.data AS data1,
rtable.id AS id2, rtable.data AS data2
FROM
(SElECT (SELECT COUNT(*) FROM foo
WHERE id <= T1.id) rnum, id, data FROM foo T1
) ltable
LEFT OUTER JOIN
(SElECT (SELECT COUNT(*) FROM bar
WHERE id <= T1.id) rnum, id, data FROM bar T1
) rtable
ON ltable.rnum=rtable.rnum
UNION
SELECT rtable.rnum AS rnum,
ltable.id AS id1, ltable.data AS data1,
rtable.id AS id2, rtable.data AS data2
FROM
(SElECT (SELECT COUNT(*) FROM bar
WHERE id <= T1.id) rnum, id, data FROM bar T1
) rtable
LEFT OUTER JOIN
(SElECT (SELECT COUNT(*) FROM foo
WHERE id <= T1.id) rnum, id, data FROM foo T1
) ltable
ON ltable.rnum=rtable.rnum)
ORDER BY rnum
Which gives you:
id1 data1 id2 data2
---------- ---------- ---------- ----------
1 a 3 c
3 c 4 d
5 e 5 e
7 g 6 f
8 h 7 g
10 j 8 h
-1 9 i
-1 10 j
This works "both ways", for example, if you invert the two tables (foo and bar), you get:
id1 data1 id2 data2
---------- ---------- ---------- ----------
3 c 1 a
4 d 3 c
5 e 5 e
6 f 7 g
7 g 8 h
8 h 10 j
9 i -1
10 j -1
i'm joining tables like:
select * from tableA a full join tableB b on a.id = b.id
But the output should be:
row without null fields
row with null fields in tableB
row with null fields in tableA
Like:
a.id a.name b.id b.name
5 Peter 5 Jones
2 Steven 2 Pareker
6 Paul null null
4 Ivan null null
null null 1 Smith
null null 3 Parker
create table a(id number, name varchar2(10));
insert into a(id, name) values(5, 'Peter');
insert into a(id, name) values(2, 'Steven');
insert into a(id, name) values(6, 'Paul');
insert into a(id, name) values(4, 'Ivan');
create table b(id number, name varchar2(10));
insert into b(id, name) values(5, 'Jones');
insert into b(id, name) values(2, 'Pareker');
insert into b(id, name) values(1, 'Smith');
insert into b(id, name) values(3, 'Parker');
select * from a full join b on a.id = b.id
order by
case
when a.id is not null and b.id is not null then 0
when a.id is not null and b.id is null then 1
when a.id is null and b.id is not null then 2
else 3
end
;