relational link within one table - sql

I have Table User, which consists of two columns - id_user and name_user?
id_user
name_user
1
Vova
2
John
3
Ivan
4
Kate
I need to make relation between two users. If I understood correctly I should make Table relation_ids:
id_user_1
id_user_2
1
2
1
3
1
4
2
3
Tell me please do I need to double relationships between two users (for example 1-2 and 2-1)? Is there another ways to make relation within one table?

Related

How to Normalize a table where a column references multiple rows of a different column in the same table

I am trying to create a table that lists different applications and if they integrate with other applications on that list.
ID SKU NAME Integrations
1 pdk1 hubspot crm pdk3,pdk4,pdk5
2 pdk2 sugar crm pdk5
3 pdk3 pipedrive pdk1
4 pdk4 quickbooks pdk1
5 pdk5 mailchimp pdk1,pdk2
How can I normalize the integrations column?
The relations between SKUs in your example are "many-to-many" (M:M). Storing multiple comma-separated values in the column violates the first normal form (1NF). Hence you need normalise table and model M:M relation using an additional link table.
SKU table
SKU
---
ID SKU NAME
1 pdk1 hubspot crm
2 pdk2 sugar crm
3 pdk3 pipedrive
4 pdk4 quickbooks
5 pdk5 mailchimp
Link table
SKU_INTEGRATION
---------------
ID INTEGRATED_WITH_ID
1 3
1 4
1 5
2 5
3 1
4 1
5 1
5 2
You may have a look on the book "Programming with databases" which covers the topics of normalization, modeling of different types of links etc.
Is this what you want?
select id, sku, name,
regexp_split_to_table(integrations) as integration
from t;
This isn't exactly "normalized" but it removes the use of a delimited string to represent multiple values.

Table Join issue

Right now I've got a Main table in which I am uploading data. Because the Main table has many different duplicates, I Append various data out of the Main table into other tables such as, username, phone number, and locations in order to keep things optimized. Once I have everything stripped down from the Main table, I then append what's left into a final optimized Main table. Before this happens though, I run a select query joining all the stripped tables with the original Main table in order to connect the IDs from each table, with the correct data. For example:
Original Main Table
--Name---------Number------Due Date-------Location-------Charges Monthly-----Charges Total--
John Smith 111-1111 4/3 Chicago 234.56 500.23
Todd Jones 222-2222 4/3 New York 174.34 323.56
John Smith 111-1111 4/3 Chicago 274.56 670.23
Bill James 333-3333 4/3 Orlando 100.00 100.00
This gets split into 3 tables (name, number, location) and then there is a date table with all the dates for the year:
Name Table Number Table Location Table Due Date Table
--ID---Name------ -ID--Number--------- ---ID---Location---- --Date---
1 John Smith 1 111-1111 1 Chicago 4/1
2 Todd Jones 2 222-2222 2 New York 4/2
3 Bill James 3 333-3333 3 Orlando 4/3
Before The Original table gets stripped, I run a select query that grabs the ID from the 3 new tables, and joins them based on the connection they have with the original Main table.
Select Output
--Name ID----Number ID---Location ID---Due Date--
1 1 1 4/3
2 2 2 4/3
1 1 1 4/3
3 3 3 4/3
My issue comes when I need to introduce a new table that isn't able to be tied into the Original Main Table. I have an inventory table that, much like the original Main table, has duplicates and needs to be optimized. I do this by creating a secondary table that takes all the duplicated devices out and put them in their own table, and then strips the username and number out and puts them into their tables. I would like to add the IDs from this new device table into the select output that I have above. Resulting in:
Select Output
--Name ID----Number ID---Location ID---Due Date--Device ID---
1 1 1 4/3 1
2 2 2 4/3 1
1 1 1 4/3 2
3 3 3 4/3 1
Unlike the previous tables, the device table has no relationship to the originalMain Table, which is what is causing me so much headache. I can't seem to find a way to make this happen...is there anyway to accomplish this?
Any two tables can be joined. A table represents an application relationship. In some versions (not the original) of Entity-Relationship Modelling (notice that the "R" in E-R stands for "(application) relationship"!) a foreign key is sometimes called a "relationship". You do not need other tables or FKs to join any two tables.
Explain, in terms of its column names and the values for those names, exactly when a row should turn up in the result. Maybe you want:
SELECT *
FROM the stripped-and-ID'd version of the Original AS o
JOIN the stripped-and-ID'd version of the Device AS d
USING NameID, NumberID, LocationID and DueDate
Ie
SELECT *
FROM the stripped-and-ID'd version of the Original AS o
JOIN the stripped-and-ID'd version of the Device AS d
ON o.NameID=d.NameId AND o.NumberID=d.NumberID
AND o.LocationID=d.LocationID AND o.DueDateID=d.DueDate.
Suppose p(a,...) is some statement parameterized by a,... .
If o holds the rows where o(NameID,NumberID,LocationID,DueDate) and d holds the rows where d(NameID,NumberID,LocationID,DueDate,DeviceID) then the above holds the rows where o(NameID, NumberID, LocationID, DueDate) AND d(NameID,NumberID,LocationID,DueDate,DeviceID). But you really have not explained what rows you want.
The only way to "join" tables that have no relation is by unioning them together:
select attribute1, attribute2, ... , attributeN
from table1
where <predicate>
union // or union all
select attribute1, attribute2, ... , attributeN
from table2
where <predicate>
the where clauses are obviously optional
EDIT
optionally you could join the tables together by stating ON true which will act like a cross product

