copy one table to another table with diffrent columns - sql

I have a TableA columns are (id,name,A,B,C,p_id)
i want convert TableA to TableB, TableB columns are (id,name,alphabets,alphabets_value,p_id)
Record in TableA
id | name | A | B | C | p_id
1 | xyz | a | b | | 1
2 | opq | a`| b`| c`| 1
Expected In TableB
u_id | id | name | alphabets | alphabets_value | p_id
1 | 1 | xyz | A | a | 1
2 | 1 | xyz | B | b | 1
3 | 2 | opq | A | a` | 1
4 | 2 | opq | B | b` | 1
5 | 2 | opq | C | c` | 1
i want TableB output currently using Microsoft SQL

This is an unpivot, probably most easily explained by a UNION ALL:
SELECT id, name, 'A' as alphabets, a as alphabets_value, p_id
UNION ALL
SELECT id, name, 'B' as alphabets, b as alphabets_value, p_id
UNION ALL
SELECT id, name, 'C' as alphabets, c as alphabets_value, p_id
You can then WHERE to remove the nulls from this, and ROW_NUMBER to give yourself a fake U_id:
SELECT ROW_NUMBER() OVER(ORDER BY id, alphabets) as u_id, x.*
FROM
(
SELECT id, name, 'A' as alphabets, a as alphabets_value, p_id
UNION ALL
SELECT id, name, 'B' as alphabets, b as alphabets_value, p_id
UNION ALL
SELECT id, name, 'C' as alphabets, c as alphabets_value, p_id
)
WHERE
x.alphabets_value IS NOT NULL
Once you get to having a result set you want, INSERT INTO, UPDATE FROM or MERGE to get it into table B is quite trivial

Related

Grouping data using PostgreSQL based on 2 fields

I have a problem with grouping data in postgresql. let say that I have table called my_table
some_id | description | other_id
---------|-----------------|-----------
1 | description-1 | a
1 | description-2 | b
2 | description-3 | a
2 | description-4 | a
3 | description-5 | a
3 | description-6 | b
3 | description-7 | b
4 | description-8 | a
4 | description-9 | a
4 | description-10 | a
...
I would like to group my database based on some_id then differentiate which one has same and different other_id
I would expecting 2 type of queries: 1 that has same other_id and 1 that has different other_id
Expected result
some_id | description | other_id
---------|-----------------|-----------
2 | description-3 | a
2 | description-4 | a
4 | description-8 | a
4 | description-9 | a
4 | description-10 | a
AND
some_id | description | other_id
---------|-----------------|-----------
1 | description-1 | a
1 | description-2 | b
3 | description-5 | a
3 | description-6 | b
3 | description-7 | b
I am open for suggestion both using sequelize or raw query
thank you
One approach, using MIN and MAX as analytic functions:
WITH cte AS (
SELECT *, MIN(other_id) OVER (PARTITION BY some_id) min_other_id,
MAX(other_id) OVER (PARTITION BY some_id) max_other_id
FROM yourTable
)
-- all some_id the same
SELECT some_id, description, other_id
FROM cte
WHERE min_other_id = max_other_id;
-- not all some_id the same
SELECT some_id, description, other_id
FROM cte
WHERE min_other_id <> max_other_id;
Demo
You can also do this using exists and not exists:
-- all same
select t.*
from my_table t
where not exists (select 1
from my_table t2
where t2.some_id = t.some_id and t2.other_id <> t.other_id
);
-- any different
select t.*
from my_table t
where exists (select 1
from my_table t2
where t2.some_id = t.some_id and t2.other_id <> t.other_id
);
Note that this ignores NULL values. If you want them treated as a "different" value then use is distinct from rather than <>.

Join number of pairs in a single table using SQL

