Joining rows as array from another table for each row - php

I am coding a movie archive script using codeigniter for myself with PHP. I am getting movie's information from IMDb and adding them to my database. I'm adding links for movies I selected using another table called links.
This is the query that I am using to get the movies from database:
$movies = $this->db->query("SELECT *
FROM movies
ORDER BY ".$order['by']." ".$order['type']."
LIMIT ".$limit.", " . $this->config->item('moviePerPage')
);
and I am fetching it in view file like this:
foreach ($movies->result() as $row) {
echo $row->name;
}
Now links must be shown for each movie with the matched IDs (movies could have more than one link). My links table has these columns: 'id', 'movieid', 'name', 'link'
How can I get links for each movie with single MySQL query? Is is posible to get all links that related to current $row movie and bind them to a single variable as array? with this I can loop it with foreach() and show links for each movie.
btw: movies.movieid and links.movieid columns have the same data.

I think you need mysql's GROUP_CONCAT
Do something like this:-
SELECT
movies.*,
group_concat(links.link ', ') as links
FROM movies
LEFT JOIN links
ON links.movieid = movies.movieid
GROUP BY movies.movieid
You will get a comma separated list of links for every movie.
Which you can extract like this:-
foreach ($movies->result() as $row) {
$linksArray = explode(",",$row->links);
}
Updates
I think this is the only way you can get the results without having multiple result rows for a single movie with multiple links.
Just be careful of the maximum length of characters you can get in the result - by default 1024 characters. Read this
Mysql group_concat_max_length and Group concat max length to know how to override the limit.
And like Dan Grossman has poined out, if you feel the links may contain comma, use a different or uncommon delimiter.

JOIN the two tables, just as your question name implies.
SELECT
movies.*,
links.*
FROM movies
LEFT OUTER JOIN links
ON links.movieid = movies.movieid
...
You will get one row per movie-link pair. If there are no links for a movie, you'll get a row with just the movie information and NULLs in the columns corresponding to the links table.
You can loop over these results and put the links for each movie in an array keyed by the movie, if you'd like.

Related

PHP MYSQL - Search comma separated list with a comma separated list

Dear Stackoverflowers,
I have a mysql query which checks if some sub categories are part of a categoryID to show all products from subcategories in the main category.
For example:
Category
Subcategory 1
Subcategory 2
Subcategory 3
For example products are added to subcats but are ALL beeing shown in the head category.
This works fine and i do this with WHERE cID in (' . $subids . ')
But now comes it, the cID used to hold just one value but since it has to be possible to add products to multiple categories i now save the multiple selected ids as comma separated in the cID field.
So im searching for a way to basicly find a match from a comma seperated list within a comma separated list because cID has now become comma separated ID's and FIND_IN_SET does not work with this.
I hope someone can shine some light, thank you all!
Have a read of these:
Many-to-many data model
Junction table
Implementing this, as opposed to comma-separated values, should probably save you and your coworkers a lot of headache and simplify your queries, effectively eliminating the need of complex queries. It should be faster, too.
Add full-text search index on this column in the database and then use following sql query
Ref - http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
Storing a CSV in a single field is not a good idea. Searching on that requires use of LIKE clause.
where CID LIKE '$cid1,' or CID LIKE ',$cid1,' or CID LIKE ',$cid1' or
CID LIKE '$cid2,' or CID LIKE ',$cid2,' or CID LIKE ',$cid2' or
.... so on
Also FIND_IN_SET would work too.
where FIND_IN_SET( $cid1, CID ) OR FIND_IN_SET($cid2, CID) .. so on
i now save the multiple selected ids as comma separated in the cID field. That's a very bad approach ,why would you store a CSV in a single field ,you shud change your design ,make a seperate table where each value will have a new row and will be mapped to a FK.
What you really need to do,is work on your DB design,read on Normalization and other related topics,I have so added some links,
MSDN Link on Many to Many
Databae Normalization

Codeigniter count number of articles in one category while listing categories

I have some problem while listing categories from database.
First i have a table called "Videos" where i store som videos-information like v_name, v_description and category_name.
In the second table called "Categories" where i store categories-information like c_name and c_description.
OFC i have id's in every table :)
But now i want to list the categories and in the same query count every videoitem in every category.
This is the code and i can't figure out how to do in the model now and later how to show the numbers in the view file, so pleace help me!
Thanks for your time and support :D
$this->db->select('c.*');
$this->db->from('categories as c');
$this->db->join('videos as v', 'c.c_name = v.v_category', 'right');
return $this->db->get()->result_array();
For your code to work you need two changes:
First you join type should be a "left join". Than way you still will get a count result (0) even if a category has no videos yet.
Second you need to group your results to be able to use the aggregate function count().
Try with this:
$this->db
->select('categories.c_name, COUNT(videos.id) as num_videos')
->from('categories')
->join('videos', 'categories.c_name = videos.v_category', 'left')
->group_by('categories.c_name');
Also you should reconsider your DB design. If you have id columns in both tables (wich I assume are the primary key) then you should define the relationship between the tables (foreign keys) using the id column, not the name.

