Traverse list of related tables - mysql

I have a peculiar situation. In my MySQL database, I have around 90 odd tables and most of the tables have been indexed (We are using INNODB). Some of the tables are having a link like this:
A -> B -> C->D->E
Is there a way where-in I can find the list of all the sub-child tables when i have only table A and E to work with? I have do a dynamic query builder mechanism, and for that purpose I list the users with the list of tables, and in a given situation like above, need to get the required information from just table "A" and "E" alone, without the tables "B","C" and "D" being selected by the search user.
The tables are linked in normal manner..each table is linked to another via a proper foreign key constraint.
Eg.
Table A (Transaction)
Id, Trxn-Date, Amount
Table B (Transaction Header)
Id, Agent_Id (FK to Agent_Profile), Upd_Time, Trnx_Hdr_ID (FK to Table A)
Table C (Agent_Profile)
Id, Prof_ID (FK to Profile)
Table D (Profile)
ID, Pers_Info_Id (FK to Personal_Info)
Table E (Personal_Info)
Id, Firstname, Lastname
User selects Trxn_Date, FirstName, LastName.
How can I retrieve the sub-linked table information, when the selected tables(in this case), happens to be only Transaction and Personal_Info.

Seems like you could consolidate a few of those tables into 2-3 tables without losing anything useful. Tables C D and E just contain columns to point to other tables.
If changed, a query with trxn_date and first/last name would be a ton easier.

Related

Create an index table for all tables in a database

I'm asking if its possible to have a database->index table-> tables?
I know that we AI the ids inside the table... but lets say we have:
1 database => 'books'
5 tables=> 'genre' like
a. fantasy
b. scifi
c. action
d. mystery
e. horror.
Each table contains ID, book_name, price of a specific genre.
the index table i want to contain:
table_id,
table_name,
table_comments (its the same we do with data but now we do it for tables)
Also this index_table should auto update whenever a table is dropped or created. Now is it possible?

Unable to figure how to manage foreign keys for 'project-customers-contacts' relation

I have a CUSTOMERS table and a CONTACTS table the relation between them is one to many obviously.
also I have PROJECTS table and PROJECT_CUSTOMERS table with relation one to many and with relation one to one between CUSTOMERS and PROJECT_CUSTOMERS.
my problem is that I have a fifth table PROJECT_CONTACTS ....I can't figure which tables shall I refer to in this tables, currently I am refering to PROJECT_CUSTOMERS and CONTACTS table, is this correct or there is something better ?
Your title refers to "foreign keys" but your question just seems to be about what columns should go in what tables.
First, decide what situations can arise and what you want/need to say about them. (This will your tables, columns, candidate keys, foreign keys and constraints.)
Every table holds rows that make some predicate (statement template parameterized by column names) true. Your design seems to have:
CUSTOMERS(id, ...) -- ID identifies a customer and ...
CONTACTS(id, ...) -- ID identifies a contact and ...
PROJECTS(id, ...) -- ID identifies a project and ...
PROJECT_CUSTOMERS(pid, cust_id, ...) -- project PID has customer CUST_ID and ...
PROJECT_CONTACTS(pid, cont_id, cust_id)...)
-- project PID has contact CONT_ID and project pid has customer CUST_ID and ...
A foreign key has a table & column list referencing a table and column list that forms a candidate key. It says that lists of values in the first table appear as lists of values in the second table. Where that is so, declare a foreign key.

Establishing relationships in a database between multiple tables

I have a web application which allows users to join multiple groups.
I have a 'users' table which stores details about the users (id, email, password, etc.) and a 'groups' table which stores details about the available groups (id, name, owner of group).
I have been researching the best way to store group memberships (i.e. which users are in which group, bearing in mind they can be members of multiple) - however I am still not sure what the most efficient solution would be.
Would you recommend I:-
Create a second table called 'group_memberships' and store the user's ID along with the corresponding group ID?
Store an array alongside the group particulars in the 'groups' table with the user IDs of its members?
Approach this task a different way?
The DBMS I am using is phpMyAdmin.
I would advise you to go with option 1; where you have a Mapping Table for linking Users & Groups.
The Users Table will have PK on User_ID.
The Groups table will have PK on Group_ID.
The Mapping table will have User_ID(FK) and Group_ID(FK).
Now you should have PK on these two columns together.
This will ensure you don't have duplicate entries.
What you're describing is called a many-to-many relationship in database terms. A user can belong to multiple groups, and groups have more than one user (or else they wouldn't be "groups"!).
Your first idea, the group_memberships table, is the accepted best way to model this relationship. Although you'll want to name it users_groups or something similar to reflect the fact it relates or associates those two tables. At its most basic, this association table needs three columns:
ID (primary key)
user_id (foreign key)
group_id (foreign key)
By JOINing to this table ON either user_id or group_id, you can find the related records from either side of the relationship. And you can do it right from a SQL query, without any additional code like you'd need if you stored an array.
I would definitely go with option 1 - creating the junction table 'group_memberships' - I have used this approach many times without problems. Don't forget to add an Index on the new table 'group_memberships' for columns: 'groupID' and 'userID'.
Option 2 is not scalable for a large amount of data, especially if groups have a lot of users.
UPDATE:
For info on Indexes, here is a good (and short) blog: https://blog.viaduct.io/mysql-indexes-primer/.
The first option is a right choice. Actually it is a materialized view for both user table and group table.
Just think materialized view as a extra table or a redundant data structure that denormalizes the user properties and group properties together for quick search.
Since if we do not have the view, when we query a group id to list all its users, we have to filter millions of users to check if he/she is in the certain group. It is a performance nightmare!
Mysql has tools to build this view very efficiently. You may build secondary index on this view columns for quick search, say, group id, group name, user id, user name or something else you hope to search with.
good luck :-)

