how to join four table in msql? - php

create table area (
area_id int(11) not null auto_increment,
area_name varchar(60) not null,
primary key (area_id)
);
create table mainCategory(
mc_id int(11) not null auto_increment,
mc_name varchar(60) not null,
area_id int(11) not null,
primary key(mc_id),
foreign key(area_id) references area(area_id)
);
create table subCategory(
sc_id int(11) not null auto_increment,
sc_name varchar(60) not null,
mc_id int(11) not null,
area_id int(11) not null,
primary key(sc_id),
foreign key(mc_id) references mc(mc_id),
foreign key(area_id) references area(area_id)
);
create table shopes(
s_id int(11) not null auto_increment,
s_name varchar(60) not null,
s_address varchar(120) not null,
s_work varchar(255) not null,
s_imagepath varchar(255) not null,
s_image varchar(255) not null,
area_id int(11) not null,
mc_id int(11) not null,
sc_id int(11) not null,
primary key(s_id),
foreign key(area_id) references area(area_id),
foreign key(mc_id) references mc(mc_id),
foreign key(sc_id) references sc(sc_id)
);
I want to select data from four table with mysql join. I am using
select s_name,s_address,s_work,s_image,area_name,mc_name from shopes inner join area on area.area_id=shopes.area_id inner join mainCategory on mc.area_id=area.area_id;
It is a three table join and it is not giving appropriate result. It is giving repeated result.

Try this:
select s.s_name, s.s_address, s.s_work, s.s_image, a.area_name, mc.mc_name from shope as s LEFT JOIN area as a on a.area_id=s.area_id LEFT JOIN mainCategory as mc on mc.area_id=a.area_id LEFT JOIN subCategory as sc on sc.area_id=a.area_id
I have used LEFT JOIN keyword instead of inner join, it's returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.

Use this syntax.
select a.coumn1,
a.coumn2,
b.coumn1,
c.coulumn1,
d.column1,
d.column2
from table1 a
left outer join table2 b
on a.id=b.id
left outer join table3 c
on b.id=c.id
left outer join table4 d
on a.id=d.id
where a.name = 'abc'

select s_name, s_address, s_work, s_image, area_name, mc_name
from shopes, area, mainCategory
where shopes.area_id = area.area_id
and shopes.mc_id = mainCategory.mc_id;
If still got duplicate data, use:
select distinct s_name, ...

Try it.
select shopes.s_name,s_address,s_work,s_image, area.area_name, maincategory.mc_name from shopes join area on shopes.area_id=area.area_id
join maincategory on shopes.mc_id=maincategory.mc_id;

select s_name,s_address,s_work,s_image,area_name,mc_name
from area
inner join area
on area.area_id=shopes.area_id
inner join mainCategory
on mc.area_id=area.area_id;

Related

How do I only select recipes that I have the ingredients for?

I'm executing the following statement:
SELECT DISTINCT
r.Recipe_Name
FROM
USER u
INNER JOIN
UserIngredient ui
ON
u.User_ID = ui.User_ID
INNER JOIN
RecipeIngredient ri
ON
ui.Ingredient_ID = ri.Ingredient_ID
INNER JOIN
Ingredient i
ON
ri.Ingredient_ID = i.Ingredient_ID
INNER JOIN
Recipe r
ON
ri.Recipe_ID = r.Recipe_ID
WHERE
u.User_Session = SessionID
and get every recipe that I have at least one ingredient for and not just the recipes that I have ALL ingredients for. My table-layout is the following:
CREATE TABLE User
(
User_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
User_Pass TEXT NOT NULL,
User_Name TEXT NOT NULL,
User_Surname TEXT NOT NULL,
User_EMail VARCHAR(255) UNIQUE,
User_Session VARCHAR(50) UNIQUE,
User_Admin BOOLEAN,
User_Newsletter BOOLEAN
);
CREATE TABLE Recipe
(
Recipe_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Recipe_Name VARCHAR(255) UNIQUE NOT NULL,
Recipe_Clicks INT,
Recipe_Description TEXT,
Recipe_Image VARCHAR(255) DEFAULT 'https://placehold.it/400x500'
);
CREATE TABLE Ingredient
(
Ingredient_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Ingredient_Name VARCHAR(255) UNIQUE,
Ingredient_Description TEXT
);
CREATE TABLE RecipeIngredient
(
RecipeIngredient_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
RecipeIngredient_Amount DECIMAL(8,2) NOT NULL,
MeasuringUnit_ID INT NOT NULL,
Recipe_ID INT NOT NULL,
Ingredient_ID INT NOT NULL,
FOREIGN KEY (MeasuringUnit_ID) REFERENCES MeasuringUnit(MeasuringUnit_ID),
FOREIGN KEY (Recipe_ID) REFERENCES Recipe(Recipe_ID),
FOREIGN KEY (Ingredient_ID) REFERENCES Ingredient(Ingredient_ID)
);
CREATE TABLE UserIngredient
(
UserIngredient_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
Ingredient_ID INT NOT NULL,
User_ID INT NOT NULL,
FOREIGN KEY(Ingredient_ID) REFERENCES Ingredient(Ingredient_ID),
FOREIGN KEY(User_ID) REFERENCES User(User_ID)
);
The result I get:
I get every recipe that I have one ingredient
The result I want:
All recipes that I have ALL ingredients.
Here is my SQL file
Try this:
SELECT DISTINCT r.Recipe_Name
FROM Recipe r
CROSS JOIN User u
WHERE
(SELECT COUNT(*)
FROM RecipeIngredients ri
LEFT OUTER JOIN UserIngredient ui
ON ri.Recipe_ID = ui.Recipe_ID
AND ri.Ingredient_ID = ui.Ingredient_ID
AND ui.User_ID = u.User_ID
WHERE ui.UserIngredient_ID IS NULL) = 0