Non standard sorting and navigation using MySQL and PHP

I am trying to sort the information given to me by the API of an engineering journal. I have extracted the following information into a table:
ID (integer),
Journal Entry Name (Text),
Description (Text),
Page Length (integer),
Has Media (boolean)
Each "Journal Entry" has only one ID associated with it. Each ID also has other characteristics that are not returned by the API but that I want to use to sort. They are:
Category (Things like Econ, Math, Biology. Each ID can have more than one category)
Boolean values (Things like requiring special subscriptions)
I have created a second table in the following format:
ID (integer),
Category (text),
Boolean1 (bool),
Boolean2 (bool),
Boolean3 (bool)
Since each ID can have more than one category, when this occurs another row is added to this table. The idea being that any given row only has one ID and one category in it.
What I want to do is this:
Be able to find the top ten categories when it comes to
Highest Journal Entry (ID) count
Highest Total Page Length
Highest Journal Entry count where the "Has Media" boolean is true
Create a means of navigating like "pagination" where each page shows the nth results of the aforementioned top ten.
So if I chose to Highest Journal Entry count method, the first page would be show IDs, Names, and Descriptions of all the Journal entries in the category with the highest count.
My plan has been to create a new table where the numbers one through ten are in the first column, and then populate the second column with the top ten categories. Then I can use a process similar to pagination in which the nth page only shows the values with the corresponding category from the original value. However I can't seem to be able to make this top ten list/matrix, nor do I know if it there is a better way.
Unfortunately I am not a MySQL or PHP coder by trade, and have only gotten this far by lots and lots of googling. I have been completely unable to find any guides for a navigation method like the one I want. And since I don't know the proper terminology, I am just trying random google searches at this point.
Is this the best way to go about it? Or would it be better to create a third table of some sort? Is there perhaps an easier way to do this with something that can use the PHP and MySQL code I already wrote?
Not sure I really understand what you're going for here, but my best guess is that you probably want to combine your two initial tables and have category be a set rather than an individual term so you can have a single entry per unique ID.
Then you'd just need to write calls for each of your top ten finds as needed. Since each id can have an unknown number of categories I would start with a limit of 10 and then process the returns starting with the top match, grab its categories, if there are more than 10 grab the first 10, if there are less than 10 grab what there are, update the amount you're looking for (if there were 4 then you're now looking for 6), and move on to the next best match.
Maybe something like this:
categories = null;
$delimeter = ',';
$count = 1;
$top10 = array();
$result = mysql_query("
SELECT *
FROM table_name
ORDER BY page_length DESC
LIMIT 10");
while($row = mysql_fetch_array($result) && $count <=10)
{
$categories = $row['categories'];
$id = $row['id'];
$splitcontents = explode($delimeter, $catagories);
foreach($splitcontents as $category){
if (!in_array($catagory,$top10)){
$top10[$count] = array(
'category'=>$category,
'journal_id'=>$id
);
$count++;
}
}
}

filtering number of rows with similar content in php mysql

I'm trying to have mysql outputting a list of article categories.
there are lots of articles, each with preset categories that are stored in mysql. But many articles have the same category, so my list get very long with similar category results.
My idea is that if the user has posted 1 post in a category, the category gets listed. but this needs to understand that the category should just be listed once even if the user has posted multiple times in that specific category. How can i do this?
This is what i got, but not working:
foreach( $result as $row ) {
if($result>1){
$kategorilink= "{$row['kategori']}";
echo $kategorilink;
}
}
Try SELECT DISTINCT * FROM .... This will give you each different value only once.
modifying mysql data in php is not a good idea, you can select disting categories from mysql like
select distinct(category) from article where full_name='$safe_name'
or you can add group by clause to your query to group your result according to categories
select * from article where full_name='$safe_name' group by (category)
if you want to check number of results you can use mysql_num_rows() like
if (mysql_num_row($result) > 1){ //code here}

Joining multiple entries to single entry

I have 2 tables, one lists Properties (Houses, flats etc) and the other table holds image filenames and an ID to link to the relevant Property.
Now, I need to join these together, but in a way so that I only get the Property information returned once, and then the X number of image records that are linked.
I have had some success using a LEFT JOIN, in that I can select the records, but it is returning duplicate info for the Property e.g. 1 Property linked to 3 images would return 3 results from the LEFT JOIN query and thusly on my output page, print the details 3 times.
The next part after that is how do I print the Property details (which should now be singular) and the multiple image information?
Hope you can help!
You can use a group_concat function to get a list of the file names. By default, this will only allow you to have 1k of data in the resulting group_concat field.
select prop.*, group_concat(filenames) as files
from properties prop
join images on prop.id = images.prop_id
where prop.owner_id = 'something'
group by prop.id
You can tweak the group_concat_max_len property if you need more data in that field.
Then in PHP you would look over resulting query, and you can explode each of the files column, and loop over the resulting array to display the images.

Categories