php, sql individual links for Group_concat - php

I have three table, movies, artist, and role_table. The role_table holds only movieCode from movies and artistID from artist which are the primary keys of movies and artist table. i used join to get the values and Group_concat. here is my sql code
SELECT m.Title, m.MovieDesc, m.image, m.catagory, a.ID, a.FullName,
GROUP_CONCAT(a.FullName )
FROM movies m
JOIN role_table r ON m.movieCode =r.movieCode_FK
JOIN artist a ON r.artistID_FK = a.ID
where
movieCode = '$movieCode
This code is perfect fine and it works. what i want is to get the individual links for those artist which gets the values from The group_concat.
i am stuck here and any kind of help will be great.
Thanks :)

Doing it in php (assiming you are using a database class):-
<?php
$sql = "SELECT m.Title, m.MovieDesc, m.image, m.catagory, a.ID, a.FullName,
GROUP_CONCAT(a.FullName ) AS ConcatFullName
FROM movies m
JOIN role_table r ON m.movieCode =r.movieCode_FK
JOIN artist a ON r.artistID_FK = a.ID
where movieCode = '$movieCode'";
$db->query($sql) or die($db->error());
while($row = $db->fetch_assoc())
{
$fullnames = explode(',', $row['ConcatFullName']);
foreach($fullnames AS $aFullName)
{
echo "".htmlspecialchars($aFullName)."";
}
}
?>

Related

Can't display query when using inner join with php?

