insert multiple rows from select statement in sql - sql

I have a table that need to be migrate to new table.
Table A migrates to Table B
Table A
| ID | type |
| A1 | A |
| A2 | B |
| A3 | A |
| A4 | both |
| A5 | A |
and I hope the table B will look like this
Table B
| ID | FKA | TYPE |
| B1 | A1 | Aa |
| B2 | A2 | Bb |
| B3 | A3 | Aa |
| B4 | A4 | Aa |
| B5 | A4 | Bb |
| B6 | A5 | Aa |
If you realized that if type is both, it will insert two times in table B from table A.
**FKA is the foreign key from table A
Currently I do 3 queries
query 1:
insert into tableB
select sequence1.nextVal, ID,
(case
when type = 'A' then 'Aa'
when type = 'B' then 'Bb'
when type = 'both' then 'Aa'
else NULL
end
) from tableA
query 2
insert into tableB
select sequence1.nextVal, ID,
(case
when type = 'both' then 'Bb'
else 'laterdelete'
end
) from tableA
query 3
delete from tableB where type = 'laterdelete'
thanks guys

I assume the rdbms is Oracle. You might want to create a table (e.g. "tablemapping") with these values
FieldFrom FieldTo
A Aa
B Bb
both Aa
both Bb
So you could do just:
Insert into tableB
select sequence1.nextval, ID, FieldTo
FROM tableA a
join tablemapping m
on a.type=m.fieldFrom
If you don't want to have a mapping table you can simulate one.
Insert into tableb
select sequence1.nextval, ID, FieldTo
FROM tableA a
join (
select 'both' as FieldFrom, 'Ab' as FieldTo from dual
Union all
select 'both' as FieldFrom, 'Bb' as FieldTo from dual
Union all
select 'A' as FieldFrom, 'Aa' as FieldTo from dual
Union all
select 'B' as FieldFrom, 'Bb' as FieldTo from dual
) tablemapping m
on a.type=m.fieldFrom

You can use union in your first query to achieve the desired result in tableB.
Query would be as given below:
insert into tableB
select sequence1.nextVal, ID,
(case
when type = 'A' then 'Aa'
when type = 'B' then 'Bb'
when type = 'both' then 'Aa'
else NULL
end
) from tableA
UNION
select sequence1.nextVal, ID,
(case
when type = 'A' then 'Aa'
when type = 'B' then 'Bb'
when type = 'both' then 'Bb'
else NULL
end
) from tableA
The above query will insert Aa and Bb in tableB when type is both in tableA.
Hope this helps.

Related

Presto SQL group by COL1 and concat COL2 values

Say I have this
col_1 | col_2
------------
1 | a
1 | b
1 | c
2 | d
2 | e
I want result like this
col_1 | col_2_concat
-------------------
1 | a,b,c
2 | d,e
something like this I would guess:
select
col_1,
join_by_comma(col2)
from tbl
group by col_1
I think you need something like:
WITH x AS (
SELECT
'a' AS c,
'b' AS c2
UNION ALL
SELECT
'a',
'b2'
UNION ALL
SELECT
'a2',
'b3'
UNION ALL
SELECT
'a2',
'b4'
)
SELECT
c,
ARRAY_JOIN(ARRAY_AGG(c2), ',') as c2
FROM x
GROUP BY
c

Get Count of records - Oracle

