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

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.

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.

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.

Parsing column data in SQL Syntax to an SQL Query

I am trying to solve a business flow issue at my work and I have an idea that I hope is technically feasible in SQL. What I would like to try and do is store different formulas in SQL syntax into database columns. Within SQL queries I would set variables to equal these columns so that the content of the columns is parsed as a part of the query and the different SQL statements pops up depending on the select specifications.
Short and sweet: I have some widgets to sell and whether or not a client can get these widgets depends on what other widgets they have bought, should have and shouldn’t have, country, customerid, their widget version, widget category and a couple of other things.
My question is how would someone proceed with this? I’m sure someone has made a similar setup before but which methods would be useful to study for my case? Are there case studies where I can find inspiration? I have searched for this without any luck. Hopefully someone who have solved similair issues before would be able to point me in a direction.
Thanks to whom‘ever is able to answer and has had the interest to read my post.
Best regards
Zaid
**OK this is more of a comment than an answer but the formatting doesn't work if I enter it as a comment!
To very vaguely answer your question I would have a Widgets table ie
WidgetID | Widget Name
1 Widget1
2 Widget2
3 Widget3
4 Widget4
Then have a WidgetRequirements table which is
WidgetRequiredID | WidgetID | RequiredWidgetID
1 1 2
2 1 3
3 1 4
4 2 4
5 3 1
6 3 4
This tells you that WidgetID 1 needs Widgets 2, 3 and 4 in order to be "active".
Widget 2 only needs widget4 to be active and Widget3 needs widgets 1 and 4.
This should get you started, expand on this theory.

in theory: would this be possible: SQL query for efficient use of build parts

I have a couple of tables, which I have simplified to the extreme for the purpose of this example.
Table 1, 'Units'
ID UnitName PartNumber
1 UnitX 1
2 UnitX 1
3 UnitX 2
4 UnitX 3
5 UnitX 3
6 UnitY 1
7 UnitY 2
8 UnitY 3
Table 2, 'Parts'
ID PartName Quantity
1 Screw 2
2 Wire 1
3 Ducttape 1
I would like to query on these tables which of these units would be Possible to build, AND if so, which one could be built first ideally to make efficient use of these parts.
Now the question is: can this be done using SQL, or is a background application required/more efficient?
So in this example, it is easy, because only one unit (unit Y) can be built.. But I guess you get the idea. (I'm not looking for a shake and bake answer, just your thoughts on this.)
Thanks
As you present it, it is efficient to use sql. As you described PartNumber column of table Units is a foreign key on ID column of Parts table, so a simple outer join or selecting units that the PartNumber are "NOT IN" the Parts table would give you the units that can not be build.
However if your db schema consists of many non normalised tables, or is very complex without indexes, other "bad" things etc
it could be examined whether specific application code is faster. But i really doubt it for the particular case, the query seems trivial.

Locating all reachable nodes using SQL

Suppose a table with two columns: From and To. Example:
From To
1 2
2 3
2 4
4 5
I would like to know the most effective way to locate all nodes that are reachable from a node using a SQL Query. Example: given 1 it would return 2,3,4 and 5. It is possible to use several queries united by UNION clauses but it would limit the number of levels that can be reached. Perhaps a different data structure would make the problem more tractable but this is what is available.
I am using Firebird but I would like have a solution that only uses standard SQL.
You can use a recursive common table expression if you use most brands of database -- except for MySQL and SQLite and a few other obscure ones (sorry, I do consider Firebird obscure). This syntax is ANSI SQL standard, but Firebird doesn't support it yet.
Correction: Firebird 2.1 does support recursive CTE's, as #Hugues Van Landeghem comments.
Otherwise see my presentation Models for Hierarchical Data with SQL for several different approaches.
For example, you could store additional rows for every path in your tree, not just the immediate parent/child paths. I call this design Closure Table.
From To Length
1 1 0
1 2 1
1 3 2
1 4 2
1 5 3
2 2 0
2 3 1
2 4 1
3 3 0
4 4 0
4 5 1
5 5 0
Now you can query SELECT * FROM MyTable WHERE From = 1 and get all the descendants of that node.
PS: I'd avoid naming a column From, because that's an SQL reserved word.
Unfortunately there isn't a good generic solution to this that will work for all situations on all databases.
I recommend that you look at these resources for a MySQL solution:
Managing Hierarchical Data in MySQL
Models for hierarchical data - presentation by Bill Karwin which discusses this subject, demonstrates different solutions, and compares the adjacency list model you are using with other alternative models.
For PostgreSQL and SQL Server you should take a look at recursive CTEs.
If you are using Oracle you should look at CONNECT BY which is a proprietary extension to SQL that makes dealing with tree structures much easier.
With standard SQL the only way to store a tree with acceptable read performance is by using a hack such as path enumeration. Note that this is very heavy on writes.
ID PATH
1 1
2 1;2
3 1;2;3
4 1;2;4
SELECT * FROM tree WHERE path LIKE '%2;%'