Pull the top three items from the database in php - php

I am trying to pull a list of genres from the database. I enter a list of genres into the database for each song, and then it (is supposed to) pull each song's genre into a list and order them by the top three most common occurrences.
The genres get put into a single text field in such a fashion:
(basic fashion, not an actual result):
blues rock, garage rock, hard rock
Here's my code:
$sql = "SELECT `song_name`, `song_genres` FROM `songs` WHERE `album_id` = '$songAlbumId'";
$query = mysqli_query($conn, $sql);
while ($row = mysqli_fetch_array($query)){
$song_name = $row['song_name'];
$song_genres = explode(", ", $row['song_genres']);
for ($i = 0; $i < count($song_genres); $i++){
$count=array_count_values($song_genres);//Counts the values in the array, returns associatve array
arsort($count);//Sort it from highest to lowest
$keys=array_keys($count);//Split the array so we can find the most occuring key
echo $keys[$i] . "<br>";
}
}
This ends up giving me:
Hard Rock
Garage Rock
Hard Rock
Garage Rock
Psychedelic Rock
Blues Rock
Garage Rock
Hard Rock
Also note there is nothing wrong with the album id or anything else. It is specifically to do with just the genres being ordered right.

Normalize the genres. Use a genres table instead of a comma separated list, and an additional songs_genres table to link songs to genres. Then you can get the data from the database without further logic in php
SELECT g.name, COUNT(DISTINCT(sg.song_id)) cnt
FROM genres g
INNER JOIN songs_genres sg ON sg.genre_id = g.id
GROUP BY g.name
ORDER BY cnt DESC
LIMIT 3

You need another loop so your genres echo for each songname
while ($row = mysqli_fetch_array($query)){
$song_name = $row['song_name'];
$song_genres = explode(", ", $row['song_genres']);
foreach($song_name as $songname){
for ($i = 0; $i < count($song_genres); $i++){
$count=array_count_values($song_genres);//Counts the values in the array, returns associatve array
arsort($count);//Sort it from highest to lowest
$keys=array_keys($count);//Split the array so we can find the most occuring key
echo $keys[$i] . "<br>";
}
}
}

I spent a couple days trying to figure it out. I ended up reworking the database and posting the songs genres into a database for the song, album, and band sections to easily pull from.
For anyone in the future who wants help with a problem like this, the solution is here: Merge multiple arrays into one array.
I appreciate the input from the other people though.

Related

Saving data from database into associative array with counting up - PHP

I would like to sort data from my database. I want to use associative arrays so it can be sorted the best.
I get all the data from a database, as said above. By doing $row['manufacturer'] I'll get some data like the following:
motorola
sony
motorola
google
samsung
lg
samsung
I would like it to be saved like this in the array: (order is not important, although alphabetically is preferred)
"motorola" => 2
"sony" => 1
"google" => 1
"samsung" => 2
"lg" => 1
I tried it by doing this, but it just didn't work and caused my web host to clean the logs, as it caused almost 2 gigs of log files.
The code I wrote to save it
$manufacturers = array();
//$row are the rows from my database. I will not add them, but by doing $row['manufacturer'] you'll get some brands like google, motorola, etc.
while($row = $resultSelect->fetch_assoc()) {
for ($i = 0; $i < $manufacturers; $i++) {
$alreadyEntered = 0;
if ($manufacturers[$i] == $row['manufacturer']) $alreadyEntered = 1;
if ($alreadyEntered == 0) {
$manufacturers[$row['manufacturer']] = 1;
} else {
$manufacturers[$row['manufacturer']] += 1;
}
//It caused huge logs, so I decided to break on 50.
if ($i > 50) {
break;
}
}
}
//Dump it :) to see if it worked
var_dump($manufacturers);
I have no idea how I can make it work. I tried searching on Google and SO for setting values in associative arrays, but nothing worked.
EDIT:
My rows:
You could do it through SQL query.
Using the count and group by query.
SELECT name, COUNT(*) as total
FROM manufactures
GROUP BY name
ORDER BY name ASC
name is your manufactures name column. manufactures is your table name.
Example PHP code:
$sql="SELECT name, COUNT(*) as total
FROM manufactures
GROUP BY name
ORDER BY name ASC";
$result=mysqli_query($con,$sql);
while($row = mysqli_fetch_assoc($result))
{
echo "Name: ". $row['name'] . " Total: ". $row['total'] . "<br>";
}
Brief explanation:
What the query will do is that it will select all manufactures name, and count them. By in the same time, it will group together the names, which means, multiple same name will be grouped together, and counted together. Finally order by name asc is used to sort the result alphabetically in ascending order (A->Z).

How to use joins in code?