I'm trying to get count of records from table by joining 2 or more table. Suppose I have 3 table like follows,
Table A
Column 1 Column 2
121 XX
123 XX
124 A0
125 A2
126 XX
Table B
Column 1
A0
A1
A2
A3
Table C
Column 1 Column 2
121 A0
122 A1
123 A0
124 A0
125 A2
126 A3
From these I need count result as follows,
Column 1 Column 2
XX,A0 2
XX,A1 0
XX,A2 0
XX,A3 1
A0,A0 1
A1,A1 0
A2,A2 1
A3,A3 0
Here I have 121 and 123 with XX in table A and same 121,123 in table C with A0, so count should be 2. Similarly 124 have A0 in table A and A0 in table C, so count should 1 and if no record matched with any column 2 it should have 0.
I tried with below query it is not returing as expected,
select b.column2 ||','|| c.column2 column , count(a.column1) count
from table A a
join table c c
on a.column1=c.column1
join table b b
on b.column1=c.column2
group by b.column2 ||','|| c.column2
order by b.column2 ||','|| c.column2
first you would want a cartesian product to get the set of all possible combinations betweeen tablea and tableb. I changed the column names to something more readable.
create table tablea(id int, name varchar2(10));
create table tableb(name varchar2(10));
create table tablec(id int, name varchar2(10));
insert into tablea
select 121,'XX' from dual union all
select 123,'XX' from dual union all
select 124,'A0' from dual union all
select 125,'A2' from dual union all
select 126,'XX' from dual
insert into tableb
select 'A0' from dual union all
select 'A1' from dual union all
select 'A2' from dual union all
select 'A3' from dual
insert into tablec
select 121,'A0' from dual union all
select 122,'A1' from dual union all
select 123,'A0' from dual union all
select 124,'A0' from dual union all
select 125,'A2' from dual union all
select 126,'A3' from dual
--Gets all possible combination of tablea and tableb
select distinct a.name as a_name,b.name as b_name
from tablea a
join tableb b
on 1=1
Then you would do a group by on these combination fields as follows
with data
as (select distinct a.name as a_name,b.name as b_name
from tablea a
join tableb b
on 1=1
)
,tablec_data
as (select c.name c_name,a.name a_name
from tablec c
join tablea a
on c.id=a.id
)
select max(m.a_name||','||m.b_name) as val_name,count(n.c_name) as cnt
from data m
left join tablec_data n
on m.a_name=n.a_name
and m.b_name=n.c_name
group by m.a_name,m.b_name
order by m.a_name desc,m.b_name
Here is a db fiddle link
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=9e573822ecc1087e5871c80b586d1116
+----------+-----+
| VAL_NAME | CNT |
+----------+-----+
| XX,A0 | 2 |
| XX,A1 | 0 |
| XX,A2 | 0 |
| XX,A3 | 1 |
| A2,A0 | 0 |
| A2,A1 | 0 |
| A2,A2 | 1 |
| A2,A3 | 0 |
| A0,A0 | 1 |
| A0,A1 | 0 |
| A0,A2 | 0 |
| A0,A3 | 0 |
+----------+-----+
Table A should be used instead of Table B for combining the values. Table B doesn't have column Colunn2.
Also, Remember alias name for a.column2 ||','|| c.column2 should not be column as this is reserved keyword in oracle. So you can use column2 or something else.
EDIT: Following will give 0 count for not matched records.
select t1.column2,
case when t2.count1 is not null then t2.count1 else t1.count1 end as count1
from (
(select distinct a.column2||','||b.column1 as column2,
0 as count1 from tableA a join tableB b on a.column2='XX'
union
select distinct c.column2||','||b.column1 as column2,
0 as count1 from tableC c join tableB b on c.column2=b.column1
)t1
left join
(select a.Column2 ||','|| c.Column2 as column2,
count(*) count1 from TableA a join TableC c on a.column1=c.column1
join TableB B on b.column1=c.column2 group by a.column2 ||','|| c.column2
)t2
on t1.column2=t2.column2
)
order by
t1.column2
Output:
A0,A0 1
A1,A1 0
A2,A2 1
A3,A3 0
XX,A0 2
XX,A1 0
XX,A2 0
XX,A3 1
At first prepare key columns, use simple union. Then use this keys to construct join. Left join is used because we need zeros too:
with keys as (select 'XX' ka, column1 kb from b union all select column1, column1 from b)
select ka, kb, sum(case when c.column2 is not null then 1 else 0 end) cnt
from keys
left join a on ka = a.column2
left join c on kb = c.column2 and a.column1 = c.column1
group by ka, kb
order by ka, kb
dbfiddle demo

Combining select and select union in SQL Server

I have 2 tables
Table A with 3 columns : ID, NAME, VALUE 1
Table B with 3 columns : ID, NAME, VALUE 2
Table A :
ID : A1, A2
NAME: AAA, BBB
VALUE 1 : 1000,2000
Table B :
ID : B1, B2
NAME: CCC,DDD
VALUE 1 : 3000,4000
And I want to show the result like this :
ID, NAME, VALUE 1, VALUE 2
A1 AAA 1000
A2 BBB 2000
A3 CCC 3000
A4 DDD 4000
I have tried union and it works for id, name column. What about regular select + union select, is it possible ?
You can use union all:
select id, name, value1, null as value2
from a
union all
select id, name, null as value1, value2
from b;
online demonstration
MS SQL Server 2017 Schema Setup:
CREATE TABLE Table1
([ID] varchar(2), [NAME] varchar(3), [VALUE1] int)
;
INSERT INTO Table1
([ID], [NAME], [VALUE1])
VALUES
('A1', 'AAA', 1000),
('A2', 'BBB', 2000)
;
CREATE TABLE Table2
([ID] varchar(2), [NAME] varchar(3), [VALUE2] int)
;
INSERT INTO Table2
([ID], [NAME], [VALUE2])
VALUES
('B1', 'CCC', 3000),
('B2', 'DDD', 4000)
;
Query 1:
select id, name, value1, null as value2
from table1
union all
select id, name, null as value1, value2
from table2
Results:
| id | name | value1 | value2 |
|----|------|--------|--------|
| A1 | AAA | 1000 | (null) |
| A2 | BBB | 2000 | (null) |
| B1 | CCC | (null) | 3000 |
| B2 | DDD | (null) | 4000 |
You can also use Full Outer Join
SELECT a.id, a.name, a.value1, b.value2
FROM tableA as a
FULL OUTER JOIN tableB AS b ON
a.id = b.id