fastest way to query a field that has more than one possible matching value

I have 2 tables.
First table is called professions, and those are indexed by ID. So each profession now has a unique ID associated with it.
My second table is called contacts, and in there I have a profession field that right now only hold the ID that a certain profession is associated with.
My problem is that what if I have a contact that has more than one profession associated with it.
What would be the best way to query the table and ways to store the professions of a contact. I didn't want to do is create a field to just store a 0 or 1 int for each profession I have. The reason is because I want to dynamically grow the professions table and have the numbers reflect any dynamic changes on my site when I query.
You have a many-to-many relationship. To implement that in MySQL you should use a linking table. So professions and contacts should have an id in each table, but no foreign keys, and you create a new table called profession_contact_links or something, containing its own id, and profession_id and contact_id, which are both foreign keys to the respective tables. Then you can have many contacts linked with each profession, and many professions linked with each contact. To connect the two main tables together in a select you will need two joins, and what they are will depend on what exactly you want to select.
The standard solution to this modelling issue is called a link table.
Basically it is a table that contains the ids of the two tables that are linked, so you would have a link table with to columns and a primary key that is both of those columns:
(profession_id, contact_id)
or the other order... doesn't matter that much, but the order can affect performance, the key you will be searching on most often is the one you want first.
You then use either SELECT ... IN (...) or SELECT ... JOIN ... to query the data that you are after.
Depending on what you want and how you want to find it, i'd suggest rlike or in
SELECT ... FROM <table> WHERE <column name> RLIKE "^id1|id2|id3$"
This will find any cell that contains any of those three terms
or use
SELECT ... FROM <table> Where <column name> IN ('id1','id2','id3')
this will find any cell that is equals to one of those three.

Design of MySQL DB to avoid having a table with mutually exclusive fields

I'm creating a new DB and I have this problem: I have two type of users that can place orders: registered users (that is, they have a login) and guest users (that is, no login). The data for registered users and guest users are different and that's why I'm thinking of using two different tables, but the orders (that share the same workflow) are all the same, so I'm thinking about using only one table.
I've read here and here (even if I don't understand fully this example) that I can enforce a MySQL rule to have mutually exclusive columns in a table (in my case they'd be "idGuest" and "idUser") but I don't like that approach.
Is there a better way to do it?
There are several approaches, which depends on the number of records and number of unique fields. For example, if you would say they differ in only two fields, I would have suggested that you just put everything in the same table.
My approach, assuming they differ a lot, would be to think "objects":
You have a main user table, and for each user type you have another table that "elaborates" that user info.
Users
-----
id,email,phone,user_type(guest or registered)
reg_users
---------
users_id, username,password etc.....
unreg_users
-----------
user_id,last_known_address, favorite_color....etc
Where user_id is foreign key to users table
Sounds like mostly a relational supertype/subtype issue. I've answered a similar question and included sample code that you should be able to adapt without much trouble. (Make sure you read the comments.)
The mildly complicating factor for you is that one subtype (guest users) could someday become a different subtype (registered users). How you'd handle that would be application-dependent. (Meaning you'd know, but probably nobody else would.)
I think I would have three tables :
A user table, that would contain :
One row for each user, no matter what type of user
The data that's present for both guests and registered
A field that indicates if a row corresponds to a registered or a guest
A guest table, that would contain :
One row per guest user,
The data that's specific to guests
And a registered table, that would contain :
One row per registered user,
The data that's specific to registered users
Then, when referencing a user (in your orders table, for example), you'd always use the id of the user table.
What you are describing is a polymorphic table. It sounds scary, but it really isn't so bad.
You can keep your separate User and Guest tables. For your Orders table, you have two columns: foreign_id and foreign_type (you can name them anything). The foreign_id is the id of the User or Guest in your case, and the content of the foreign_type is going to be either user or guest:
id | foreign_id | foreign_type | other_data
-------------------------------------------------
1 | 1 | user | ...
2 | 1 | guest | ...
To select rows for a particular user or guest, just specify the foreign_type along with the ID:
SELECT * FROM orders WHERE foreign_id = 1 AND foreign_type = 'guest';
The foreign key in the Orders table pointing back to the Customer entity that placed the order is typically a non-nullable column. If you have two different Customer tables (RegisteredCustomer and GuestCustomer) then you would requiree two separate nullable columns in the Orders table pointing back to the separate customer tables. What I would suggest is to have only one Customers table, containing only those rows (EDIT: sorry, meant to write only those COLUMNS) that are common to registered users and guest users, and then a RegisteredUsers table which has a foreign-key relationship with the Customers table.