Result display problem in php and mysql - php

A B C
P_id | name | add P_id | t_id t_id | paper
----------------- -------------- ------------------
1 sam ca 1 1 1 asdxa
2 john de 2 1 2 dgfv
3 sam jk 3 2 3 decgf
4 sam ca 4 3 4 ergvtr
Now I can easily make a search for Name 'sam' in Table A group by name, add. and It shows me result like,
sam ca
sam jk
I am using php and mysql. I want to do some additional task in this:-
--> Totalcount for the rows..Like
sam ca 2
sam jk 1
(I am not taking P_id here... just focus on name and add.)
--> Make a link on 2 and 1 (above). so if I click on it. It should displays the related papers on another html page from table C.
example: if I click on 2... then it should display asdxa and decgf.

--> Totalcount for the rows..Like
SELECT `name`, `add`, count(`add`) FROM `A` WHERE (`name` = 'sam') GROUP BY `add`;
As for the linking, you just link to the page with that ID, and have your php script get the data from the given id in the C table.
To select all matching occurences while searching for a name:
SELECT `A`.`name` AS name, `A`.`P_id` AS aid, `C`.`t_id` AS cid, `C`.`paper` AS paper
FROM `A` , `C`
WHERE (
`A`.`name` = 'sam'
)
AND (
`A`.`P_id` = `C`.`t_id`
)
result:
name aid cid paper
sam 1 1 qwertyui
sam 3 3 zxcvbn
sam 4 4 uytrewq
sam 5 5 hfdsa
Which matches the test tables I did in my local environment

Try to use for the first task
$pdo = new PDO(....);
$result = $pdo->query('SELECT name, add, count(*) from table where name='sam' group by add;')->fetchAll();
if ($result) {
foreach($result as $row) {
......
}
}
//second
$sql = 'select paper from tableA a inner join TableB b on a.P_id=b.P_id inner join Tablec c inner join b.t_id = c.t_id where a.p_id=2';
//repeat previous statements

Related

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.

Count workers in business with branches

Select a group, where is one Main and for example 5 Branch. So, the total of places is 6. In each of those 6, search for 3 workers, who is working as job_types LIKE "%C%". If, in one of those 6 places, are 3workers with given parameter, query must get results of all those 6 places.
To clarify: 3 workers must be working in same main/branch.
Because project itself is very dificult, it would be better, to get results using RAW query:
business table
id | mainorbranch | name
--------------------------------------
1 Main Apple
2 Branch Apple London
3 Branch Apple Manchester
4 Main IBM
5 Branch IBM London
etc ...
Relationship
business_branches table
b_id | branch_id | id
--------------------------------------
1 1 1
2 2 1
3 3 1
4 4 4
5 5 4
// etc
people_details table
d_id | id | job_types
--------------------------------------
1 1 C
2 3 D
3 2 F
4 4 C
5 5 C
// etc
people_branches table
pb_id | branch_id | id
--------------------------------------
1 1 3
2 3 2
3 4 4
4 2 5
5 1 1
// etc
What i need to get:
Business id | Name | Postcode
-----------------------------------------
1 Apple postcode
2 Apple 232 postcode
3 Apple 323 postcode
// etc...
DB Structure for Helpers
http://sqlfiddle.com/#!9/206733
Simplified, minified SQL file with total of 110k+ rows
UPDATE
Answer by #KikiTheOne is kinda working, but it gets only half a results. Other half is missing.
as discussed in Chat. here is a solution:
if u Need Company Infos... get them # t1.XXXX like postcode.
i changed
"pb_id" "branch_id" "id"
"1" "1" "3"
"2" "3" "2"
"3" "1" "4"
"4" "1" "5"
"5" "1" "1"
so i get 3 People in 1 branch
SELECT
t1.id as "Business id",
t1.name as Name,
'postcode' as "Postcode"
FROM SO_business as t1 inner join
(
SELECT * FROM SO_busness_branches as t3
inner join
(
SELECT
t5.branch_id as inner_branch,
count(t5.branch_id) as workers_in,
max(t6.job_types) as job_types,
max(t7.id) as mainbranch
FROM
SO_people_branches as t5
inner join SO_people_details as t6
on t5.id = t6.id
inner join SO_busness_branches as t7
on t5.branch_id = t7.branch_id
WHERE
t6.job_types LIKE '%C%'
GROUP BY
t5.branch_id
) as t4
on t3.id = t4.inner_branch
WHERE t4.workers_in >= 3
) as t2
on t1.id = t2.branch_id
Explanation:
-.1 the Most inner SQL Counts ALL branches with workers ( number of workers init ) and Job_type = %c% and joines the MAIN id of the branch.
-.2 the second SQL gets that info and only selects all branches with workers >= 3
-.3 the outer SQL selects all inner INFOS and gives back ALL branches/main with the branchID-Main from the Inner SQL. AND connects them to the Business table so u can Display all Infos likepostcode from there
hope that this works as it's not as easy to interpret the relationships with the name of the columns in your question.
With this script you can add any group of main/branch to search into
SELECT b.id, b.name, 'postcode' as postcode
FROM business b
INNER JOIN business_branches bb ON (bb.branch_id = b.id)
WHERE bb.id IN (
SELECT bb1.id FROM people_details pd
INNER JOIN people_branches pb ON (pb.id = pd.id)
INNER JOIN business_branches bb1 ON (bb1.branch_id = pb.branch_id)
INNER JOIN business b1 ON (b1.id = bb1.branch_id)
WHERE
pd.job_types like '%C%' AND
bb1.id IN (1,4) -- You can add as many group of businesses (main/branch combinations) using the main branch key
GROUP BY pb.branch_id HAVING count(pb.branch_id) >= 3
)