How to join two tables when there's no coincidence?

I have two tables that I want to join. I've tried an usual left and right join but neither gives the result I want.
TABLE A
ID_A VALUE_A
-----------------
A 1
B 2
TABLE B
ID_B ID_A VALUE_B
-------------------------
90 A 1
90 C 1
90 E 1
91 A 1
91 B 1
92 B 1
92 E 1
92 F 1
I want to get this result:
ID_A VALUE_A ID_B ID_A VALUE_B
-------------------------------------------------
A 1 90 A 1
B 2 90 NULL NULL
A 1 91 A 1
B 2 91 B 1
A 1 92 NULL NULL
B 2 92 B 1
If I understand correctly, you want all combinations of id_a and value_a from the first table along with all distinct id_b from the second table. If so:
select iv.id_a, iv.value_a, ib.id_b, b.id_a, b.value_b
from (select distinct id_a, value_a from a) iv cross join
(select distinct id_b from b) ib left join
b
on b.id_b = ib.id_b and b.id_a = iv.id_a;
The cross join generates the rows. The left join brings in the additional columns.
I usually break things like this down into CTEs:
DDL
use tempdb
CREATE TABLE Table1
([ID_A] varchar(1), [VALUE_A] int)
;
INSERT INTO Table1
([ID_A], [VALUE_A])
VALUES
('A', 1),
('B', 2)
;
CREATE TABLE Table2
([ID_B] int, [ID_A] varchar(1), [VALUE_B] int)
;
INSERT INTO Table2
([ID_B], [ID_A], [VALUE_B])
VALUES
(90, 'A', 1),
(90, 'C', 1),
(90, 'E', 1),
(91, 'A', 1),
(91, 'B', 1),
(92, 'B', 1),
(92, 'E', 1),
(92, 'F', 1)
;
Answer
with a as (
select distinct id_b
from Table2
),
b as (
select id_a, value_a, id_b
from Table1 cross join a
)
select b.id_a, b.value_a, b.id_b, t2.id_a, t2.value_b
from b left join Table2 t2
on b.id_a = t2.id_a
and b.id_b = t2.id_b
Results
+------+---------+------+------+---------+
| id_a | value_a | id_b | id_a | value_b |
+------+---------+------+------+---------+
| A | 1 | 90 | A | 1 |
| B | 2 | 90 | NULL | NULL |
| A | 1 | 91 | A | 1 |
| B | 2 | 91 | B | 1 |
| A | 1 | 92 | NULL | NULL |
| B | 2 | 92 | B | 1 |
+------+---------+------+------+---------+
I couldn't resolve the exact logic and couldn't match the results exactly as desired , but presume you'd like to get something like :
SELECT a.ID_A, COALESCE(a.VALUE_A,b.VALUE_B) VALUE_A, b.ID_B, a.ID_A,
(CASE WHEN a.ID_A IS NULL THEN a.ID_A ELSE CAST(b.VALUE_B as VARCHAR(1)) END)
as VALUE_B
FROM TABLE_A a FULL OUTER JOIN TABLE_B b
ON ( a.ID_A = b.ID_A )
GROUP BY a.ID_A, a.VALUE_A, b.ID_B, a.ID_A, b.VALUE_B
ORDER BY 3, 2, 1;
SQL Fiddle Demo
Try this:
SELECT A.ID_A , A.VALUE_A , B.ID_B , B.ID_A , B.VALUE_B
FROM TABLE_A A
LEFT OUTER JOIN TABLE_B B
ON A.ID_A = B.ID_A ;
EDIT: Typos corrected following sticky bit note (thanks!!).

How can I make a one row from 1 group using oracle statement

There is a group as below.
refno | col1 | col2
---------------------
1 | a | aa
1 | b | bb
1 | c | cc
1 | d | dd
I want to make it like this using Oracle SQL:
refno a b c d
1 aa bb cc dd
How to do it?
You can do it using PIVOT
WITH sel AS
(SELECT 1 refno , 'a' col1 , 'aa' col2 FROM dual
UNION ALL
SELECT 1 , 'b' , 'bb' FROM dual
UNION ALL
SELECT 1 , 'c' , 'cc' FROM dual
UNION ALL
SELECT 1 , 'd' , 'dd' FROM dual
)
SELECT *
FROM sel
PIVOT
(max(col2)
FOR col1 IN ('a','b','c','d'))
But you have to specify col1 values manually - FOR col1 IN ('a','b','c','d')
More - here and here