PostgreSQL select from 3 many-to-many tables - sql

I'm using PostgreSQL, and I've got the following tables:
Category
Service
Report
All of them have many to many relationships to each other, so I've got the following tables for relationships between them:
link_category_service
link_category_report
link_service_report
I got stuck with the SQL query that allows getting all the categories-reports ids for the particular service with some id (for service with id 4, for instance):
category_id | report_id

You have a direct link between category and report - you can query the mapping table, and filter according to the link tables with the service table:
SELECT *
FROM link_category_report
WHERE category_id IN (SELECT category_id
FROM link_category_service
WHERE service_id = 4) AND
report_id IN (SELECT report_id
FROM link_report_service
WHERE service_id = 4)

Related

Postgres SQL INNER JOIN AND ARRAY_AGG

I have three simple tables:
Category which stores my list of different types of categoriesCategory Table
Items, which stores my items:
JunctionTable table, as a connection between category and items - relation N:M
item_list_category junction table
So my problem is, I would like to create select which will select data from all mentioned tables. First I tried this:
SELECT item_list_id, ARRAY_AGG(category_id) AS array_category
FROM item_list_category
WHERE item_list_id = 1
GROUP BY item_list_id;
With this result:
Attempt 1
Then I wanted to Join tables:
SELECT item_list_id, ARRAY_AGG(category_id) AS array_category
FROM item_list_category
WHERE item_list_id = 1
GROUP BY item_list_id;
This is result, but this is not obviously what I need.Attempt 2
I expected for instance: {"Dětské", "Misteriozní"} etc.

Inserting data from old SQL tables into new tables

I have the following Postgres tables
users table:
id |
-----|
user_follows table (old table):
follower_id | following_id
------------|--------------
communities table (new table):
id | owner_id
-----|-----------
community_members table (new table):
community_id | member_id
-------------|------------
The communities already exist each having an owner_id. I'm trying to construct a SQL statement that will move data from user_follows into community_members given a community owner's id. The following_id should be the owner_id and the follower_id should be the member_id
follower_id, following_id, owner_id, and member_id are all reference to the users table id.
Thanks!
edit: This is what I'm currently thinking
INSERT INTO community_members (community_id, member_id)
SELECT communities.id, user_follows.follower_id
FROM communities JOIN user_follows
WHERE communities.owner_id = 123
AND user_follows.following_id = 123;
``
I figured it out. The working query is
INSERT INTO community_members (community_id, member_id)
SELECT communities.id, user_follows.follower_id
FROM communities JOIN user_follows
ON communities.owner_id = user_follows.following_id
It would be cool to be able to do this for every user that is a community owner automatically, instead of having to run the query for each one. This is ok for now as there are <15 users I need to run this for
edit: Have updated to run for all community owners

Query table using relid instead of the table name

I'm using node-postgres to return a joined table to the front end of my React app through an express server. Here is the query...
SELECT channels.name as channels, programmes.title as title, series.number as series, episodes.episode_number as episode
​FROM programmes
​INNER JOIN programme_channels ON programme_channels.programme_id = programmes.programme_id
​INNER JOIN channels ON programme_channels.channel_id = channels.channel_id
​INNER JOIN series ON programmes.programme_id = series.programme_id
​INNER JOIN episodes ON series.series_id = episodes.series_id
This works as needed, however I'd like for front-end users to be able to update or delete columns of the table. To do this, each cell of my table would need to know the origin of its data. Currently the query I have returns a table like this...
channel | title | series | episode
--------------+------------+---------------+---------
Some Channel | Some title | 1 | 1
Where channel is from the channels, title, series and episode are all from different tables. For a user to update or delete this data, they will need the origins of each column for the query.
The node-postgres query returns some more information which may be helpful for this in the form of a fields array...
fields: [
Field {
name: 'title',
tableID: 16554,
columnID: 2,
dataTypeID: 1043,
dataTypeSize: -1,
dataTypeModifier: 104,
format: 'text'
},
...]
and I can return a table with the original table name of a column using this query...
SELECT relname
FROM pg_catalog.pg_statio_user_tables
WHERE relid = '16554'
result...
relname
----------
programmes
however I'm not sure how to use the results of this to query the table 'programmes'. This is where I've hit a wall. My questions are...
Am I going about this the right way, or is there an easier way to update data returned from a joined table?
If so, is there any way I can SELECT a table by either the relid or the result of a query.