I have two tables of events in bigquery that look like as follows. The main idea is two count the number of events in each table (are always pairs of event_id and user_id) and join them in a single table that for each pair in any table it tells the number of events.
table 1:
| event_id | user id |
| -------- | ------- |
| 1 | 1 |
| 2 | 1 |
| 2 | 3 |
| 2 | 5 |
| 1 | 1 |
| 4 | 7 |
table 2:
| event_id | user id |
| -------- | ------- |
| 1 | 1 |
| 3 | 1 |
| 2 | 3 |
I would like to get a table which has the number of events of each table:
| event_id | user id | num_events_table1 | num_events_table2 |
| -------- | ------- | ----------------- | ----------------- |
| 1 | 1 | 2 | 1 |
| 2 | 1 | 1 | 0 |
| 2 | 3 | 1 | 1 |
| 2 | 5 | 1 | 0 |
| 4 | 7 | 1 | 0 |
| 3 | 1 | 0 | 1 |
Any idea of how to do this with sql? I have tried this:
SELECT i1, e1, num_viewed, num_displayed FROM
(SELECT id as i1, event as e1, count(*) as num_viewed
FROM table_1
group by id, event) a
full outer JOIN (SELECT id as i2, event as e2, count(*) as num_displayed
FROM table_2
group by id, event) b
on a.i1 = b.i2 and a.e1 = b.e2
This is not getting exactly what I want. I amb getting i1 which are null and e1 that are null.
Consider below
#standardSQL
with `project.dataset.table1` as (
select 1 event_id, 1 user_id union all
select 2, 1 union all
select 2, 3 union all
select 2, 5 union all
select 1, 1 union all
select 4, 7
), `project.dataset.table2` as (
select 1 event_id, 1 user_id union all
select 3, 1 union all
select 2, 3
)
select event_id, user_id,
countif(source = 1) as num_events_table1,
countif(source = 2) as num_events_table2
from (
select 1 source, * from `project.dataset.table1`
union all
select 2, * from `project.dataset.table2`
)
group by event_id, user_id
if applied to sample data in your question - output is
If I understand correctly, the simplest method is to modify your query via a USING clause along with COALESCE():
SELECT id, event, COALESCE(num_viewed, 0), COALESCE(num_displayed, 0)
FROM (SELECT id, event, count(*) as num_viewed
FROM table_1
GROUP BY id, event
) t1 FULL JOIN
(SELECT id , event, COUNT(*) as num_displayed
FROM table_2
GROUP BY id, event
) t2
USING (id, event);
Note: This requires that the two columns used for the JOIN have the same name. If this is not the case, then you might still need column aliases in the subqueries.
One way is aggregate the union
select event_id, user id, sum(cnt1) cnt1, sum(cnt2) cnt2
from (
select event_id, user id, 1 cnt1, 0 cnt2
from table_1
union all
select event_id, user id, 0 cnt1, 1 cnt2
from table_2 ) t
group by event_id, user id

Filtering a table via another table's values

