I would like to store a nested associative array in MySQL. I need this for a nestable navigation menu on my site. There should be no limit to the level of nesting.
I have researched the nested set model and the adjacency list, but am unsure of which to use for my needs.
Ideally, I will be able to query my table in a way that I can reconstruct my associative array in PHP and then use this to construct my navigation menu.
Records may be added / changed / re-ordered, but this will only happen infrequently.
I am looking for an example table structure for MySQL (InnoDB), queries to get and re-order the records, and update, delete and add new records. I am using PDO in PHP so any example code of how to turn the record set into the associative array would also be helpful.
Try the following design:
Column 'BEFORE'
Column 'AFTER'
Column 'NAME'
Column 'ID'
Now, just store ID as required.
Example: The navigation menu might be
A --> B --> C
Just give an ID to each entry in the menu and store it with an unique ID.
Then enter the BEFORE and AFTER values as IDs into the table.
So, for B we have
Entry for B:
BEFORE = ID(C)
AFTER = ID(A)
NAME = 'B'
This can be easily expanded for multiple nested menus.
I would suggest following design for implementing the solution.
Table : Navigation
Columns :
ID (INT NOT NULL IDENTITY),
Description (VARCHAR),
ParentID (INT NULL) - Refer its own table ID column,
AdditionalColulmns..
Related
I was wondering if mysql has a way to look at a column and only retrieve the results when it finds a unique column once. For example
if the table looks like this:
id name category
1 test Health
2 carl Health
3 bob Oscar
4 joe Technology
As you can see their are two rows that could have the same category. Is their a way to retrieve the result where the array will one only return the category once?
What I am trying to do is get all the categories in the database so I can loop through them later in the code and use them. For example if I wanted to created a menu, I would want the menu to list all the categories in the menu.
I know I can run
SELECT categories FROM dbname
but this returns duplicate rows where I only need the cateogry to return once. Is there a way to do this on the mysql side?
I assume I can just use php's array_unique();
but I feel like this adds more overhead, is this not something MYSQL can do on the backend?
group by worked perfectly #Fred-ii- please submit this as answer so I can get that approved for you. – DEVPROCB
As requested by the OP:
You can use GROUP BY col_of_choice in order to avoid duplicates be shown in the queried results.
Reference:
https://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html
By using database normalization, you would create another table with an unique id and the category name and by that link those two together, like
select * from mytable1
on mytable1.cat = mytable2.id
group by mytable1.cat
You can ofcourse also use group by without multiple tables, but for the structure, I recommend doing it.
You can use select distinct:
SELECT DISTINCT categories
FROM dbname ;
For various reasons, it is a good idea to have a separate reference table with one row per category. This helps in many ways:
Ensures that the category names are consistent ("Technology" versus "tech" for instance).
Gives a nice list of categories that are available.
Ensures that a category sticks around, even if no names currently reference it.
Allows for additional information about categories, such as the first time it appears, or a longer description.
This is recommended. However, if you still want to leave the category in place as it is, I would recommend an index on dbname(categories). The query should take advantage of the index.
SELECT id, name from dbname GROUP BY categoryname
Hope this will help.
You can even use distinct category.
I have an array of data fetched from a database table that uses the adjacency model to build a heirarchy of topics. Each record contains the following fields:
'id' - a unique AI id.
'name' - a display name.
'parent_id' - the id of a parent topic (can be null for root topics)
The array comes from the database un-nested and sorted by id as you would expect. The 'id' field is random and abritary and cannot be relied upon to produce a useful order. I am seeking a way to sort the array using the parent_id so that it is in the correct adjacency order but without the end result being nested into sub arrays. The list would look like below:
RootTopicA
ATopic1
ATopic2
Child1ofATopic2
Child2ofATopic2
ATopic3
RootTopicB
BTopic1
BTopic2
etc.
Any help or a pointer to an example (even in a different language) would be much appreciated.
You can add a field for example sort in which you would store the order of the same ids in the category.
The other solution is to sort them (in SQL) by ORDER BY parent_id, id or combining the two, ORDER BY sort, using JOINs like (not tested):
SELECT object.id, object.sort, parent.id, parent.sort
FROM objects AS object
LEFT JOIN objects AS parent ON object.parent=parent.id
ORDER BY parent.sort, object.sort;
assuming that objects is your table name, the same table is object as the main object, and parent as object that is its parent (you need it to get sort of parent).
I'm trying to create a web index. Every advertiser in my database will be able to appear on a few categories, so I've added a categorys column, and in that column I'll store the categories separated by "," so it will look like:
1,3,5
The problem is that I have no idea how I'm supposed to select all of the advertisers in a certain category, like: mysql_query("SELECT * FROM advertisers WHERE category = ??");
If categories is another database table, you shouldn't use a plain-text field like that. Create a "pivot table" for the purpose, something like advertisers_categories that links the two tables together. With setup, you could do a query like:
SELECT A.* FROM advertisers AS A
JOIN advertisers_categories AS AC ON AC.advertiser_id = A.id
WHERE AC.category_id = 12;
The schema of advertisers_categories would look something like this:
# advertisers_categories
# --> id INT
# --> advertiser_id INT
# --> category_id INT
You should design your database in another way. Take a look at Atomicity.
Short: You should not store your value in the form of 1,3,5.
I won't give you an answer because if you starting you use it this way now, you going to run into much more severe problems later. No offense :)
It's not possible having comma-separated values to do this strictly in an SQL query. You could return every row and have a PHP script which goes through each row, using explode($row,',') and then if(in_array($exploded_row,'CATEGORY')) to check for the existence of the category.
The more common solution is to restructure your database. You're thinking too two-dimensionally. You're looking for the Many to Many Data Model
advertisers
-----------
id
name
etc.
categories
----------
id
name
etc.
ad_cat
------
advertiser_id
category_id
So ad_cat will have at least one (usually more) entry per advertiser and at least one (usually more) entry per category, and every entry in ad_cat will link one advertiser to one category.
The SQL query then involves grabbing every line from ad_cat with the desired category_id(s) and searching for an advertiser whose id is in the resulting query's output.
Your implementation as-is will make it difficult and taxing on your server's resources to do what you want.
I'd recommend creating a table that relates advertisers to categories and then querying on that table given a category id value to obtain the advertisers that are in that category.
That is a very wrong way to define categories, because your array of values cannot be normalized.
Instead, define another table called CATEGORIES, and use a JOIN-table to match CATEGORIES with ADVERTIZERS.
Only then you will be able to properly select it.
Hope this helps!
This is somewhat of a multipart question, but..
I am looking to query a MySQL table to get fields from a event category table.
Each category has a specific calendar assigned to it, in the "calendar" field in the category table.
I am planning to have a HTML list box for each of the different types of calendars (only 4, and they wont change).
Is there a way to query the category table once, and split the results into different arrays?
Ex.
Sports (only categories assigned to the sports calendar appear here):
(in list box):
Basketball
Baseball
Golf
etc.
then,
General:
(only categories assigned to the general calendar appear here)
etc.
etc.
etc.
I thought to do this in one query, instead of querying the whole table for each calendar type, but will there be that much difference in speed?
I am using PHP, by the way.
Thanks for the help.
You can query the table once and use mysql_data_seek to reset the rowset pointer back to the beginning after having read through it - i.e. iterate over the rowset for category 1, reset the pointer, iterate over for category 2, etc. You need only query once, and iterating over the results is very fast vs. querying.
Alternatively, have four strings each containing the HTML for the content of one of the listboxes, and iterate over the rowset once, appending to the relevant string based on the category of the current record.
I need advices for a table structure.
I need to create menus dynamically.
There will be more than 3 menus.
Some of menus will have multi-level structures.
What is the best way to strucure the menu tables?
All the menus are in one table
Each table should have one table
Any other??
Please give me your experience or common practices for dynamically generated menus please.
assuming your menu tree is not very large, the so-called adjacency list would be the simplest option
id
parent_id
title
other fields
for top level menus parent_id = 0
see Managing Hierarchical Data in MySQL for further discussion and other options
You could use a structure like this:
table name: menu
id - primary key
menu_id - reference to the parent menu item
title - title of the menu
(any other data you need)
this way you can have unlimited levels ...
off course this is not the only way ...
Using parent_id should be enough for most structures, however if you get stuck on performance (with regards to deep recursion), you should also research Modified Preorder Tree Traversal.
http://www.codeproject.com/Tips/354696/Dynamically-populating-menu-items-from-the-databas
this will be helpful,
Dynamically populating menu items from the database in ASP.NET