inner join slow performance

I have a table offers that has over 100k rows so the below query is very slow (4sec - average).
SELECT cat1.id AS cat1id,
cat1.title_gr AS title,
cat1.order
FROM categories_groups_cat1 AS cat1
INNER JOIN
( SELECT categories_id, categories_groups_cat1_id FROM
categories_vs_groups
GROUP BY categories_groups_cat1_id ) AS vs
ON vs.categories_groups_cat1_id=cat1.id
INNER JOIN
( SELECT id, title_gr FROM
categories
GROUP BY title_gr ) AS cats
ON cats.id=vs.categories_id
INNER JOIN
( SELECT category_gr FROM
offers
GROUP BY category_gr ) AS offers
ON offers.category_gr=cats.title_gr
GROUP BY cat1.id
ORDER BY cat1.order ASC
table offers
`id` int(11) NOT NULL,
`title` text NOT NULL,
`description` text NOT NULL,
`image` text NOT NULL,
`price` float NOT NULL,
`start_price` float NOT NULL,
`brand` text NOT NULL
`category_gr` text NOT NULL
table categories_groups_cat1
`id` int(11) NOT NULL,
`order` int(11) NOT NULL,
`title_gr` text NOT NULL
table categories_vs_groups
`id` int(11) NOT NULL,
`categories_groups_cat1_id` int(11) NOT NULL,
`categories_id` int(11) NOT NULL
table categories
`id` int(11) NOT NULL,
`title_gr` char(255) NOT NULL
I try to choose from categories_groups_cat1 where offers exist, that's why I use the inner join. I don't know if it is completely correct. If there is another faster(performance) solution I would appreciate it
You should avoid sub-query that creates temp table. This will surely improve performance. Sub-queries that create temp table in memory kills performance, try to avoid as much as you can.
I have modified your code. There may small syntactic errors.
SELECT cat1.id AS cat1id,
cat1.title_gr AS title,
cat1.order
FROM categories_groups_cat1 AS cat1
INNER JOIN
categories_groups_cat1_id AS vs
ON vs.categories_groups_cat1_id=cat1.id
INNER JOIN
categories
AS cats
ON cats.id=vs.categories_id
INNER JOIN
offers
ON offers.category_gr=cats.title_gr
GROUP BY cat1.id,cats.title_gr, offers.category_gr
ORDER BY cat1.order ASC

Mysql product filters with multiple options