I have a drop down menu form like so: https://ibb.co/eX5BhH
Each selected option will filter the query and return the query. So far, my "disability" and "veteran" option are querying correctly. I'm trying to get the "Type of Resource" category to work by using inner join. Here's the sql command:
SELECT shelter_name, shelter_address, disability, veteran
FROM shelter s
INNER JOIN shelter_type st ON s.shelter_id = st.shelter_id
INNER JOIN s_type stt on st.type_id = stt.type_id
WHERE type_name = "Charitable Organization";
This sql command works but it only query the resources under the "Charitable Organization" category. The user will be able to choose other category so instead of "Charitable Organization" I replace it with "$value_4":
SELECT shelter_name, shelter_address, disability, veteran
FROM shelter s
INNER JOIN shelter_type st ON s.shelter_id = st.shelter_id
INNER JOIN s_type stt on st.type_id = stt.type_id
WHERE type_name = "$value_4";
Here is my php code:
<?php
require'/Library/WebServer/Documents/Require/require.php';
$value_1 = $_POST["county"];
$value_2 = $_POST["disability"];
$value_3 = $_POST["veteran"];
$value_4 = $_POST["resources"];
$sql = "SELECT shelter_name, shelter_address, disability, veteran
FROM shelter s
INNER JOIN shelter_type st ON s.shelter_id = st.shelter_id
INNER JOIN s_type stt on st.type_id = stt.type_id
WHERE type_name = '$value_4'";
$result = mysqli_query($dbc, $sql) or die (mysql_error());
echo"<table border='1'>";
echo"<tr><td>Shelter</td><td>Address</td><td>Disability</td></tr>";
//iterate through the table
while ($row = mysqli_fetch_assoc($result)){
echo"<tr><td>{$row['shelter_name']}</td><td>{$row['shelter_address']}</td><td> {$row['disability']}</td><td>{$row['veteran']}</td></tr>";
}
echo"</table>"; //close table
echo"success";
?>
However, when I use "$value_4", the table doesn't display. If I change it back to "Charitable Organization", the table is displayed again. What can I do to make my table display when I use "$value_4"?
I think to resolve this issue you should be using LEFT JOIN rather than INNER JOIN.
Inner Joins expect data from the left table and right table to match. If it only exists in the left table but not the right then it won't show the records.
By using Left Join you are saying you want everything from the left table and then if there is information from the right table (i.e. the one you're joining on) then bring that too.
It might be worth reading this tutorial on joins to help you get more experience.

Selecting from comments and images table for each article in a while loop

I have an articles table that and I am displaying it in the homepage in a while loop. Inside the while loop I want to display the comments count and images count for each article.
It is working for me now, but it is three queries in total, I am trying to combine it in the first query and then just display all of them in one while loop. Here is what I am trying to achieve:Articles page
The current format I am following:
//a represents articles table, c represents comments table, i represents image table
$query = mysqli_query($conn, "SELECT a.a_id, a.title, a.datetime, a.user_id FROM a ORDER BY a.datetime DESC");
while($fetch = mysqli_fetch_assoc($query){
$imageQ = msqli_query($conn, "SELECT COUNT(image_path), image_path FROM i WHERE a_id = '$fetch['a_id']'");
$imageFetch = mysqli_fetch_assoc($imageQ);
$commentQ = mysqli_query($conn, "SELECT COUNT(comment_id) FROM c WHERE a_id = '$fetch['a_id']'");
$commentFetch = mysqli_fetch_assoc($commentQ);
}
I want to cram all of these queries into one single query that fetches the article and comments count and image count for each article and the first image.
The images and comments are separate dimensions of the data. So, you have to be careful about how to bring them together. In your case, you can aggregate the values before doing the joins:
SELECT a.a_id, a.title, a.datetime, a.user_id,
i.num_images, c.num_comments
FROM a LEFT JOIN
(SELECT a_id, COUNT(image_path) as num_images
FROM i
GROUP BY a_id
) i
ON i.a_id = a.a_id LEFT JOIN
(SELECT a_id, COUNT(comment_id) as num_comments
FROM c
GROUP BY a_id
) c
ON c.a_id = a.a_id
ORDER BY a.datetime DESC;
You can use mysql nested queries something like
SELECT a.,tab1.,tab2.* FROM a INNER JOIN (SELECT * FROM b ) as tab1 INNER JOIN (SELECT * FROM c) as tab2
Hope this can get you to get desired output.
Thanks

Getting many rows through joined tables

I have the id of an album and I'd like to get all the tracks from an album with their artists. An album has many tracks. A track has many producers (artists).
MySQL Structure
Problem
I don't know if I can do it in full mySQL or if I should add some PHP instead.
EDIT : My question wasn't clear enough. The problem wasn't the fact of doing a query with joined table but to get the tracks with a list of the artists. You can handle that with group_concat.
Tutorial : http://www.mysqlperformanceblog.com/2006/09/04/group_concat-useful-group-by-extension/
It depends how you need the data. If you're more interested in the artists then you can join tracks on albums and then artists onto tracks. This will give you a record for each artist.
SELECT
ar.*
FROM albums AS al
JOIN tracks AS t
ON t.album_id = al.album_id
JOIN produced AS p
ON p.produced_track = t.track_id
JOIN artists AS ar
ON ar.artist_id = p.produced_artist
If you're more interested in the tracks and just need to list the artists then do the same join but use group_concat on the artist name and group by the track id
SELECT
t.*,
GROUP_CONCAT(DISTINCT ar.name ORDER BY ar.name SEPARATOR ', ') AS artists
FROM albums AS al
JOIN tracks AS t
ON t.album_id = al.album_id
JOIN produced AS p
ON p.produced_track = t.track_id
JOIN artists AS ar
ON ar.artist_id = p.produced_artist
GROUP BY t.track_id
Learn about SQL joins:
SELECT *
FROM Tracks
JOIN Produced ON Produced.produced_track = Tracks.track_id
JOIN Artists ON Artists.artist_id = Produced.produced_artists
WHERE Tracks.track_album = ?
It's probably best just to do this in pure SQL like so:
SELECT *
FROM albums al
LEFT JOIN tracks tr ON (tr.ttack_album = al.album_id)
LEFT JOIN produced pr ON (pr.produced_track = tr.track_id)
LEFT JOIN artists ar ON (ar.artist_id = pr.produced_artist)
WHERE al.album_id = thealbumid;
However there's nothing preventing you from doing separate queries depending on how you need to use the data.
You can, and you should, do that with pure MySQL, have three tables, link them with foreign keys, and query using JOINs.
You don't need PHP to overload the work, MySQL can handle it just fine :)
You can use LEFT JOIN to achieve this with mysql only:
SELECT * FROM Albums a
LEFT JOIN Tracks b
ON a.album_id = b.track_album
LEFT JOIN Produced c
on b.track_id = c.produced_track
LEFT JOIN Artist d
on c.produced_artist = d.artist_id
WHERE a.album_id = ?
You could do it in SQL using aggregate functions and group by clause.
It should look like:
select t.*,
some_aggregate_function(a.whatever)
from Tracks t
left join Produced p on (t.trac_id = p.produced_id)
left join Artist a on (p.produced_artist = a.artist_id)
group by t.*

Combining 2 queries into 1

I'm looking to optimize two queries into one, if possible.
My first query searches for all the authors of a lyrics... Then, for each author found, i want to find the total numbers of lyrics the author was involded in...
Right now, im executing the first query and for each row found, i'm launching another query to get the authors total lyrics he was involved... So, if there is 4 authors i will end up launching 4 more queries...
That is to many queries in my opinion. That is why i've decided to write here, so i can get help on how to optimize my query...
This is the query i'm executing to get the author(s) responsable for a lyrics:
$sql = "SELECT author.author_id, author.name
FROM track INNER JOIN lyrics_author ON track.lyrics_id = lyrics_author.lyrics_id
INNER JOIN author ON lyrics_author.author_id = author.author_id
WHERE track.track_id = $trackid ";
This is the query to get the total number of lyrics the author as writing:
$total = "SELECT lyrics_author.author_id, count(*) as total
FROM lyrics_author
WHERE lyrics_author.author_id = $author_id
GROUP BY lyrics_author.author_id";
This is a sample of the code:
<?php
$trackid = 5;
$sql = "SELECT author.author_id, author.name
FROM track INNER JOIN lyrics_author ON track.lyrics_id = lyrics_author.lyrics_id
INNER JOIN author ON lyrics_author.author_id = author.author_id
WHERE track.track_id = $trackid ";
$result_author = # $conn->query($sql);
while ($row_author = $result_author->fetch_assoc()) {
$author_id = $row_author['author_id'];
$total = "SELECT lyrics_author.author_id, count(*) as total
FROM lyrics_author
WHERE lyrics_author.author_id = $author_id
GROUP BY lyrics_author.author_id";
$result_total_lyrics = # $conn->query($total);
$t = $result_total_lyrics->fetch_assoc();
echo $t['total'];
$result_total_lyrics->free();
}
$result_author->free();
?>
Is it posible to optimize this query? If yes, how? Is there a link you could refer, so i can learn...
Thanks
Marco
SELECT
author.author_id,
author.name,
COUNT(DISTINCT more_tracks.lyrics_id) AS total
FROM track
INNER JOIN lyrics_author USING (lyrics_id)
INNER JOIN author USING (author_id)
LEFT JOIN lyrics_author AS more_tracks USING (author_id)
WHERE track.track_id = $trackid
GROUP BY author.author_id
That's confusing as heck. Why are you passing in a trackid as a lyricsid when you have a property called lyricsid??
Anyway
Select author.author_id, author.name, Count(*)
inner join
(SELECT lyrics_author.author_id
FROM lyrics_author
INNER JOIN tracks ON track.lyrics_id = lyrics_author.lyrics_id
WHERE track.track_id = $lyricsid";
) as lyricalauthors
inner join lyrics_author on lyrics_author.author_id = lyricalauthors.author_id
On author.author_id = lyricalauthors.author_id
Group By Author.author_id,author.name
I think ...

How do I calculate avg and count on multiple columns involving many tables?

Here are my different tables:
computers (id,name)
monitors (id,name)
computer_monitor (id, computer_id,monitor_id)
useractivity (id,userid,timestamp,computer_monitor_id,ip)
useropinion (id,userid,computer_monitor_id,timestamp,rating)
user (id,name,email)
I want to search after the name of computer or monitor and get a row like this in return:
computer name and/or monitor name
computer_monitor_id
avg(rate)
count(useractivity)
avg(rate) is on that specific computer_monitor_id that matches the name, the same goes for count.
A computer with no connection to monitor has a value of 0 on monitor field in computer_monitor table and vice versa for monitor->computer.
useractivity and useropinion only contains the ID from computer_monitor table
As I understand, the query should be built around the computer_monitor table. All other tables connect to it, including those from which you want to obtain the stats.
SELECT
c.name AS ComputerName,
m.name AS MonitorName,
uo.AverageRating,
ua.ActivityCount
FROM computer_monitor cm
LEFT JOIN computer c ON c.id = cm.computer
LEFT JOIN monitor m ON m.id = cm.monitor
INNER JOIN (
SELECT computer_monitor_id, AVG(rating) AS AverageRating
FROM useropinion
GROUP BY computer_monitor_id
) uo ON cm.id = uo.computer_monitor_id
INNER JOIN (
SELECT computer_monitor_id, COUNT(*) AS ActivityCount
FROM useractivity
GROUP BY computer_monitor_id
) ua ON cm.id = ua.computer_monitor_id
Actually, as you can see, useropinion and useractivity are aggregated first, then joined. This is to avoid the Cartesian product effect when a computer_monitor.id matches more than one row both in useropinion and in useractivity.
<?php
$res_comp = mysql_query("select * from computers where name = '$name'");
$res_monitor = mysql_query("select * from monitor where name = '$name'");
if(mysql_num_rows($res_comp) > 0)
{
$row_comp = mysql_fetch_array($res_comp);
$comp_id = $row_comp['id'];
$res_result = mysql_query("select computers.name, computer_monitor.id, count(computer_monitor_id) from computers, computer_monitor, useractivity where computers.id = '$comp_id' AND computer_monitor_id = '$comp_id' AND useractivity.computer_monitor_id = '$comp_id'");
}
// repeat the same for monitor also. then use mysql_fetch_array to show your data.
?>
hopefully this will help.
This might do the trick...(one table with the computer/monitor relation ship, the other with a xref table threw me, and check the join types depending on your data)
SELECT computers.name AS ComputerName
, monitors.name AS MonitorName
, AVG(useropinion.rating) AS AvgRating
, COUNT(useractivity.id) AS ActivityCount
FROM computers
INNER JOIN computer_monitor ON (computers.id = computer_monitor.computer_id)
INNER JOIN useractivity ON (computers.id = useractivity.computer_id)
INNER JOIN monitors ON (computer_monitor.monitor_id = monitors.id)
INNER JOIN useropinion ON (computer_monitor.id = useropinion.computer_monitor_id) AND (monitors.id = useractivity.monitor_id)
INNER JOIN USER ON (useropinion.user_id = user.id) AND (useractivity.user_id = user.id)

Categories