SQL insert all data to bridge table, (many to many) - sql

I Have two table like below ;
X table ;
+---+----------+
| id| value |
+---+----------+
| 1 | x value1 |
+---+----------+
| 2 | x value2 |
+---+----------+
| 3 | x value3 |
+---+----------+
Y table ;
+---+----------+
| id| value |
+---+----------+
| 1 | y value1 |
+---+----------+
| 2 | y value2 |
+---+----------+
| 3 | y value3 |
+---+----------+
And I have created new table(x_y table)which has foreign keys for x and y tables ;
And I want to add all data related to each other to new table like below;
x_y table
+----+------+------+
| id | x_id | y_id |
+----+------+------+
| 1 | 1 | 1 |
+----+------+------+
| 2 | 1 | 2 |
+----+------+------+
| 3 | 1 | 3 |
+----+------+------+
| 4 | 2 | 1 |
+----+------+------+
| 5 | 2 | 2 |
+----+------+------+
| 6 | 2 | 3 |
+----+------+------+
| 7 | 3 | 1 |
+----+------+------+
| 8 | 3 | 2 |
+----+------+------+
| 9 | 3 | 3 |
+----+------+------+
how can I add value like this to third table on postgresql script.

This can be done with a cross join and a row_number that generates id's.
select row_number() over(order by x.id,y.id) as id,x.id as x_id,y.id as y_id
from x
cross join y

Presumably, the new table is defined with id as a serial column. If so, you would insert the data by doing:
insert into x_y (x_id, y_id)
select x.id, y.id
from x cross join
y
order by x.id, y.id;

Related

Postgresql: Group rows in a row and add array

Hi i have a table like this;
+----+----------+-------------+
| id | room_id | house_id |
+----+----------+-------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 1 | 2 |
| 5 | 2 | 2 |
| 6 | 3 | 2 |
| 7 | 1 | 3 |
| 8 | 2 | 3 |
| 9 | 3 | 3 |
+----+-------+----------------+
and i want to create a view like this
+----+----------+-------------+
| id | house_id | rooms |
+----+----------+-------------+
| 1 | 1 | [1,2,3] |
| 2 | 2 | [1,2,3] |
| 3 | 3 | [1,2,3] |
+----+-------+----------------+
i tried many ways but i cant gruop them in one line
Thanks for any help.
You can use array_agg():
select house_id, array_agg(room_id order by room_id) as rooms
from t
group by house_id;
If you want the first column to be incremental, you can use row_number():
select row_number() over (order by house_id) as id, . . .

Combine results from separate columns grouped by a specific column

having a table like this in oracle db:
+-----+-----+-----+-----+
| VAL1| VAL2| VAL3| ID |
+-----+-----+-----+-----+
| A | | | 1 |
-------------------------
| | B | | 1 |
-------------------------
| | | C | 1 |
-------------------------
| X | | Z | 2 |
-------------------------
| | Y | | 2 |
-------------------------
| | Y | Z | 2 |
-------------------------
| E | | | 3 |
-------------------------
| | | F | 3 |
-------------------------
How to select from this table (in ORACLE) in order to get following output where all this rows are grouped by ID column?
+-----+-----+-----+-----+
| VAL1| VAL2| VAL3| ID |
+-----+-----+-----+-----+
| A | B | C | 1 |
-------------------------
| X | Y | Z | 2 |
-------------------------
| E | | F | 3 |
-------------------------
You can use aggregation:
select id, max(val1) as val1, max(val2) as val2, max(val3) as val3
from t
group by id;
Use GROUP BY combined with an aggregation function, such as MAX().
For example:
select
max(val1) as val1,
max(val2) as val2,
max(val3) as val3,
id
from t
group by id

Limit a sorted number of rows joined

I have two tables, A and B, and a join table M. I want to, for each A.id, get the top 2 B.id's sorting on the value in table M, producing the results below. This is running on an Azure SQL database
Table A Table M Table B
+-----+ +-----+-----+-------+ +-----+
| Id | | AId | BId | Value | | Id |
+-----+ +-----+-----+-------+ +-----+
| 1 | | 1 | 3 | 4 | | 1 |
| 2 | | 1 | 2 | 3 | | 2 |
| 3 | | 3 | 2 | 3 | | 3 |
| 4 | | 3 | 5 | 6 | | 4 |
+-----+ | 3 | 3 | 4 | | 5 |
| 4 | 1 | 2 | +-----+
| 4 | 2 | 1 |
| 4 | 4 | 3 |
+-----+-----+-------+
Result
+-----+-----+-------+
| AId | BId | Value |
+-----+-----+-------+
| 1 | 3 | 4 |
| 1 | 2 | 3 |
| 3 | 5 | 6 |
| 3 | 3 | 4 |
| 4 | 1 | 2 |
| 4 | 4 | 3 |
+-----+-----+-------+
I know that I can select all the M.AId rows where they equal 1, sort it, and limit by 2, but I need to do this for every row in Table A. I've made an attempt to use group by, but I wasn't sure how to sort and limit it. I've also tried to search for resources associated with this issue but I couldn't find any resources.
(I also wasn't sure how to word the title for this issue)
You can just use ROW_NUMBER:
SELECT
AId, BId, Value
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY AId ORDER BY Value DESC)
FROM M
) t
WHERE Rn <= 2

Select distinct combinations of values

I have a table with X values and Y values, both INT. What I want to do is group on the X value with the condition that it contains a distinct combination of Y values. I also want to see the total number of each combination.
I tried using SUM ( POWER (2, Y)), but that generates numbers that are too big as Y can get up to about 300 in some cases.
+--------------+--------------+
| X | Y |
+--------------+--------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
| 1 | 6 |
| 2 | 1 |
| 2 | 2 |
| 2 | 4 |
| 2 | 6 |
| 3 | 2 |
| 3 | 3 |
| 3 | 5 |
| 4 | 2 |
| 4 | 3 |
| 4 | 5 |
| 5 | 2 |
| 5 | 3 |
| 5 | 6 |
+--------------+--------------+
I want the result to look something like:
+--------------+--------------+
| X | COUNT |
+--------------+--------------+
| 1 | 2 |
| 3 | 2 |
| 5 | 1 |
+--------------+--------------+
Based on your description (but not on your sample data) next query should do:
select X, count(distinct Y)
from TBL
group by X
Thanks for trying to help. I realize that it might have been hard to understand what I was trying to do.
Anyway, I ended up solving it with the checksum_agg aggregate function.

Create a combined list from two tables

I have a table with CostCenter_ID (int) and a second table with Process_ID (int).
I'd like to combine the results of both tables so that each cost center ID is assigned to all process IDs, like so:
|CostCenterID | ProcessID |
---------------------------
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
I've done it before but I'm drawing a blank. I've tried this:
SELECT CostCenter_ID,NULL FROM dbo.Cost_Centers
UNION ALL
SELECT NULL,Process_ID FROM dbo.Processes
which returns this:
|CostCenterID | ProcessID |
---------------------------
| 1 | NULL |
| NULL | 1 |
| NULL | 2 |
| NULL | 3 |
Try:
select a.CostCenterID, b.ProcessID
from table1 a
cross join table2 b
or:
select a.CostCenterID, b.ProcessID
from table1 a
,table2 b
NB: cross join is the better method as it makes it clearer to the reader what your intentions are.
More info (with pics) here: http://www.w3resource.com/sql/joins/cross-join.php