I have 2 tables:
Value
+----+-------+
| id | name |
+----+-------+
| 1 | Peter |
| 2 | Jane |
| 3 | Joe |
+----+-------+
Filter
+----+---------+------+
| id | valueid | type |
+----+---------+------+
| 1 | 1 | A |
| 2 | 1 | B |
| 3 | 1 | C |
| 4 | 1 | D |
| 5 | 2 | A |
| 6 | 2 | C |
| 7 | 2 | E |
| 8 | 3 | A |
| 9 | 3 | D |
+----+---------+------+
I need to retrieve the values from the Value table where the related Filter table does not contain the type 'B' or 'C'
So in this quick example this would be only Joe.
Please note this is a DB2 DB and i have limited permissions to run selects only.
Or also a NOT IN (<*fullselect*) predicate:
Only that my result is 'Joe', not 'Jane' - and the data constellation would point to that ...
WITH
-- your input, sans reserved words
val(id,nam) AS (
SELECT 1,'Peter' FROM sysibm.sysdummy1
UNION ALL SELECT 2,'Jane' FROM sysibm.sysdummy1
UNION ALL SELECT 3,'Joe' FROM sysibm.sysdummy1
)
,
filtr(id,valueid,typ) AS (
SELECT 1,1,'A' FROM sysibm.sysdummy1
UNION ALL SELECT 2,1,'B' FROM sysibm.sysdummy1
UNION ALL SELECT 3,1,'C' FROM sysibm.sysdummy1
UNION ALL SELECT 4,1,'D' FROM sysibm.sysdummy1
UNION ALL SELECT 5,2,'A' FROM sysibm.sysdummy1
UNION ALL SELECT 6,2,'C' FROM sysibm.sysdummy1
UNION ALL SELECT 7,2,'E' FROM sysibm.sysdummy1
UNION ALL SELECT 8,3,'A' FROM sysibm.sysdummy1
UNION ALL SELECT 9,3,'D' FROM sysibm.sysdummy1
)
-- real query starts here
SELECT
*
FROM val
WHERE id NOT IN (
SELECT valueid FROM filtr WHERE typ IN ('B','C')
)
;
-- out id | nam
-- out ----+-------
-- out 3 | Joe
Or also, a failing left join:
SELECT
val.*
FROM val
LEFT JOIN (
SELECT valueid FROM filtr WHERE typ IN ('B','C')
) filtr
ON filtr.valueid = val.id
WHERE valueid IS NULL
You can use EXISTS, as in:
select *
from value v
where not exists (
select null from filter f
where f.valueid = v.id and f.type in ('B', 'C')
);
Result:
ID NAME
--- -----
3 Joe
See running example at db<>fiddle.

Select unique results and null

I need get all lines from table, that have unique value in certain fields and all lines, than have null in this fields. Example:
id | name | group
-----------------
1 | One | 1
2 | Two | null
3 | Three| 3
4 | Four | 2
5 | Five | 1
6 | Six | 2
7 | Seven| null
Result:
id | name | group
-----------------
1 | One | 1
2 | Two | null
3 | Three| 3
4 | Four | 2
7 | Seven| null
How to make it in one request?
select t.id, t.name, t.`group`
from tablename t
join (select `group`, min(id) as mid
from tablename
where `group` is not null
group by `group`) x on x.mid = t.id and x.`group` = t.`group`
union all
select id, name, `group`
from tablename
where `group` is null

Select distinct multiple field without NULL

I have a table with Value ID and Value
--------------
| id | value |
--------------
| 1 | NULL |
--------------
| 1 | A |
--------------
| 2 | NULL |
--------------
| 2 | NULL |
--------------
| 3 | B |
--------------
| 3 | B |
--------------
| 3 | B |
--------------
I need to select distinct id and corresponding value from the table. When selecting the Id should be unique and if it is having multiple values in the value field it should retrieve only not NULL values
So the result should be like below.
--------------
| id | value |
--------------
| 1 | A |
--------------
| 2 | NULL |
--------------
| 3 | B |
--------------
How to achieve this? using SQL server 2005
You can use a regular GROUP BY.
The GROUP BY will
eliminate the NULL value from 1 because other values are present.
retain the NULL value for 2 because it only has NULL values.
SQL Statement
SELECT id
, MIN(value)
FROM YourTable
GROUP BY
id
Test script
;WITH q (id, value) AS (
SELECT 1, NULL
UNION ALL SELECT 1, 'A'
UNION ALL SELECT 2, NULL
UNION ALL SELECT 2, NULL
UNION ALL SELECT 3, 'B'
UNION ALL SELECT 3, 'B'
UNION ALL SELECT 3, 'B'
)
SELECT id
, MIN(value)
FROM q
GROUP BY
id
It's a bit convoluted, but it should do the trick:
select distinct x.id, x.value
from table x
where x.value is not null
or not exists
(select y.id
from table y
where y.id = x.id
and y.value is not null)