Storing one to many relation in database - Array or one to many relation?

When we store a one to many association in a database, which is a better approach. One - Many mapping in a table or storing the many part as an array. I'm specific to postgres database (constraint)
For example: If we define the relationship as follows
a b
1 - 2
1 - 3
1 - 6
2 - 3
2 - 4
3 - 5
3 - 6
Here, the one part is a and the many part is b (Primary key being a, b)
The same thing can be stored as an array as (similar to an adjacency list).
1 - {2,3,6}
2 - {3,4}
3 - {5,6}
Which of this is more efficient. I may have to do some operations on this such as transitive closure etc. and, the graph may be really huge.
A practical example of the above may be something like connections of a particular profile (LinkedIn connections), or any social graph scenario
In your example the relationship is many to many, not one to many. Multiple a records can be associated with one b and multiple b records can be associated with one a. As such, the correct normalized form is a join table.
Hypothetically, imagine this DB relationship represents one profile "liking" another profile in a social media context. In that case you may want to store additional information; a timestamp of when the "like" was initiated, the degree to which the profiled shruged/liked/loved the other profile, etc. It then becomes apparent that in the array implementation there is nowhere to store this additional data. You need a join table so that each "like" can have its own metadata.
Here is the structure I would recommend:
PK A B
100 1 - 2
200 1 - 3
300 1 - 6
400 2 - 3
500 2 - 4
600 3 - 5
700 3 - 6
Where PK is an auto generated PK, hopefully from a sequence, and A, B are constrained by a unique index. This structure is future proof for eventually dropping the unique index on A, B, a headache I've had to deal with occasionally.

Counting number of occurences of tuples in an m:n relationship

I'd like to know if there's an efficient way to count the number of occurences of a permutation of entities from one side of the m:n relationship. Hopefully, the next example will illustrate properly what I mean:
Let's imagine a base with people and events of some sort. People can organize multiple events and events can be organized by more than one person. What i'd like to count is whether a certain tuple of people have already organized an event or if it's their first time. My first idea to do this is to add an attribute to the m:n relationship
PeopleID | EventID | TimesOrganized
100 1 1
200 1 1
300 2 1
400 3 1
Now, there's an event no. 4 that's again organized by persons 200 and 100 (let's say they should be added in that order). The new table should look like:
PeopleID | EventID | TimesOrganized
100 1 2
200 1 2
300 2 1
400 3 1
200 4 2
100 4 2
Now, if I added an event organized by persons 200 and 300 it would look like this:
PeopleID | EventID | TimesOrganized
100 1 2
200 1 2
300 2 1
400 3 1
200 4 2
100 4 2
200 5 1
300 5 1
How would I go about keeping the third column updated properly and what are my options?
I should also add that this a part of the larger project we have for one of the classes and we'll be implementing an application that uses the database in some way, so I might as well move this to application logic if there's no easy way.
I wouldn't recommend tracking a TimesOrganized column as you suggest.
You can simple query it as needed using a COUNT(EventId)..GROUP BY PeopleID.
If you do feel you need to maintain the value somewhere it probably is better normalized to the (presumed) table People. Something like People.TimesOrganized. But then you have to increment it as you go instead of just recalculating as needed.
If you want to count how many many time someone have organized an event the problem is not m:n, but 1:m. Just count the event grouped by the people, that's it, you don't really need to have that column in the table, if it's not needed a lot of time.
That said I find you table a little confusing, there are detail and aggregation mixed, the third one downright wrong: the PeopleID 200 had organized 3 event and the 300 have 2 event.

MySQL: Getting connected (similar) data with lef/right fields

In MySQL Im having two tables:
PRODUCTS (id, Name)
SEEALSO (id, prodLeft, prodRight)
SEEALSO defines which PRODUCTS are related together and are represented as binded fileds "prodLeft"-"prodRight".
For Example:
PRODUCTS:
1 Desk
2 Table
3 Chair
4 Doors
5 Tree
6 Flower
SEEALSO
1 1 2
2 2 3
3 3 4
4 5 6
From that we can see binding of Desk-Table-Chair-Doors and Tree-Flower.
I would now want to write SQL statement where I could specifie PRODUCT name (e.g. Chair) and i would get result of binded fields that are connected with it (e.g. Chair: Desk-Table-Chair-Doors).
From this point on i would like to know if this is even possible for my data presentation concept in SEEALSO and if it is if you could help me solve my problem.
As you're wondering whether it's even possible, you could look into this information on Nested Sets, which is the MySQL way of doing this (I gather).
I could not give you a worked sample, as I'm no MySQL expert: perhaps this will help you enough given the general nature of your question.