Return all the rows even the joined table has empty results

In my table 1 I have something like this
name | age
George 42
Bob 30
Ken 23
In my table 2, I have something like this, this is where i store votes for each person.
name | votes |
George 1
Ken 1
George 1
George 1
Ken 1
My goal is to combine the 2 tables, and return all the rows in table 1 even it doesn't exist in table 2.
Desire results:
name | age | total_votes
George 42 3
Bob 30 0
Ken 23 2
But instead I get:
name | age | total_votes
George 42 3
Ken 23 2
I have tried something like this
SELECT `table_1`.*, coalesce(COUNT(`table_2`.votes), 0) AS total_votes
FROM `table_1`
LEFT JOIN `table_2`
ON `table_1`.name = `table_2`.name
You can do one of these:
1) Use Right Join instead of current Left Join.
Or
2) Exchange table1 and table2 places in your join expression, like:
FROM table_2
LEFT JOIN table_1
Try this. This works in MS Access , I think this will work on your's too just convert the query to SQL:
SELECT Table1.name, First(Table1.age) AS age, Count(Table2.Votes) AS totalVotes
FROM Table1 LEFT JOIN Table2 ON Table1.name = Table2.name
GROUP BY Table1.name;
Left Join table1 to table2 so that all entry from table1 , even if its is corresponding data is null, will be included. GROUP BY your query by name so that votes will be counted by name .

Mysql query with IF

I have two tables
Users
Id user grade access_level
1 Alice 1 1
2 Charles 3 3
3 Ben 2 2
Class
Id name grade
1 biology 1
2 math 2
3 geography 2
I can read $username = $_SESSION['MM_Username'] and I want to select for each logged user a list of classes depending on their access_level. For access_level => 3 the user can see all the classes, for access_level < 3 user can see only classes with the same grade with his/hers. So:
For Charles, with access_level=3, I want this result
Id name grade
1 biology 1
2 math 2
3 geography 2
For Alice, with access_level=1 and grade = 1, I want this result
Id name grade
1 biology 1
And for Ben, with access_level=2 and grade = 2, I want this result
Id name grade
1 math 2
2 geography 2
Added from the comment
They have the access_levels based on their position in school. Let's say that Charles is a professor and Alice and Ben are students. Students can see only their classes, but the teacher can see everything.
You could use a INNER JOIN with OR:
SELECT Class.*
FROM
Class INNER JOIN Users
ON Class.grade = Users.grade
OR Users.access_level>=3
WHERE
User='username';
Please see fiddle here.
Try this.
SELECT *
FROM Users as U, Class as C
WHERE U.user = $username
AND U.access_level>=C.grade
I'm not quite sure what are you going to achieve, According to my understanding you can do something like this below.
SELECT u.user,c.name
FROM user AS u INNER JOIN class AS c ON u.grade = c.grade
WHERE u.access_level = 1 AND u.grade = 1
SELECT u.user,c.name
FROM user AS u INNER JOIN class AS c ON u.grade = c.grade
WHERE u.access_level = 2 AND u.grade = 2
SELECT u.user,c.name
FROM users AS u INNER JOIN class AS c ON u.grade = c.grade
WHERE u.grade != 3

not listing users when using innerjoin with max in php mysql

i am new in php i have a problem in my php code.please help me..
i have two tables
seeker
seeker_nic-----username
111-------------ali
222-------------umer
333-------------raza
`
requestblood
id-------seeker_nic-----requireddate
1------- 111 ----------2012/9/9
2 ------- 222-----------2012/5/8
3 ------ 111-----------2012/10/11
4 ------- 111-----------2012/11/12
5 ------- 222-----------2012/7/9
6 ------- 333 ----------2012/4/4
now i want to list users one time with maximum date like..
s.no---- username----- requireddate
1------- ali---------- 2012/11/12
2------- umer--------- 2012/7/9
3------- raza--------- 2012/4/4
i am using this query
"SELECT bloodrequest.requireddate, seeker.username
FROM
bloodrequest
JOIN seeker ON bloodrequest.seeker_nic= seeker.seeker_nic
Join (SELECT max(requireddate)as maxdate FROM bloodrequest) maxresults on
bloodrequest.requireddate = maxresults.maxdate"
..
but it shows only 1 record not the list
and if use this query (left join instead of join)
"SELECT bloodrequest.requireddate, seeker.username
FROM
bloodrequest
left JOIN seeker ON bloodrequest.seeker_nic = seeker.seeker_nic
left join (SELECT max(requireddate)as maxdate FROM bloodrequest) maxresults
on bloodrequest.requireddate = maxresults.maxdate";
then it shows all records with all dates but not tha maximum..
id------seeker_nic -------requireddate<br>
1 ------ ali --------- 2012/9/9<br>
2 ------ ali ---------- 2012/10/11<br>
3 ------ ali ------------ 2012/11/12<br>
4------ umer------------- 2012/5/8<br>
5------- umer -------------2012/7/9<br>
6 ------ raza--------------2012/4/4<br>
You should be able to do this simpler:
select seeker.username, max(requestblood.requireddate)
from seeker
join requestblood on seeker.seeker_nic=requestblood.seeker_nic
group by seeker.username
Feel free to add any sorting order you need.

Categories