I'm actually not too sure if I even need a join. It's really the only thing while learning SQL that I didn't really understand or pay attention too, but basically I have 2 tables:
games
subgames
In games I have gamesname row:
Final Fantasy
Metal Gear Solid
Yu-Gi-Oh
In subgames I have subgamesname row:
Metal Gear Rising
They both have autoincrement for an id. However I am trying to display my games as clickable links then refreshes the page and shows the subgames. So for example if I clicked Metal Gear Solid it would take you to games.php?subgame=Metal%20Gear%20Solid and show Metal Gear Rising. Here is what I have so far, but it does not show Metal Gear Rising, probably because I have the games in one table and sub games in another with no reference to each other.
So my question is, how can I reference them in my code to display properly?
<?php
$sub = $_GET['subgame'];
if($sub){
$result = mysql_query("SELECT $sub FROM games");
while ($row = mysql_fetch_array($result)) {
printf("%s<br />", $row["subgamename"], $row["subgamename"]);
}
}
else{
$result = mysql_query("SELECT gamename FROM games ORDER BY gamename");
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
printf("<a href='games.php?subgame=%s'> %s </a><br />", $row["gamename"], $row["gamename"]);
}
}
?>
Your query it's wrong. What is:
$result = mysql_query("SELECT $sub FROM games"); ????
it should be
mysql_query("SELECT subgamesname FROM subgamesname where gamesName ='".$_GET['subgame']."'");
But your name of parameter it's not intuitive subgame, it's should be gameName because you search through games name
The query you probably want is:
$sub = mysql_real_escape_string($_GET['sub']);
$query = "
SELECT subgamesname
FROM subgames s
JOIN games g ON g.id = s.game_id
WHERE g.gamesname = '$sub'
";
I'm assuming the subgames table has a game_id column that's a foreign key to the games table. You need to replace those column names with what you're actually using in your schema.

Codeigniter / PHP, 2 Mysql Tables, Multiple Queries

I have 3 tables 1 is an item table, one is a note table and the other is a note image table.
When a user views item details, all notes are picked up for that item (there is a item_id field in the note table)
The notes can have multiple images attached to them these are stored in flat file but are referenced by the "note image" table.
Now when displaying item details I run a query to get all notes for a item... simple enough, then these results are looped through to output them onto the page.
Problem now arises after adding images to notes, how would you go about querying all notes for a item say
SELECT * FROM notes WHERE item = 1
then how would you loop though the result array getting all note images for a note say
SELECT * FROM note_img WHERE note_img_noteid = 27
Its hurting my head a little because I can't visualize how to get the results and output them in PHP.
---EDIT---
Think I may of got it,
SELECT
d.door_note_id,
d.door_note_doorid,
d.door_note_timestamp,
d.door_note_editedtime,
d.door_note_text,
u.user_name AS created_by,
e.user_name AS edited_by,
i.door_img_id AS img_id,
i.door_img_url AS img_url
FROM
user u,
door_note d
LEFT JOIN
user e
ON
user_id = d.door_note_editeduserid
LEFT JOIN
door_img i
ON
door_img_noteid = d.door_note_id
WHERE
d.door_note_doorid = 214
AND
u.user_id = d.door_note_userid
Then I use this:
foreach ($result->result() as $row){
if(!isset($my_items[$row->door_note_id])){ //the note id becaoms a key
//here you set up an array for all the note details
$my_items[$row->door_note_id] = array('door_note_id'=>$row->door_note_id,
'door_note_doorid'=>$row->door_note_doorid,
'door_note_timestamp'=>$row->door_note_timestamp,
'door_note_editedtime'=>$row->door_note_editedtime,
'door_note_text'=>$row->door_note_text,
'created_by'=>$row->created_by,
'edited_by'=>$row->edited_by,
'images'=>array());
}
//if the note has any images add them to the images array for that note.
if(isset($row->img_url)){
$my_items[$row->door_note_id]['images'][] = $row->img_url;
}
}
Its very hard to know when you haven't post your relationships in a table but taking some assumptions
$query = "SELECT items.id as item_id, items.name as item_name, notes.id as note_id,
notes.description as note_description, note_image.image as note_image from notes
LEFT JOIN notes ON items.id = notes.item_id
LEFT JOIN note_image ON notes.id = note_image.note_img_noteid";
//this wil fetch all you items with description, notes and images, because item can have multiple notes, your result wil have multiple entires of the item. so you have to index correctly to use in views
$result = $this->db->query($query)
$my_items = array();
foreach ($result->result() as $row){
if(!isset($my_items[$row->item_id])){ //you item it becaoms a key
//here you set up an array for all your items
$my_items[$row->item_id] = array('item_name'=>$row->item_name, 'notes'=>array());
}
//here you stroe all images fro a note
if(!isset($my_items[$row->item_id]['notes'][$row->note_id])){
$my_items[$row->item_id]['notes'][$row->note_id] = array('note_description'=>$row->note_description, 'images'=>array());
}
$my_items[$row->item_id]['notes'][$row->note_id]['images'][] = $row->note_image;
}

search for element in a php array

