Trying to combine three tables base on my situation mysql php? - php

I am trying to connect three table. The output will be like this: Get fruit match price 4 first on table_1 and exclude any fruit with mark 6 on table_2, then at last, on table_3, if the fruit factor match, then get the value of val, if not, I still keep the fruit with val NULL value. I was thinking JOIN, but not so sure how to combine three tables to do what i want. Help, appreciate.
<?php
/*
table_1
fruit price
apple 4
banana 5
pear 4
table_2
fruit mark
apple 5
banana 4
pear 6
table_3
fruit factor val
apple 56 good
banana 89 good
pear 56 bad
*/
$sql = $wpdb->get_results( $wpdb->prepare("
SELECT a.fruit, b.fruit, c.fruit, c.val
FROM table_1 a, table_2 b, table_3 c WHERE a.price = %d AND b.fruit NOT IN
( SELECT fruit FROM table_2 WHERE mark =%d ) AND c.fruit = a.fruit OR c.factor = %d
",$price,$mark,%factor));
foreach($sql as $sqls){
$result1 = $sqls-> a.fruit;
$result2 = $sqls-> c.val;
$result[] = array($result1=>$result2);
}
?>

SELECT
a.fruit,b.mark,c.factor,c.value
from table_1 a,
left join table_2 b
on b.fruit=a.fruit and b.mark != 6
left join table_3 c
on c.fruit=a.fruit

Related

SQL Query with two different filters

I have a page which shows all cars from DB.
I have two filters , both are multiple select filter.
For example
filter 1 - Color
Red , green , blue <-- All these are checkbox ,can be selected multiple
filter 2 - brand
BMW, Honda , Hyundai <-- All these are checkbox ,can be selected multiple
I have done below query
Select * from cars
JOIN term_car_relationships
ON cars.id = term_cars_relationships.car_id
WHERE term_cars_relationships.term_id in (6,2,3)
GROUP BY cars.id
In above query term_id
6 = blue (Color)
2 = green (Color)
3 = BNW (brand)
But with above query I will get all cars which has blue color or green color or BMW brand
But how to change in such a way that I get BMW which is blue or green color.
I have 3 tables which handles these categories.
taxonomy table
taxonomy_id | taxonomy_title
1 | Color
2 | Brand
term_list
term_id | term_name | taxonomy_id
1 | Blue | 1
2 | Red | 1
3 | BMW | 2
4 | Honda | 2
term_cars_relationships Table
term_id | car_id
1 | 1
1 | 2
2 | 3
You should join the term_cars_relationships table twice:
SELECT * FROM cars
JOIN term_car_relationships c ON cars.id = c.car_id
JOIN term_car_relationships b ON cars.id = b.car_id
WHERE c.type_of_category = 'color'
AND b.type_of_category = 'brand'
AND c.term_id in (6,2)
AND b.term_id in (3)
GROUP BY cars.id
Note that I used b.term_id in (3) instead of b.term_id = 3 since I assumed you might want to select multiple brands.
You can construct your query with separate joins for each term category, and separate filter conditions for each as well.
SELECT cars.*, colorTerms.*, brandTerms.*
FROM cars
INNER JOIN term_car_relationships AS carColorTerms
ON cars.id = carColorTerms.car_id
INNER JOIN term_list AS colorTerms
ON carColorTerms.term_id = colorTerms.term_id AND colorTerms.taxonomy_id = 1
INNER JOIN term_car_relationships AS carBrandTerms
ON cars.id = carBrandTerms.car_id
INNER JOIN term_list AS brandTerms
ON carBrandTerms.term_id = brandTerms.term_id AND brandTerms.taxonomy_id = 2
WHERE colorTerms.term_id IN (6, 2)
AND brandTerms.term_id IN (3)
Of course, to construct this query, you will need to know the terms' types before the query.
Also, using GROUP BY cars.id without aggregation is probably a sign of a problem, or just not the right way to get what you want. If you only want the information from the cars table, you should just SELECT DISTINCT cars.*. Using GROUP BY in this manner will end up with results with the data from just one color-brand match for each car.
With the complexity the edit to the original question added, another possibility presents itself....
SELECT cars.* -- You should really just select the fields you want, and may have to in some configurations (see GROUP BY)
FROM cars AS c
INNER JOIN term_car_relationships AS tcr ON c.car_id = tcr.car_id
INNER JOIN term_list AS tl ON tcr.term_id = tl.term_id
WHERE tcr.term_id IN (6, 2, 3)
GROUP BY cars.car_id -- In some configurations of MySQL, and most other RDBMSes, you must specify every SELECTed non-aggregated field here
HAVING COUNT(DISTINCT tl.taxonomy_id)
= ( SELECT COUNT(DISTINCT taxonomy_id)
FROM term_list
WHERE term_id IN (6, 2, 3)
)
Note: This final solution does not actually require you to know term taxonomies ahead of time anymore, and does not grow as more taxonomies need supported; so while it is a little less obvious with what it is doing, is probably definitely worth considering.

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.

How to do operation on an output tables in sql or php

I have these tables
courses students_records
--------------------- --------------------------------
NO code CRD name ID NO grade
--------------------- --------------------------------
1 COE200 4 Michael 2255 1 A
2 COE305 3 Michael 2255 2 B+
grades
---------------------
NO. points
---------------------
A 4
B+ 3.5
I wrote this query
SELECT courses.code,student_records.grade,courses.crd,grades.points FROM grades INNER
JOIN student_records ON grades.letter = student_records.grade INNER
JOIN courses ON courses.no = student_records.no WHERE student_records.id=2255;
so the out put of this query will be like this
grades
------------------------------
code grade CRD points
------------------------------
COE200 A 4 4
COE305 B+ 3 3.5
My question is How I can write function in php or query in order to
multiply CRD and points and do sum after multiply like this.
(CRD * points)
(4*4)+(3*3.5)=26.5
You can perform the math in the SQL Select and an aggregation to do the sum.
To get the grade/credits to show, you can use this query:
SELECT
courses.code,
student_records.grade,
courses.crd,grades.points,
courses.crd * grades.points AS grade_credits
FROM grades
INNER JOIN student_records ON grades.letter = student_records.grade
INNER JOIN courses ON courses.no = student_records.no
WHERE student_records.id=2255;
For the sum, you can use most of the same query:
SELECT
student_records.id,
SUM(courses.crd * grades.points) AS sum_grade_credits
FROM grades
INNER JOIN student_records ON grades.letter = student_records.grade
INNER JOIN courses ON courses.no = student_records.no
GROUP BY student_records.id
This would give you results for all students.
This is how you would do it in PHP:
$totalgrade = 0;
while($row = $query->fetch_array()) {
$totalgrade += $row['CRD']*$row['points'];
}
echo $totalgrade;

Need to fetch all products that have specific features with mysql

Hello I have a table in some cms (products) that has 3 columns:
product_id feature_id value
1 1 blue
1 8 cotton
2 5 t-shirt
2 1 red
3 8 wool
1 9 large
Each product has its own id, also each product has a list of features
(about 10 of them) each feature_id represent's a feature. Depending on
the feature_id the "value" column has the value for that type of feature.
E.x. imagine clothes, 1 unique product_id -> 1 cloth -> many features / properites like color type of material price size etc etc.
Question is it possible to fetch 3 rows something like
product_id value1 value2
1 blue large
2 red medium
3 green xsmall
4 purple xlarge
where value1 is the string on the value column when products 1 feature_id = 1 and
value2 is the string on the value column when products 1 feature_id = 9 (feature_id for size)
I cant figure out how to do this in one statement, without having to merge arrays in php.
Join will work:
http://dev.mysql.com/doc/refman/5.0/en/join.html
SELECT * FROM tbl_Products
JOIN tbl_Features ON tbl_Products.product_id = tbl_Features.product_id
WHERE tbl_Features.feature_id = ?
or
SELECT * FROM tbl_Products
JOIN tbl_Features ON tbl_Products.product_id = tbl_Features.product_id
WHERE tbl_Features.feature_id in (1, 2, 3, 4)
You can do it this way:
select p.product_id
(select value
from product_features pf
where pf.product_id = p.product_id
and pf.feature_id = 1) as feature_1
(select value
from product_features pf
where pf.product_id = p.product_id
and pf.feature_id = 9) as feature_9
from p.products
The query is standard SQL, so any compliant database should accept it.
I'm assuming you have a normal design with a products and product_features table
SELECT DISTINCT product_id AS book_id, (
SELECT value
FROM cscart_product_features_values
WHERE product_id = book_id
AND feature_id = '1'
) AS publisher, (
SELECT value
FROM cscart_product_features_values
WHERE product_id = book_id
AND feature_id = '8'
) AS author
FROM `cscart_product_features_values`
ORDER BY product_id
Well after some testing this works great :)

Result display problem in php and mysql

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

Categories