SQL Query between 3 tables that related by ids

I have a 3 Tables like this:
Table 1: Category (ID, Description)
Table 2: SubCategory (ID, Description, CategoryParent_ID)
Table 3: Items (ID, SubCategory_ID, Info, Documentation, etc...)
where SubCategory_ID in items table refers to SubCategory Table, & this last one refers to Category Table by CategoryParent_ID.
enter image description here
I want to make a query, that:
When I select a Category from Table 1, Every item in Table 3 that related to this Category is shown (via SubCategory)
Example: I select IT Equipment from table 1
data shown must be: Every item in table 3 that is related to Table 2 AND Table 2 get its reference from TABLE 1
You probably want to look into joins.
SELECT *
FROM tableOne, tableTwo, tableThree
WHERE tableOne.ID = tableTwo.CategoryParent_ID AND tableTwo.ID = tableThree.SubCategory_ID
You can also avoid these joins in the "where" clause by explicitly placing them in the "from" clause.
For example (jarlh's way):
SELECT *
FROM tableOne
INNER JOIN tableTwo ON tableOne.ID = tableTwo.CategoryParent_ID
INNER JOIN tableThree ON tableTwo.ID = tableThree.SubCategory_ID
Here's some info:
https://www.w3schools.com/sql/sql_join.asp

database model structure

I have a column groups. Groups has different type stored in group_types (buyers, sellers, referee). Only when the group is of type buyer it has another type (more specialized) like electrical and mechanical.
I'm a bit puzzled with how I will store this in a database.
Someone can suggest me a database structure?
thanks
Store your group_types as a hieararchical table (with nested sets or parent-child model):
Parent-child:
typeid parent name
1 0 Buyers
2 0 Sellers
3 0 Referee
4 1 Electrical
5 1 Mechanic
SELECT *
FROM mytable
WHERE group IN
(
SELECT typeid
FROM group_types
START WITH
typeid = 1
CONNECT BY
parent = PRIOR typeid
)
will select all buyers in Oracle.
Nested sets:
typeid lower upper Name
1 1 2 Buyers
2 3 3 Sellers
3 4 4 Referee
4 1 1 Electrical
5 2 2 Mechanic
SELECT *
FROM group_types
JOIN mytable
ON group BETWEEN lower AND upper
WHERE typeid = 1
will select all buyers in any database.
Nested sets is implementable anywhere and more performant, if you don't need hierarchical ordering or frequent updates on group_types.
Parent-child is implementable easily in Oracle and SQL Server and with a little effort in MySQL. It allow easy structure changing and hierarchical ordering.
See this article in my blog on how to implement it in MySQL:
Hierarchical queries in MySQL
You could possibly store additional types like, buyer_mechanical or buyer_electrical.
You could try:
Group
group_id
group_name
group_parent_id
with entries (1, buyers, 0), (2, sellers, 0), (3, referee, 0), (4, electrical, 1), (5, mechanical, 1)
This has the advantage of being infinitely scalable, so each subgroup can have as many subgroups as you want.
Typically, you have extension tables. These are simply additional tables in your schema which hold additional information linked to the main table by some type of key
For example let's say your main table is:
People
PersonId int, PK
GroupTypeId int, FK to GroupTypes
Name varchar(100)
GroupTypes
GroupTypeId int, PK
GroupTypeName varchar(20)
BuyerTypes
BuyerTypeId int, PK
BuyerTypeName varchar(20)
BuyerData
PersonId int, FK
BuyerTypeId int FK
====
Additionally, the BuyerData would have a composite primary key (PK) on PersonId and BuyerTypeId
When pulling Buyer data out, you could use a query like
SELECT *
FROM People P
INNER JOIN BuyerData BD on (P.PersonId = BD.PersonId)
INNER JOIN BuyerTypes BT on (BD.BuyerTypeId = BT.BuyerTypeId)
grouptype: ID, Name ('buyers', 'sellers', 'referee')
group: GroupTypeID, ID, Name ('electrical' and 'mechanical' if grouptypeid == 'buyers')
contact: GroupTypeID (NOT NULL), GroupID (NULL), other attributes
Table Group is populated with records for GroupTypes as required.
Contact.GroupID can be NULL since a GroupType need not have any Groups.
UI has to take care of Group selection. You can have a trigger check the group/type logic.