I've got
a users table named "members"
a rooms table named "rooms"
a table that associates the user id to the ids of the rooms "membersRooms"
I should write a loop that prints a dropdown for each user with all the rooms, but that adds the attribute "selected" to rooms associated with the user
What's wrong with this loop?
$members = mysql_query("SELECT * FROM members ");
$rooms = mysql_query("SELECT * FROM rooms");
while($member = mysql_fetch_array($members)){
echo("<select>");
$roomsOfUser = mysql_query("SELECT roomID FROM membersRooms WHERE userID=".$member["id"]);
$cuArray = mysql_fetch_array($roomsOfUser);
while($room = mysql_fetch_array($rooms)){
if(in_array($room["id"],$cuArray,true))
echo("<option selected='selected'>".$room["roomName"]."</option>");
else
echo("<option>".$class["roomName"]."</option>");
}
echo("</select>");
}
To make this a little easier on you, you could try utilizing left and right joins on your database. This would significantly reduce your server load and still allow you to do the same functionality.
I believe, if I'm reading your database structure right, that you'ld want something along the lines of:
SELECT members.id as memberID, rooms.id as roomID, rooms.roomName, membersRooms.roomID as memberRoom
FROM members
LEFT JOIN membersRooms
ON members.id = membersRooms.userID
RIGHT JOIN rooms
ON membersRooms.roomID = rooms.id
Then in PHP you should be able to just keep track of when your memberID changes, and when it does, start a new select. If I didn't totally bungle that SQL (which I might have) then the resulting rows should look something like:
memberID | roomID | roomName | memberRoom
1 1 foo 1
1 2 bar 1
2 1 foo 1
2 2 bar 1
So on your loop iteration you would use roomID and roomName to build your select, and if RoomID matched memberRoom then you would select that row.
$rooms query while is dead
while runs once time in while
put this $rooms = mysql_query("SELECT * FROM rooms"); query line
in first while
OK, so you need information from 3 tables - members, rooms, and membersRooms. The rows from members and membersRooms line up 1:1, so we can get both of those with 1 query.
This method will minimize the number of queries needed - if you ever see yourself querying the database in a loop, ask yourself if there's a better way.
$member_query = mysql_query("SELECT * FROM members LEFT JOIN membersRooms ON (members.id = membersRooms.userID)");
$room_query = mysql_query("SELECT * FROM rooms");
$rooms = array();
while ($room = mysql_fetch_assoc($room_query))
$rooms[] = $room;
while ($member = mysql_fetch_assoc($member_query)) {
echo '<select>';
foreach($rooms as $room) {
echo "<option value='{$room['roomID']}' ";
if ($member['roomID'] == $room['id'])
echo 'selected="selected"';
echo ">{$room['roomName']}</option>";
}
echo '</select>';
}
It's worth noting that if members:rooms is a 1:many relation, you don't need to use a third table to join them - just add a roomId to members, and you're fine.

Join two MySQL Tables and display combined data

I have two tables in my database.
cat - catid, catname
articles - id, catid, content
so what i want to display is category name (catname) and how many articles are there in that category.
This is my code but it dosent work.
$query = "SELECT cat.cname, COUNT(articles.cat_id)".
"FROM cat, articles ".
"GROUP BY cat_id";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
echo $row['cname']. " - ". $row['COUNT(cat_id)'];
echo "<br />";
}
Any help will be most aprriceated. thanks.
So this is a 1:many relationship. i.e. 1 Category -> Many articles.
The best way to do this is to create a third table, an adjacency list.
Keep your 'category_id' and 'article_id' unique in tables 'cat' and 'article'.
In your third table you define the 1 : many relationships.
Table 3: cat_articles
adj_id cat_id art_id
1 1 1
2 1 2
3 2 3
4 2 4
5 3 5
Now join the tables:
$sql = "SELECT * FROM `cat_articles` adj ".
"LEFT JOIN (`cat` cat, `articles` art)".
"ON (cat.cat_id = adj.cat_id AND art.art_id = adj.art_id) ";
This takes the adjacency table, preserves it's format(due to left join) and appends the tables article and category to it, giving you a categorised table of all your articles. You can now use mysql_fetch_array() to get your results.
Edit: reference first comment, displaying number of rows
You can either, as you have done, use SQL's function COUNT to return a count of a specific column.
Or, with PHP, run the query, and then use mysql_num_rows($result) to return the number of rows SQL has in its buffer.
Alternatively, retrieve results using mysql_fetch_array($result) and use count to return the number of paired values in the array.
Using mysql_fetch_array:
$query = "SELECT cat.cname, COUNT(articles.cat_id)".
"FROM cat, articles ".
"GROUP BY cat_id";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
echo $row[0]. " - ". $row[1];
echo "<br />";
}
mysql_fetch_array returns a number indexed array (0,1,2,3,4, ..)
SELECT cat.cname, COUNT(articles.cat_id) artcount
FROM cat, articles WHERE c.cat_id = articles.cat_id
GROUP BY cat.cat_id
I guess you are missing the join clause. Unless you are joining the tables correctly you are creating a "cartesian product".
Get the rows "$row['cname'] and $row['artcount'].

Categories