Combining two tables - php

I have two tables: Team and player. Team player id's table. When I run the tool url, url and name of the player Starring table, I want to take.
player table
player
p_id p_name p_url
1 Iker Casillas iker-casillas
2 Mesut Ozil mesut-ozil
3 Xavi xavi
4 Victor Valdés victor-valdes
team
t_id t_name t_url player
1 FC Barcelona fc-barcelona 3,4
2 Real Madrid C.F. real-madrid-cf 1,2
team url is running, players want to print the name and url.but I can not get the result. where I make mistakes.
include('confing.php');
$t_url = $_GET["t_url"];
$sql = mysql_query("select player.p_name,player.p_url from player,team where player.t_id = team.t_name and team.t_url='.$t_url.'");
while($write = mysql_fetch_assoc($sql)) {
echo ''.$write['t_name'].'';
}

you need to use FIND_IN_SET
SELECT b.*
FROM team a
INNER JOIN player b
ON FIND_IN_SET(b.p_ID, a.player) <> 0
WHERE a.t_url = 'valueHere'
SQLFiddle Demo
one more thing, your code is vulnerable with SQL Injection, please read the article below to prevent from it
How can I prevent SQL injection in PHP?

Related

Count from selection and access both tables with joins

I stumbled upon a query that I have never done until now.
Before asking the question I looked for if another user had had the same need as me but nothing.
My goal is very simple:
having two tables:
collaboratori (collaborators)
invite (invitations)
I have to count how many invitations the collaborators have made.
table structure of collaboratori:
ID_Collaboratori | cod_manager
37 4675
150 6675
3 6575
table structure of inviti:
invite_id | invite_code_manager
37 6675
39 6575
40 4675
41 6675
if I execute the join obviously I access the two tables in this way:
$q_stats_prod_manager = $connessione->prepare("
SELECT * FROM invite
LEFT JOIN collaboratori
ON collaboratori.cod_manager = invite.invite_code_manager ");
$q_stats_prod_manager->execute();
$r_stats_prod_manager = $q_stats_prod_manager->get_result();
my need lies in showing in a table:
show me for each manager who has his cod_manager inside the inviti table, the number of times he sent them.
Name Surname Manager 1 | Number of invite: 200
Name Surname Manager 2 | Number of invite: 50
Name Surname Manager 3 | Number of invite: 10
not limiting myself to just one counter but also being able to access other table values ​​like any join
I take the liberty of putting the answer that was partially written by another user, adding a detail and explanation for future users. The resolution query for this case is the same:
$q_stats_prod_manager = $connessione->prepare("
SELECT count(invite.invite_id)
/*name of what you want to call the result you will see in the while*/
AS result_count, /*you can call this value whatever you want*/
/*Start | Values ​​of the tables you are interested in selecting*/
collaboratori.nome,
collaboratori.data_registrazione,
invite.invite_code_manager
/*End | Values ​​of the tables you are interested in selecting*/
FROM collaboratori
LEFT JOIN invite
ON invite.invite_code_manager = collaboratori.cod_manager group by invite.invite_code_manager
");
$q_stats_prod_manager->execute();
$r_stats_prod_manager = $q_stats_prod_manager->get_result();
$count_invite_manager=mysqli_fetch_array($r_stats_prod_manager);
$number_of_invite_manager = $count_invite_manager[0];
Select the id of the table you want to count
Give a name you wish you want to name the counted result
Select the values ​​of the tables on which you will perform the join you want to view
Join the tables
Show the result with while
Code while:
<?php while($rowstatspm = mysqli_fetch_assoc($r_stats_prod_manager)){ ?>
<!-- this is the fancy name you associated with your query when you wrote: AS nameofwhatyouwant -->
<?php echo $rowstatspm['result_count'] ;?>
<?php } ?>
You seem to want aggregation. I assume you want all rows for collaboratori, so that should be the first table for the LEFT JOIN:
SELECT c.cod_manager, COUNT(i.invite_code_manager)
FROM collaboratori c LEFT JOIN
invite i
ON c.cod_manager = i.invite_code_manager
GROUP BY c.cod_manager;
Your question doesn't describe where the name comes from. But those fields should be in both the SELECT and GROUP BY.
SELECT count(invite.invite_id),collaboratori.name FROM collaboratori
LEFT JOIN invite
ON invite.invite_code_manager = collaboratori.cod_manager group by invite.invite_code_manager

How should be my mysql table structure?

This is what I want:
Users will send one or two values in my website and I will store them in two variables $genres1 and $genres2.
Like: If user sends, Action, then my code will show all movies with Action genres. If user sends Action+Crime, then my table will fetch all movies with Action+Crime.
Got it?
My current table structure is one to many relationship, like this
tmdb_id movie_title
-----------------------------
1 Iron man
2 Logan
3 Batman
4 The hangover
tmdb_id genres
-----------------------------
1 Action
1 Crime
2 Drama
2 Action
3 Crime
3 Action
4 Comedy
4 Drama
But the problem here is, I can't achieve what I explained above with this.
2nd option: I make a single table like this:
movie_tile genres1 genres2 genres3 genres4
----------------------------------------------------
Logan Action Crime Drama Null
Iron man Action Crime Null Null
And I can do what, I want with this single line:
SELECT * FROM movies WHERE (genres1='$genres1' or genres2='$genres1' orgenres1='$genres3' or genres3='$genres1')
Any other option?
use a table width genres
and use an other table connecting the movie to any genre
-----
movieid title
-----
1 Logan
2 Smurf
-----
-----
genreid genre
-----
1 animated
2 blue people
-----
-----
movieid genreid
-----
1 1
2 1
2 2
-----
that way you won't be limited to 4 genres per movie
now I read your question better.
That's what you do, but you put left out the genre-table.
The 2nd option is bad, as you limit yourself to only 4 categories
Is this connected to PHP? I think is easiest to solve this further by a join query, sorted by movie and a loop in PHP
you want all movies where (by user request) the genres are both Crime And Action?
SELECT mg.movieid, count(1), m.title
FROM movies_genres mg
JOIN movies m ON m.movieid mg.movieid
WHERE mg.genreid = 1 OR mg.genreid =3
group by mg.movieid, m.title
HAVING COUNT(1) = 2
edit: see other genres as well
SELECT movies.movieid,movies.title, genres.genre
FROM movies
JOIN movie_genre mg ON mg.movieid = movies.movieid
JOIN genres on genres.genreid = mg.genreid
WHERE movie.movieid IN (
SELECT mg.movieid
FROM movies_genres mg
WHERE mg.genreid = 1 OR mg.genreid =3
GROUP BY mg.movieid
HAVING COUNT(1) = 2
)
forgot to mention: count = 2, means you gave 2 genreid's to find. This could also be 1, 3 or 25
select distinct a.tmdb_id, a.movie_tittle
from movie_tittle a inner join genre_tittle b
on a.tmdb_id = b.tmdb_id
where b.genres in ('Action', 'Crime')
Based on your comment, try this :
SELECT
a.tmdb_id, a.movie_tittle
FROM
movie_tittle a inner join genre_tittle b
ON
a.tmdb_id = b.tmdb_id
WHERE
b.genres in ('Action', 'Crime')
GROUP BY
a.tmdb_id, a.movie_tittle
HAVING
count(a.tmdb_id) = 2
tmdb_id and genres in table genre_tittle should not duplicated. Make it as primary key.
But the problem here is, I can't achieve what I explained above with [the first two tables]
Yes, you can. Assuming the two tables are called movies and movie_genres, you can select the movies which have both tags using:
SELECT movie_title FROM movies
JOIN movie_genres genre1 USING (tmdb_id)
JOIN movie_genres genre2 USING (tmdb_id)
WHERE genre1.genres = 'Action'
AND genre2.genres = 'Crime'
See it for yourself here.
try something like this :
tableA
Movie_ID Movie_title
1 Iron man
2 Logan
3 Batman
4 The hangover
tableB
Genre_ID Genre_title
1 Action
2 Crime
3 Drama
4 Comedy
tableC
ID Movie_ID Genre_ID
1 1 1
2 1 2
3 2 2
4 2 3
query :
Select A.Movie_title,B.Genre_title
from tableC C
inner join tableA A on A.Movie_ID = C.Movie_ID
inner join tableB B on B.Genre_ID = C.Genre_ID
where
C.Genre_ID in (IFNULL(val1,0),IFNULL(val2,0))
you should make a relational table to solve you issues like so
movie table
movie_id movie_name genre_id
1 alien 2
2 logan 1
3 ps i love you 4
4 click 3
then you will need a genre table
genre table
genre_id genre_type
1 action
2 sci fi
3 comedy
4 romance
then your select would link the to tables
function get_movies_by_genre($genre_id) {
global $MySQLiConnect;
$query = '
SELECT *
FROM movies m
INNER JOIN genre g ON (g.genre_id = m.genre_id)
WHERE g.genre_id = ?
';
$stmt = $DBConnect->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param("i", $genre_id);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
}
return $rows;
}
or
function get_movies_by_genre($genre_id) {
global $MySQLiConnect;
$query = '
SELECT *
FROM movies m
INNER JOIN genre g ON (g.genre_id = m.genre_id)
WHERE g.genre_name = ?
';
$stmt = $DBConnect->stmt_init();
if ($stmt->prepare($query)) {
$stmt->bind_param("i", $genre_id);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->fetch_all(MYSQLI_ASSOC);
$stmt->close();
}
return $rows;
}
This is the base function to get you all information from the movie table depending on which genre id you send to it.
as for multiple ids you can then run the function through a foreach loop for as many genre_ids as you need and then display them as you need.
I hope this helps.

MySQL - Friends Leaderboard ranking by wins and include player in ranking

Platform: MySQL/PHP
Scenario: Create Friend Leaderboard which includes all friends of a player and also include the player in the leaderboard within a single query.
Details: I'm trying to create a query where the results include the player selected along with all their friends. Ranking will be determined on who has the greatest number of wins.
Question: Can this be done within a single query or is it faster to get the result set then compare each friend # of wins to the player # of wins to determine rank order.
Other Details:
Here is the query I have to return a player and their friends along with wins and money total:
SELECT a.profile_id, 'player', a.win AS player_wins, b1.profile_id AS friend_id,
b1.handle AS friend_handle, b1.win AS friend_wins, b1.bankroll AS friend_bank
FROM ldrbrd_cache_tmp a, buddy_tbl b, ldrbrd_cache_tmp b1
WHERE a.profile_id = b.profile_id
AND b.buddy_id = b1.profile_id
AND a.profile_id <> 1
AND b.buddy_id <> 1
AND a.profile_id = 2
ORDER BY a.profile_id, b1.win DESC;
Results:
id | name | player-wins | friend-id | friend-name | friend-wins | friend-money
'2','player' ,'200' ,'50' ,'Freddy K' ,'303' ,'10004572'
'2','player' ,'200' ,'53' ,'dannn' ,'217' ,'92065'
'2','player' ,'200' ,'51' ,'YoDood' ,'126' ,'2383600'
'2','player' ,'200' ,'58' ,'princess' ,'19' ,'89565'
'2','player' ,'200' ,'71' ,'com-on' ,'8' ,'-9530'
'2','player' ,'200' ,'57' ,'foolzzz' ,'7' ,'210'`
The results show the player-wins being 200 so in this case the player should be ranked #3.
You will notice I have the player wins but how can I compare the player wins along with the friend wins to return ranking within the same SQL statement? OR is the best course of action to just assign results to an array then determine where the player fits?
EDIT:
So I came up with a UNION that works, is this the only option??
SELECT profile_id, handle, win FROM (
SELECT a.profile_id, a.handle, a.win
FROM ldrbrd_cache_tmp a
WHERE a.profile_id = 2
UNION ALL SELECT b1.profile_id, b1.handle, b1.win
FROM ldrbrd_cache_tmp a, buddy_tbl b, ldrbrd_cache_tmp b1
WHERE a.profile_id = b.profile_id
AND b.buddy_id = b1.profile_id
AND a.profile_id <> 1
AND b.buddy_id <> 1
AND a.profile_id = 2
ORDER BY profile_id, win DESC) AS player_ranking
ORDER BY win DESC;
This seems to work for now, unless someone has a better solution?

PHP Mysql joinget results

I have 3 tables the subject, student, and relation
The following are sample data
students table
id name
1 John
2 Doe
3 Jane
subject table
id subject
1 Math
2 Science
3 English
relation table
id student_id subject_id
1 1 1
2 1 3
3 2 1
4 1 2
in this case sudent with id=1 has 3 subjects. How can I get result like this?
student name is John
subjects are:
Math
Science
English
I already get the values for student, what I'm trying to do is get his subject to be shown by user.
I'm totally confused using join tables. I'm a newbie in php and I start learning this last week. I'm getting an error on my code. Please help.
My Cuurent code is this:
<?php
//mysql connection
$query = "
SELECT *,* FROM relation, subject
on subject_id = id
WHERE student_id = $student_id
";
$result = mysql_query($query);
?>
Student name is <?php echo $name ?><br />
Subjects are:<br />
<?php
while($row = mysql_fetch_array($result)) {
echo $row["subject"];
}
?>
Start by making sure your query is right. I think this is what you're looking for:
SELECT subjects.*
FROM subjects,
INNER JOIN relations ON relations.subject_id = subjects.id
WHERE relations.student_id = $student_id
It might pay to check it in a mysql client first (e.g., phpMyAdmin). You'll notice in the SELECT part I only have subjects.* because that is all you need.
I actually ask an interview question to weed out people who don't have basic SQL knowledge but claim it on their resume that this is a direct implementation of. It can lead to a good conversation about database design, normalization, de-normalization etc.
What I'd want to see is the basic join syntax that goes hand in hand with the relationship table you've created.
"Select subject from subjects inner join relations on relations.subject_id = subjects.id where relations.student_id = ?".
Taking it the next step you get to
"Select subject from subjects inner join relations on relations.subject_id = subjects.id inner join students on relations.student_id = students.student_id where students.name = ?".
allowing you to query without pre-fetching the student id if you don't want to expose your internal database keys to the external user.
The question mark is for variable binding, its rare that its a reasonable practice to not escape inputs for database interactions. Variable binding for queries is an easy way to get good coverage on that issue.
I love asking this design problem as an interview question because it can quickly lead to discussions about SQL injection, how to sanitize web form input, and general best practices in data management, web application development and database design.
There's the GROUP_CONCAT() aggregate function for this situation:
SELECT students.id, students.name, GROUP_CONCAT(subject.subject) AS subjects
FROM students
LEFT JOIN relation ON students.id = relation.student_id
LEFT JOIN subject ON relation.subject_id = subject.id
GROUP BY students.id
ORDER BY students.name
which will return data like this:
+-------------+---------------+------------------------+
| students.id | students.name | subject.name |
+-------------+---------------+------------------------+
| 1 | John | Math, English, Science |
| 2 | Doe | Math |
| 3 | Jane | NULL |
+-------------+---------------+------------------------+
You can do this without the grouping, in which case you'll get one row for every id/student name/subject name, and then you can use a simple state machine like in OMG Ponies' answer for the display portion.
<?php
//mysql connection
function query($query){
global $conn;
$qu=mysqli_query($conn,$query);
return $qu;
}
$query1 =query("
SELECT * FROM student
WHERE student_id = $student_id
");
$query2=query("SELECT * FROM relation, subject
WHERE relation.student_id = $student_id
AND subject.id=relation.subject_id
");
$name=mysqli_fetch_assoc($query1);
?>
Student name is <?=$name['name']?><br />
Subjects are:<br />
<?php
while($row = mysql_fetch_array($query2)) {
$rew[]=$row['subject'];//For store subject
echo $row["subject"];
}
$subject=join(",",$rew);//Get the stored subject from array
?>
Maybe can help you ?
The simple way to do this, is to query all students:
SELECT * FROM `students`;
and then loop the resultset in php, now for each of the rows you have to make another query to get students subjects:
SELECT * FROM `subject` WHERE `id` IN (SELECT subject_id FROM relation WHERE student_id={$student_row['id']})
assuming $student_row is the name you choose for assigning fetched record.
Now, you do a nested-loop to fetch this query, and print students' subjects.

where id = multiple artists

Any time there is an update within my music community (song comment, artist update, new song added, yadda yadda yadda), a new row is inserted in my "updates" table. The row houses the artist id involved along with other information (what type of change, time and date, etc).
My users have a "favorite artists" section where they can do just that -- mark artists as their favorites. As such, I'd like to create a new feature that shows the user the changes made to their various favorite artists.
How should I be doing this efficiently?
SELECT *
FROM table_updates
WHERE artist_id = 1
OR artist_id = 500
OR artist_id = 60032
Keep in mind, a user could have 43,000 of our artists marked as a favorite.
Thoughts?
This depends on how your database is setup. If I had my way, I'd set it up with a table like so:
Table: user_favourite_artist
user_id | artist_id
---------------------
1 | 2
1 | 8
1 | 13
2 | 2
3 | 6
6 | 20
6 | 1
6 | 3
user_id and artist_id together would be a composite primary key. Each row specifies a user, by id, and an artist they have as a favourite, by id. A query like so:
SELECT artist_id FROM user_favourite_artist WHERE user_id = 1
Would give you the artist_id's 2, 8, and 13. This is a very simple query that will scale to your expectations.
On the reverse, when an artist is updated, you'd run this query:
SELECT user_id FROM user_favourite_artist WHERE artist_id = 2
And you would get the user_id's 1 and 2. This will tell you which users to notify. This query is also simple and will scale.
Maybe you can try this:
SELECT *
FROM table_updates
WHERE artist_id IN(1, 500, 60032)
If you have the marked artists in a secondary table, I would recomend rather using a join.
Something like
SELECT *
FORM table_updates tu INNER JOIN
table_marked_by_user tmbu ON tu.artist_id = tmbu.artist_id
WHERE tmbu.user_id = $user_id
If you're on SQL Server, you can use a nested select statement:
select * from table_updates where artist_id in
(select artist_id from favorites_table where user_id = 10)
If you don't mind doing dirty reads, you can speed it up with (nolock).
select * from table_updates (nolock) where artist_id in
(select artist_id from favorites_table (nolock) where user_id = 10)

Categories