for example I have a list o TVs, and each TV has some attributes like: Brand(Samsung,Sony etc..), Size(80cm, 116 cm etc), SmartTv(yes, no).
I have the following schema:
CREATE TABLE `products` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(150) NOT NULL,
)
CREATE TABLE `attributes` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(20) character set latin1 NOT NULL
)
CREATE TABLE `attributes_entity` (
`product_id` int(11) NOT NULL,
`attribute_id` int(11) NOT NULL,
`value_id` int(11) NOT NULL,
)
CREATE TABLE `attributes_values` (
`id` int(11) NOT NULL auto_increment,
`value` varchar(255) default NULL,
)
If i want all TV from samsung i say like this:
SELECT
`p`.`id`,
`p`.`name`
FROM `attributes_entity` `ae`
INNER JOIN `products` `p` ON `ae`.`product_id`=`p`.`id`
INNER JOIN `attributes` `a` ON `ae`.`attribute_id`=`a`.`id`
INNER JOIN `attributes_values` `av` ON `ae`.`value_id`=`av`.`id`
WHERE (`a`.`name`='samsung' AND `av`.`value`='samsung')
This is great but what if I want: All Samsung TVs that are smartTv:
SELECT
`p`.`id`,
`p`.`name`
FROM `attributes_entity` `ae`
INNER JOIN `products` `p` ON `ae`.`product_id`=`p`.`id`
INNER JOIN `attributes` `a` ON `ae`.`attribute_id`=`a`.`id`
INNER JOIN `attributes_values` `av` ON `ae`.`value_id`=`av`.`id`
WHERE (`a`.`name`='samsung' AND `av`.`value`='samsung')
//imposible query
and (`a`.`name`='smartv' AND `av`.`value`='yes')
How should i fix the query with multiple ANDs?
First idea, off the top of my head - try replacing your joins with an inner query, and count the number of matching attributes:
SELECT `p`.`id`, `p`.`name`
FROM `products` `p`
WHERE `p`.`id` IN (SELECT `ae`.`product_id`
FROM `attributes_entity` `ae`
INNER JOIN `attributes` `a` ON `ae`.`attribute_id`=`a`.`id`
INNER JOIN `attributes_values` `av` ON `ae`.`value_id`=`av`.`id`
WHERE ((`a`.`name`='samsung' AND `av`.`value`='samsung') OR
(`a`.`name`='smartv' AND `av`.`value`='yes'))
HAVING COUNT(*) >= 2 -- number of matching attributes required
);

How do I select MySQL records based on results from a related table?

I have two tables in this scenario: members and team_members. The members table is pretty self explanatory. The team members table stores the member's team information if they are a member of the team. If there is no row in the team members table that has a member_id of a user, then they are not in a team. What I want to do is get all the users that are not members of a team. Should I use left join, inner join, outer join, or just join? What would this query look like?
CREATE TABLE IF NOT EXISTS `members` (
`member_id` int(15) NOT NULL AUTO_INCREMENT,
`group_id` int(15) NOT NULL,
`display_name` text NOT NULL,
`email_address` text NOT NULL,
`password` text NOT NULL,
`status` tinyint(1) NOT NULL,
`activation_code` varchar(16) NOT NULL,
`date_joined` text NOT NULL,
PRIMARY KEY (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `team_members` (
`team_member_id` int(15) NOT NULL AUTO_INCREMENT,
`member_id` int(15) NOT NULL,
`team_id` int(15) NOT NULL,
`date_joined` text NOT NULL,
`date_left` text NOT NULL,
`total_xp` int(15) NOT NULL,
PRIMARY KEY (`team_member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
There's several ways to write this query.
To me this is the easiest to read and understand:
select * from members where member_id not in (select member_id from team_members).
This is a really simple way to write it. If you decide you want everything you can quickly comment out the where clause:
select m.* from members m left outer join team_members tm on m.member_id = tm.member_id
where tm.member_id is null
This way doesn't seem very popular from the SQL I read but I think it's straightforward:
select m.* from members m where not exists
(select member_id from team_members tm where tm.member_id = m.member_id)
On the face of it, the below query is fine
SELECT members.member_id
FROM members
LEFT OUTER JOIN team_members
ON team_members.member_id = members.member_id
WHERE team_members.member_id IS NULL
This will do, but on reading your question again, you seem to have a date_left column and if you want only those members who have not yet left a team then
SELECT members.member_id
FROM members
LEFT OUTER JOIN (SELECT *
FROM team_members
WHERE team_members.date_left != '') CURRENT_TEAMS
ON CURRENT_TEAMS.member_id = members.member_id
WHERE CURRENT_TEAMS.member_id IS NULL
SQLFiddle example
http://www.sqlfiddle.com/#!2/46b25/6/0

how do I output the rowName based on a linking table?

I need to output A_Name, B_Name, and C_Name. from tableA, tableB, tableC. I have a linking table containing all the ID's of the above, e.g:
CREATE TABLE `tableLink` (
`tableLinkID` int(5) NOT NULL auto_increment,
`A_ID` int(11) NOT NULL,
`B_ID` int(5) NOT NULL,
`C_ID` int(5) NOT NULL,
PRIMARY KEY (`tableLinkID`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 AUTO_INCREMENT=17 ;
My question: I need to know how to SELECT based on having C_ID, how to select and output A_ID's [A_Name], B_ID's [B_Name], and C_ID's [C_Name].
I hope this is clear enough.
(I have the C_ID in a variable)
Try using JOINs:
SELECT
tableA.A_Name,
tableB.B_Name,
tableC.C_Name
FROM tableLink
JOIN tableA ON tableLink.A_ID = A.ID
JOIN tableB ON tableLink.B_ID = B.ID
JOIN tableC ON tableLink.C_ID = C.ID
WHERE tableLink.C_ID = 42

Categories