Best way to Manage Junction Tables - php

I have a PHP application where I want to enter many-to-many relationships between products and categories. Everything I put into the database will be manual and my database structure is:
--TABLES--
Products - (Product_ID, Name, etc.)
Categories - (Category_ID, Name, etc.)
Product_Categories (Product_Category_ID, Product_ID, Category_ID)
*this is my junction table
*the Product/Category IDs in this table reference those in the other tables.
Currently when entering in relationships manually, I have to think: which product is product #7 again, and which category is category #8? now there is just a handful but this will be incredibly cumbersome when there are more.
My question is: If I'm manually entering relationships into the junction table, what is the best way to manage this process. Do I need to create my own php page that visualizes these relationships, is there an application better than phpmyadmin (or a feature in it) for this, can I somehow show other table info related to ID's in phpmyadmin?
I'm new to all of this, so sorry if I'm missing something obvious.

PHPMyAdmin wiki has a page describing how to link foreign key values from tables with fewer than 200 rows. Maybe this will help your category problem, but probably not your product id problem.
(Personally I think your instinct to write a data entry app in php or whatever was correct, but here is at least an attempt to find a feature within PMA.

Related

Foreign key vs. SET data type MySQL

I have a MySQL database set up with a list of all my movies, which I imported from a MS Access database. One field contains the possible values for the genre of the movie, movies can have more than one genre, so I need a data type which supports this feature. In access I could link one table 'genre' to the field 'genre' in my table 'movies', so I could choose none, one ore multiple genres per movie. When I switched to MySQL I used the SET data type to define all the possible values. So far everything is running perfectly.
I am now trying to set up a table in html/php to show the mysql table. I want the table to be able to sort on: title, genre, quality, rating, etc. But for the sorting on genre, I would need the possible values from the set data type. I don't know if it is possible to get the values with some php command/code, but after I lurked around on the web for a while, I didn't see many applications where they use the SET data type for obvious negative reasons.
So I started looking into the Foreign Key possibility. The problem I have here is that -for as far as I know- the key can only contain one possible value, which puts me right back at the start of my problem. I do like the idea of a foreign key, because it would make it way easier for me to add a new genre to the list.
Is there a possibility I am overlooking? Is it possible to either get the values from the SET type to php or to use a foreign key with multiple possibilities for one record?
I know I can also put every genre in my php script manually, but I'd like to have it all on one place. So that if I add a movie with a genre I haven't defined yet, I can just update it at one place and everything else adapts to it.
Dagon is absolutely right here - you have an issue with the structure of the tables in your back end. You are wanting to model a many to many relationship when at the moment with your current back end the best you can do is a one to many relationship.
To review:
You have individual films that can have many genres
And you have individual genres that are related to many films
Relational databases actually don't model many to many relationships with one relationship they use recursion of the one to many relationship and create two joins.
To model a many to many relationship you need three tables
A film table (which I think you already have)
A genre table (which I think you already have)
A junction table which as Dagon suggests will consist of two fields film id and genre id.
You then set up two separate one to many relationships. One from the film table to the junction table and one from the genre table to the junction table.
Now if you want to know all the genres a film is in you simply filter the junction table on the relevant film id and if you want to know all the films with a certain genre you filter the junction table on the genre id.
Set up lookups to relate your genre ids to textual descriptions and bang you are free to change the textual description as much as you want and the great thing if you've done it right it will upgrade every single value in your forms.
This is an absolute fundamental concept of the algebra of sets behind the design of SQL and relational database design.

Backend app in OO PHP: Structuring classes/tables efficiently

I'm currently working on an app backend (business directory). Main "actor" is an "Entry", which will have:
- main category
- subcategory
- tags (instead of unlimited sub-levels of division)
I'm pretty new to OOP but I still want to use it here. The database is MySql and I'll be using PDO.
In an attempt to figure out what database table structure should I use in order to support the above classification of entries, I was thinking about a solution that Wordpress uses - establish relationship between an entry and cats/subcats/tags through several tables (terms, taxonomies, relationships). What keeps me from this solution at the moment is the fact that each relationship of any kind is represented by a row in the relationships table. Given 50,000 entries I would have, attaching to a particular entry: main cat, subcat and up to 15 tags might slow down the app (or I am wrong)?
I then learned a bit about Table Data Gateway which seemed an excellent solution because I liked the idea of having one table per a class but then I read there is virtually no way of successful combating the impedence missmatch between the OOP and relational-mapping.
Are there any other approaches that you may see fit for this situation? I think I will be going with:
tblentry
tblcategory
tblsubcategory
tbltag
structure. Relationships would be based on the parent IDs but I+'m wondering is that enough? Can I be using foreign key and cascade delete options here (that is something I am not too familiar with and it seems to me as a more intuitive way of having relationships between the elements in tables)?
having a table where you store the relationship between your table is a good idea, and through indexes and careful thinking you can achieve very fast results.
since each entry must represent a different kind of link between two entities (subcategory to main entry, tag to subcategory) you need at least (and at the very most) three fields:
id1 (or the unique id of the first entity)
linkid (linking to a fourth table where each link is described)
id2 (or the unique id of the second entity)
those three fields can and should be indexed.
now the fourth table to achieve this kind of many-to-many relationship will describe the nature of the link. since many different type of relationship will exist in the table, you can't keep what the type is (child of, tag of, parent of) in the same table.
that fourth table (reference) could look like this:
id nature table1 table2
1 parent of entry tags
2 tag of tags entry
the table 1 field tells you which table the first id refers to, likewise with table2
the id is the number between the two fields in your relationship table. only the id field should be indexed. the nature field is more for the human reader then for joining tables or organizing data

Magento - Delete selected products with SQL query

I have about 800,000 products in my magento database, and I need to delete about half of those products (approx 400,000).
Running on magento 1.7.0.2
It's just taking me forever to do it from the "Manage Products" page. The process takes to long and the server keeps timing out.
Is there a SQL statement that can deleted selected products from within the database?
All the products that need to be deleted, the title starts with *NLA
I know magneto stores the product data in several different tables, so I'm trying to figure out how to delete all the data associated with the selected products from all tables.
I know MySQL statements, but I'm not an expert, and can't figure this one out.
For example if it was only one table I would do something like this:
DELETE FROM product_table WHERE title_value LIKE '*NLA%'
I would appreciate it if someone could point me in the right direction.
You can use this query
DELETE FROM product_table WHERE title_value LIKE '*NLA%
Magento used InnoDB engine Storage for MySQL with foreign keys. All data which has FK keys will be also deleted.
Your SQL statement should do the job IF you're deleting from a single table.
If stored on different tables, it depends on the way they are stored. If, for example, products are stored according to their key being a foreign key in the different tables, then all related tables will update when the products are deleted from the main table (depending on whether the foreign keys are set to CASCADE ON DELETE or not).
But be careful about the regex given in LIKE condition, make sure there are no other products that have 'NLA' somewhere in their title.
Edit: you said starting with 'NAL'? In that case your regex should be something like 'NAL*%'
DELETE FROM product_table WHERE title LIKE 'NAL*%'
In Magento product details are stored in data base using EAV concept so there are more then 30 tables where a product data will go.
I suggest you to use Magento import export facility for bulk delete.
refer this link :
magento: bulk delete products via import/export facility?
There is an extension Magmi which can be used as well.

The right database structure and model relations in CakePHP for my project (small shop)?

I have a pretty simple shop-system. I'm working with CakePHP. Actually I wouldn't call it shop, it's rather a basic form where you can type in your data and which items in which color you want and that's it.
There is one buying-form which is "open to the public" and then there are buying-forms which are password secured.
The latter ones have a selection of the items (or selection of colors) which you get on the public site, but have discounts.
I want to save the orders in a database. I have a table orders and ordered_products. That's working fine.
It works pretty good, but only because I made something not very good: Since there are just a few products I just wrote an array in the controller with the names, prices and stuff... the discounts or selection of products I handled by just overwriting the products-property.
Well, putting data in the controller is not really the idea behind the MVC-Structure, so I was thinking about who to handle the products, the selection of products for the different password-secured buying forms and the discounts with models.
My idea was, to create the following tables:
products (id, name, price,...) -hasAndBelongsToMany Color
colors (id, name)
products_colors (product_id, color_id)
Now to set in which "closed-area", which products in which color and with which special price can be ordered I thought of the following tables (the actual table and field names are of course not wise chosen, but just for the idea):
product_selections (id, closed-area_name, product_id, special_price) hasAndBelongsToMany Color
product_selections_colors (product_selection_id, color_id)
When I'm creating the public buying form I would just use the top three tables. but building the "closed-area" I would use the bottom two, selecting the product_ids and special_prices from product_selection as well as the different colors over the product_selections_colors-table for the according "closed-area" (i dont know a better name for that right now...). with the product_id i would get the other information about the product from the table products and create the buying form with this data.
I want to have it all in a database, because then I can better work with the orders (creating receipts, deliverynotes etc.).
I would like to know what you think about that, because I have the feeling that I'm going totally in the wrong direction, since it feel way to complicated for such a simple thing...
I hope you can help me.
Based on your description, I would recommend doing it this way:
Have a users table with a field for "group_id". This allows you to have multiple users with login privileges that all can view the same options or colors based on their grouping.
In the case of a general (non-logged in) user, the assign the group_id to default to 0.
Next, ditch the product_selections and product_selections_colors tables.
You don't want to have to repeat products across tables.
Simply add a new table that pairs which product ids can be purchased by which group_ids. (HABTM relationship in cake)
You will obviously need to tweak this general setup to work specifically for your needs.

Should I create a new table into my database for this?

On my database I have among other tables, products. Products table contains the id, name, description and some other data about the product. I want to add also a category.
Should I create a new table named category with and id and the name of each category, and have into the products a *category_id* that will refers to the id of category, or should I have the name of the category on each row of products ?
On the first case I will have to use JOIN. Will this have a serious impact on the performance?
By defining the categories in their own table you can:
Rename categories
Dynamically generate lists of categories for picking from
Add descriptions of categories
Add new categories
… and so on, without having to update every bit of category related code each time you modify them.
So yes, add a table.
Will this have a serious impact on the performance?
Probably not.
Yes you should keep your data normalized. I think create a new table named category is a good idea.
Will categories tend to change over time? In most instances that will be the case, so you're usually better off with a separate Categories table and a foreign key (FK) between the two tables. You can then add or change categories simply with data changes. Otherwise, you'll want to put a check constraint on the category name column in your table to make sure that you don't get junk data in there and that becomes much harder to maintain.
With proper indexing, the join should only have a minimal cost. Also, keep in mind that you won't always necessarily need to join the tables. You'll only need to join them when you want the actual category name as part of your result set. For example, if you have a look-up box on your front end with the categories and their IDs then your select of the Products only needs to return the category ID values and you don't need to even bother with a join.
The stock answer is "it depends". It depends on how the data is used, will be used, might be used. But once you get through all the discussions and arguments, for something this simple and prominent in your data, nine times out of eight you will be better off properly normalizing the data (i.e. Category table, CategoryId columns, and foreign key).
Only add a table if you require the extra functionality this level or normalization provides.
If you need to rename categories, or list them then yes this is a good candidate. If not then why bother with it, it will make your database slightly harder to read.
Join will most probably not be a performance impact but if you do not need it now, try not to be a victim of over-design.

Categories