How to join with multiple tables in MySQL? - php

The image of the table relation can be found at image.
-- Table structure for table `area`
CREATE TABLE `area` (
`area_id` int(10) NOT NULL auto_increment,
`area_name` varchar(255) NOT NULL,
PRIMARY KEY (`area_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `area` (`area_id`, `area_name`) VALUES
(1, 'Area 1'),
(2, 'Area 2'),
(3, 'Area 3'),
(4, 'Area 4');
-- Table structure for table `fruits`
CREATE TABLE `fruits` (
`fruit_id` int(10) NOT NULL auto_increment,
`fruit_name` varchar(255) NOT NULL,
`area_id` int(10) NOT NULL,
PRIMARY KEY (`fruit_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
INSERT INTO `fruits` (`fruit_id`, `fruit_name`, `area_id`) VALUES
(1, 'Apple', 1),
(2, 'Orange', 1),
(3, 'Mango', 2),
(4, 'Apricot', 3);
-- Table structure for table `vegetables`
CREATE TABLE `vegetables` (
`veg_id` int(10) NOT NULL auto_increment,
`veg_name` varchar(255) NOT NULL,
`area_id` int(10) NOT NULL,
PRIMARY KEY (`veg_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;
INSERT INTO `vegetables` (`veg_id`, `veg_name`, `area_id`) VALUES
(1, 'Chickpea', 1),
(2, 'Drumstick', 4);
If I use the following query I get the output as below
SELECT
`area`.`area_name` AS AreaName
,COUNT(*) AS num
FROM
`area`
INNER JOIN `fruits`
ON (`fruits`.`area_id` = `area`.`area_id`)
GROUP BY `fruits`.area_id
UNION ALL
SELECT
`area`.`area_name` AS AreaName
,COUNT(*) AS num
FROM
`area`
INNER JOIN `vegetables`
ON (`vegetables` .`area_id` = `area`.`area_id`)
GROUP BY `vegetables`.area_id
AreaName num
Area 1 2
Area 2 1
Area 3 1
Area 1 1
Area 4 1
But I want the output to be like:
it should fetch all the areas which are present in vegetables and fruits and if the area is repeating in either fruits or vegetables it should return the total count of area_id by totalling the count of fruits and vegetables.. so the output will be like below
AreaName num
Area 1 3
Area 2 1
Area 3 1
Area 4 1

You can use a subselect over your query and use SUM() to add the counts for same area
SELECT t.AreaName ,SUM(t.num) num
FROM ( ....) t
GROUP BY t.AreaName
Fiddle Demo

Related

MySQL: How can I list sub categories and its items, limiting them to 3?

I would like to retrieve sub categories data and its items, limiting to 3 items per subcategory
sub category 1
item1
item2
item3
sub category 2
item1
item2
item3
sub category 3
item1
item2
item3
here is my table structure
CREATE TABLE `sub_categories` (
`id` INT(11) NOT NULL,
`category_id` INT(11) NULL DEFAULT NULL,
`title` VARCHAR(255) NULL DEFAULT NULL,
`slug` VARCHAR(255) NULL DEFAULT NULL,
`active_start` DATETIME NULL DEFAULT NULL,
`active_end` DATETIME NULL DEFAULT NULL,
`created` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)]]
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
joint table
CREATE TABLE `sub_category_items` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`item_id` INT(11) NOT NULL,
`sub_category_id` INT(11) NOT NULL,
`created` DATETIME NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=64;
CREATE TABLE `items` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`title` VARCHAR(255) NULL DEFAULT NULL,
`created` DATETIME NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=64;
here is my MySQL query
SELECT `Item`.`title`,`SubCategoryItem`.`id`, `SubCategoryItem`.`item_id`, `SubCategoryItem`.`sub_category_id`, `SubCategoryItem`.`created`, `SubCategory`.`id`, `SubCategory`.`category_id`, `SubCategory`.`title`, `SubCategory`.`active_start`, `SubCategory`.`active_end`, `SubCategory`.`created`
FROM `items` AS `Item`
left JOIN `sub_category_item` AS `SubCategoryItem` ON (`SubCategoryItem`.`item_id`=`Item`.`id`) right JOIN `sub_categories` AS `SubCategory` ON (`SubCategoryItem`.`sub_category_id`=`SubCategory`.`id`)
WHERE `SubCategory`.`category_id` = 21 ORDER BY CASE
WHEN MONTH(`SubCategory`.`active_start`) = MONTH(CURDATE()) THEN 0
WHEN MONTH(`SubCategory`.`active_end`) >= MONTH(CURDATE()) THEN 1
WHEN MONTH(`SubCategory`.`active_start`) <= MONTH(CURDATE()) THEN 2
ELSE 3
END , MONTH(`SubCategory`.`active_start`) desc
what am I doing wrong ?

How to verify if room is fully booked?

I am currently working on a booking system . I'm currently encountering a problem in finding out if an apartment is fully booked. In my database i have a table holding all the apartments and their details. I am trying to get the dates that all apartments for example with 4 bedrooms that are booked. I am running the following sql to return the booked dates of all 4 bedroom apartments.
SELECT *
FROM `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId )
JOIN booking AS b ON ( b.id = bookingId )
WHERE bedrooms = '4'
ORDER BY checkIn
The return of the sql is
id CheckIn checkOut userId
74 2014-04-15 2014-04-22 1
75 2014-04-15 2014-04-22 1
102 2014-06-03 2014-07-07 1
71 2014-06-16 2014-06-23 1
114 2014-07-19 2014-08-02 1
121 2014-07-20 2014-08-02 1
57 2014-07-22 2014-08-05 1
122 2014-07-28 2014-08-02 1
117 2014-08-03 2014-08-10 1
As i have 4 apartments in the system with four bedrooms i would like to get the dates that all four bedrooms are booked.
Example with the output got the dates 2014-07-28 till 2014-08-02 are fully booked as in that date range there are in total four bookings.
Database:
CREATE TABLE `apartment` (
`id` int(11) NOT NULL auto_increment,
`code` varchar(4) NOT NULL,
`bedrooms` int(11) NOT NULL,
`description` varchar(500) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=26 ;
--
-- Dumping data for table `apartment`
--
INSERT INTO `apartment` (`id`, `code`, `bedrooms`, `description`) VALUES
(1, '1c', 3, ''),
(4, '4d', 4, NULL),
(5, '5b', 2, NULL),
(10, '10c', 3, NULL),
(11, '11b', 2, NULL),
(12, '12d', 4, NULL),
(13, '13c', 3, NULL),
(14, '14a', 1, 'Yo'),
(15, '15b', 2, NULL),
(16, '16b', 2, NULL),
(17, '17d', 4, NULL),
(22, '22d', 4, NULL),
CREATE TABLE `apartment_booking` (
`id` int(11) NOT NULL auto_increment,
`apartmentId` int(11) NOT NULL,
`bookingId` int(11) NOT NULL,
`ref` varchar(50) NOT NULL,
`pax` int(11) NOT NULL default '1',
`remarks` varchar(500) default NULL,
`guestFullName` varchar(30) default NULL,
`guestCountry` varchar(2) default NULL,
`guestFlightDetails` varchar(200) default NULL,
PRIMARY KEY (`id`),
KEY `apartmentId` (`apartmentId`),
KEY `bookingId` (`bookingId`),
KEY `ref` (`ref`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=179 ;
--
-- Dumping data for table `apartment_booking`
--
INSERT INTO `apartment_booking` (`id`, `apartmentId`, `bookingId`, `ref`, `pax`, `remarks`, `guestFullName`, `guestCountry`, `guestFlightDetails`) VALUES
(164, 1, 140, 'Hotelbeds', 5, '', 'Andrew Robertson', 'MT', '')
(165, 21, 141, 'Hotelbeds', 6, '', 'Pipitone', 'MT', ''),
(166, 5, 142, 'maltaholidaylets', 2, '', 'holly turpin', 'MT', ''),
(167, 12, 143, 'direct003', 4, '', 'Bernard Walch', 'MT', ''),
(168, 17, 144, 'meetingpoint', 4, '', 'Edvin Modigh', 'MT', ''),
(169, 23, 145, 'direct', 3, '', 'Andrea bacchetti', 'MT', ''),
(172, 25, 148, 'direct', 5, '', 'Wimold Peters', 'MT', ''),
(173, 20, 149, '7228110687', 4, '', 'Ms. Benedetta Tombari', 'MT', ''),
(174, 23, 149, '7228110687 meetingpoint', 2, '', 'Ms. Milena Moretti', 'MT', ''),
(175, 25, 150, 'meetingpoint', 6, '', 'N Burdett', 'MT', ''),
(176, 8, 151, 'Hotelbeds', 2, '', 'tito titti', 'MT', ''),
(177, 1, 152, 'meetingpoint', 3, '', 'Stephen Mckenna', 'MT', ''),
(178, 16, 153, 'mhcs', 4, '', 'Wojclech Blaszak', 'MT', '');
-- --------------------------------------------------------
--
-- Table structure for table `booking`
--
CREATE TABLE `booking` (
`id` int(11) NOT NULL auto_increment,
`reference` varchar(20) NOT NULL,
`dateTime` datetime NOT NULL,
`checkIn` date NOT NULL,
`checkOut` date NOT NULL,
`userId` int(11) default NULL,
PRIMARY KEY (`id`),
KEY `agent` (`userId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=154 ;
--
-- Dumping data for table `booking`
--
INSERT INTO `booking` (`id`, `reference`, `dateTime`, `checkIn`, `checkOut`, `userId`) VALUES
(136, 'euroresort booking.b', '2014-07-02 09:30:08', '2014-08-04', '2014-08-11', 1),
(137, '7014505534', '2014-07-02 09:32:05', '2014-07-19', '2014-07-24', 1),
(138, 'BR4277518', '2014-07-02 09:45:02', '2014-08-09', '2014-08-16', 1),
(139, '100206154', '2014-07-02 10:11:45', '2014-07-27', '2014-08-03', 1),
(140, '120-135249-95', '2014-07-02 10:13:14', '2014-07-02', '2014-07-03', 1),
(141, '120-135181-94', '2014-07-02 10:14:31', '2014-08-10', '2014-08-17', 1),
(142, '000548MHL', '2014-07-02 12:38:54', '2014-08-25', '2014-09-01', 1),
(143, 'direct003', '2014-07-02 15:48:04', '2014-08-11', '2014-08-22', 1),
(144, 'SH3049361', '2014-07-02 15:52:18', '2014-08-05', '2014-08-14', 1),
(145, 'direct009', '2014-07-03 08:27:56', '2014-07-19', '2014-07-26', 1),
(148, 'direct010', '2014-07-04 08:12:13', '2014-07-08', '2014-07-22', 1),
(149, '7228110687', '2014-07-04 13:28:16', '2014-08-10', '2014-08-16', 1),
(150, '7308310623', '2014-07-07 08:39:04', '2014-08-11', '2014-08-20', 1),
(151, '120-135677-92', '2014-07-07 08:43:06', '2014-08-22', '2014-08-29', 1),
(152, '100209964', '2014-07-07 10:59:16', '2014-08-05', '2014-08-12', 1),
(153, 'mhcs', '2014-07-07 13:07:22', '2014-08-08', '2014-08-16', 1);
It gets a bit complicated.
The following query generates a range of numbers from 0 to 999, and adds each number as a number of days to the checkIn date for each booking, where the resulting date is less than or equal to the checkOut date for bookings for apartments with 4 rooms. This should give one row per apartment per day booked.
The number of booking ids for each date is then counted, and compared with the number of apartments with 4 bedrooms (from a sub query). The HAVING clause then discards all rows for dates where the number of aparments booked is not the same as the number of apartments with 4 rooms.
SELECT aBookedDate, sub2.apartment_cnt, COUNT(id) AS all_booking_cnt
FROM
(
SELECT booking.id, DATE_ADD(booking.checkIn, INTERVAL iCnt DAY) AS aBookedDate
FROM
(
SELECT units.i + tens.i * 10 + hundreds.i * 100 AS iCnt
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)units
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)tens
CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)hundreds
) sub0
CROSS JOIN booking
INNER JOIN apartment_booking ON booking.id = apartment_booking.bookingId
INNER JOIN apartment ON apartment.id = apartment_booking.apartmentId
WHERE DATE_ADD(booking.checkIn, INTERVAL iCnt DAY) <= booking.checkOut
AND apartment.bedrooms = 4
) sub1
CROSS JOIN
(
SELECT COUNT(*) AS apartment_cnt
FROM apartment
WHERE bedrooms = 4
) sub2
GROUP BY aBookedDate
HAVING all_booking_cnt = sub2.apartment_cnt
SQL fiddle for it:-
http://www.sqlfiddle.com/#!2/6edbe/5
You need left outer join, so you also show the apartments that are not booked.
SELECT *
FROM `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId )
JOIN booking AS b ON ( b.id = bookingId )
WHERE bedrooms = '4' and userId is null
ORDER BY checkIn
Ones that have null user id will be empty (aka non-booked), since there is no booking connected to that apartment. You didn't say enough about the structure so I take it you delete the bookings rather than keeping history. If you keep all historical entries you need to check the date with today's date instead.
SELECT *
FROM `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId )
LEFT OUTER JOIN booking AS b ON ( b.id = bookingId )
WHERE bedrooms = '4' and checkOut > NOW()
ORDER BY checkIn
EDIT:
It should look something like, I'll try to prepare a fiddle with that later:
SELECT
(COUNT(
SELECT *
FROM `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId )
LEFT OUTER JOIN booking AS b ON ( b.id = bookingId )
WHERE bedrooms = '4' and checkIn <= <<<SOMEDATEHERE>>> and checkOut >= <<<<SOMEOTHERDATEHERE>>>>>
) >= 4);

Calling SQL foreign key data with PHP

I need to get a better grasp on the process of manipulating and utilizing the SQL tables I need to make so I can continue figuring out exactly how I should make them and structure them to work.
If I have a table for shirts and another table for sizes and I use a foreign key on the shirts table to link to the sizes table to represent multiple options for that column. Do I only need to call on the shirts table in the PHP coding? If so how do I tell the PHP to gather whatever options are available for each row on the sizes table?
If in the table it has
vneck sizes,
scoop neck sizes
and I have it set where the vnecks only have s,m,l,1x and the scoop necks have xs,s,m,l,1x,2x,3x. How can I code the PHP to recognize the difference I have logically set in each row for that column?
It sounds like you actually need to have at least three tables, one for shirts, one for sizes , and one to relate shirts to sizes. There are any number of way you can use PHP to query the data, but most likely you would want to simply query using a JOIN to get data from all tables at the same time.
So perhaps something like this:
shirts table:
shirt_id (auto-incrementing primary key)
...other shirt-related fields
sizes table:
size_id (auto-incrementing primary key)
size_value (i.e. S, M, L)
...other size-related fields
shirt_sizes table:
shirt_id (foreign key to shirts table)
size_id (foreign key to sizes table)
(you have compound primary key across these two fields)
An you would query it like
SELECT * (or whatever fields you need)
FROM shirts
INNER JOIN shirt_sizes ON shirts.shirt_id = shirt_sizes.shirt_id
INNER JOIN size ON shirt_sizes.size_id = sizes.size_id
With the following table structure:
CREATE TABLE `shirt` (
`id` INTEGER NOT NULL,
`name` VARCHAR(32),
PRIMARY KEY( `id` )
);
CREATE TABLE `size` (
`id` INTEGER NOT NULL,
`name` VARCHAR(4),
PRIMARY KEY( `id` )
);
CREATE TABLE `shirt_size` (
`shirtId` INTEGER NOT NULL,
`sizeId` INTEGER NOT NULL,
PRIMARY KEY( `shirtId`, `sizeId` ),
FOREIGN KEY( `shirtId` ) REFERENCES `shirt`( `id` ),
FOREIGN KEY( `sizeId` ) REFERENCES `size`( `id` )
);
And this data:
INSERT INTO
`shirt` ( `id`, `name` )
VALUES
( 1, "vneck" ),
( 2, "scoop neck" );
INSERT INTO
`size` ( `id`, `name` )
VALUES
( 1, "xs" ), ( 2, "s" ), ( 3, "m" ),
( 4, "l" ), ( 5, "1x" ), ( 6, "2x" ), ( 7, "3x" );
INSERT INTO
`shirt_size` ( `shirtId`, `sizeId` )
VALUES
( 1, 2 ), ( 1, 3 ), ( 1, 4 ), ( 1, 5 ),
( 2, 1 ), ( 2, 2 ), ( 2, 3 ), ( 2, 4 ), ( 2, 5 ), ( 2, 6 ), ( 2, 7 );
In MySQL you could do:
SELECT
`shirt`.`id`,
`shirt`.`name`,
GROUP_CONCAT( `size`.`name` ) as `sizes`
FROM
`shirt`
JOIN
`shirt_size`
ON `shirt_size`.`shirtId` = `shirt`.`id`
JOIN
`size`
ON `size`.`id` = `shirt_size`.`sizeId`
GROUP BY `shirt`.`id`;
Which would result in something like:
+----+------------+-------------------+
| id | name | sizes |
+----+------------+-------------------+
| 1 | vneck | s,m,l,1x |
+----+------------+-------------------+
| 2 | snoop neck | xs,s,m,l,1x,2x,3x |
+----+------------+-------------------+
Not sure if other RDBMS's have aggregate functions similar to MySQL's GROUP_CONCAT(). If not, then use something like:
SELECT
`shirt`.`id`,
`shirt`.`name` as `shirtName`,
`size`.`name` as `sizeName`
FROM
`shirt`
JOIN
`shirt_size`
ON `shirt_size`.`shirtId` = `shirt`.`id`
JOIN
`size`
ON `size`.`id` = `shirt_size`.`sizeId`;
Which will give you multiple rows for every size, with each shirt.

mysql left join takes too long

I have the following SQL Query:
SELECT
upd.*,
usr.username AS `username`,
usr.profile_picture AS `profile_picture`
FROM
updates AS upd
LEFT JOIN
subscribers AS sub ON upd.uid=sub.suid
LEFT JOIN
users AS usr ON upd.uid=usr.uid
WHERE
upd.deleted='0' && (upd.uid='118697835834' || sub.uid='118697835834')
GROUP BY upd.id
ORDER BY upd.date DESC
LIMIT 0, 15
where i get all user(118697835834) updates, his profile picture from another table using left join and also all his subscription users updates so can i show them in his newsfeed.
However as the updates get more and more so the query takes more time to load... right now using Codeigniter's Profiler i can see that the query takes 1.3793...
Right now i have created around 18k dummy accounts and subscribed from to me and vice versa so i can test the execution time... the times that i get are tragic considering that i am in localhost...
I also have some indexes where i suppose need more in the users table(username and uid as unique), updates table(update_id as unique and uid as index)
I suppose i am doing something wrong to get so bad results...
EDIT:
Running EXPLAIN EXTENDED result:
Array
(
[0] => stdClass Object
(
[id] => 1
[select_type] => SIMPLE
[table] => upd
[type] => ALL
[possible_keys] => i2
[key] =>
[key_len] =>
[ref] =>
[rows] => 22
[filtered] => 100.00
[Extra] => Using where; Using temporary; Using filesort
)
[1] => stdClass Object
(
[id] => 1
[select_type] => SIMPLE
[table] => sub
[type] => ALL
[possible_keys] =>
[key] =>
[key_len] =>
[ref] =>
[rows] => 18244
[filtered] => 100.00
[Extra] => Using where
)
[2] => stdClass Object
(
[id] => 1
[select_type] => SIMPLE
[table] => usr
[type] => eq_ref
[possible_keys] => uid
[key] => uid
[key_len] => 8
[ref] => site.upd.uid
[rows] => 1
[filtered] => 100.00
[Extra] =>
)
)
EDIT2: SHOW CREATE of Tables
Users table:
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uid` bigint(20) NOT NULL,
`username` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
`email` text CHARACTER SET latin1 NOT NULL,
`password` text CHARACTER SET latin1 NOT NULL,
`profile_picture_full` text COLLATE utf8_unicode_ci NOT NULL,
`profile_picture` text COLLATE utf8_unicode_ci NOT NULL,
`date_registered` datetime NOT NULL,
`activated` tinyint(1) NOT NULL,
`closed` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid` (`uid`),
UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=23521 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Subscribers table:
CREATE TABLE `subscribers` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`sid` bigint(20) NOT NULL,
`uid` bigint(20) NOT NULL,
`suid` bigint(20) NOT NULL,
`date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=18255 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Updates table:
CREATE TABLE `updates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`update_id` bigint(19) NOT NULL,
`uid` bigint(20) NOT NULL,
`type` text COLLATE utf8_unicode_ci NOT NULL,
`update` text COLLATE utf8_unicode_ci NOT NULL,
`date` datetime NOT NULL,
`total_likes` int(11) NOT NULL,
`total_comments` int(11) NOT NULL,
`total_favorites` int(11) NOT NULL,
`category` bigint(20) NOT NULL,
`deleted` tinyint(1) NOT NULL,
`deleted_date` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i1` (`update_id`),
KEY `i2` (`uid`),
KEY `deleted_index` (`deleted`)
) ENGINE=MyISAM AUTO_INCREMENT=23 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Try this one (without the GROUP BY):
SELECT
upd.*,
usr.username AS `username`,
usr.profile_picture AS `profile_picture`
FROM
updates AS upd
LEFT JOIN
users AS usr
ON upd.uid = usr.uid
WHERE
upd.deleted='0'
AND
( upd.uid='118697835834'
OR EXISTS
( SELECT *
FROM subscribers AS sub
WHERE upd.uid = sub.suid
AND sub.uid = '118697835834'
)
)
ORDER BY upd.date DESC
LIMIT 0, 15
At least the columns that are used in Joins should be indexed: updates.uid, users.uid and subscribers.suid.
I would also add an index on subscribers.uid.
Try:
SELECT
upd.*,
usr.username AS `username`,
usr.profile_picture AS `profile_picture`
FROM
updates AS upd
LEFT JOIN
subscribers AS sub ON upd.uid=sub.suid
LEFT JOIN
users AS usr ON upd.uid=usr.uid
WHERE
upd.deleted=0 and upd.uid in (118697835834,118697835834)
GROUP BY upd.id
ORDER BY upd.date DESC
LIMIT 0, 15
Note that ' has been removed from numeric values and bitwise operators changed to conventional operators.
don't use joins, try this one:
select *,
(select username from users where uid = upd.uid) as username,
(select profile_picture from users where uid = upd.uid) as profile_picture,
from updates as upd
WHERE
upd.deleted='0' && upd.uid='118697835834'
(not tested!)
maybe you have to check if there exists a subscriber in the where-clause with another sub-select.
Another way would be to make a join on sub-selects and not on the whole table. This may increase your performance also.
Shouldn't take too long to run; do you have an index on 'deleted'? What is the 'GROUP BY id' doing? Should it be UID? Can it come out, if ID is in fact just an auto increment, unique ID? (which would be expensive as well as pointless)
I think you'll be best separating this query into a select on the user table and then union those results with the select on the subscribers table.

How to merge two tables MySQL-PHP with date sorting

I want to merge the results of two tables in to one.
Please refer the following tables :
Data from microblog table as Row array
Array ( [ID] => 46 [userID] => 1 [userNAME] => user [blog_content] => HAI DEAR [page_name] => honda [page_ID] => 31 [post_time] => 2011-10-18 11:06:54 )
Data from Page_review table as Row array
Array ( [page_review_id] => 5 [page_id] => 31 [page_review_by_id] => 31 [page_review_by_username] => user [page_review_time] => 2011-10-18 11:43:34 [page_review_content] => hai )
Table Microblog MySQL query:
DROP TABLE IF EXISTS `featurezme_store`.`microblog`;
CREATE TABLE `featurezme_store`.`microblog` (
`ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`userID` int(10) unsigned NOT NULL,
`userNAME` varchar(45) NOT NULL,
`blog_content` text NOT NULL,
`page_name` varchar(45) NOT NULL,
`page_ID` int(10) unsigned NOT NULL,
`post_time` datetime NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=latin1;
Table page_review
DROP TABLE IF EXISTS `featurezme_store`.`page_review`;
CREATE TABLE `featurezme_store`.`page_review` (
`page_review_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`page_id` int(10) unsigned NOT NULL,
`page_review_by_id` int(10) unsigned NOT NULL,
`page_review_by_username` varchar(145) NOT NULL,
`page_review_time` datetime NOT NULL,
`page_review_content` varchar(555) NOT NULL,
PRIMARY KEY (`page_review_id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
the table Microblog is used to store blog posts & page_review is used to store reviews about pages[Microblog's are in pages].
My requirement is i want to show Blogposts & page reviews sorted by Date [post_time in Microblog & page_review_time on page_review].
how can i do this ? please help me.
Okay I have updated my answear, you can use union as you wanted.
Just have the same number of fields and because the results are placed the one unde the other use fields that make sense to be the one under the other. This example will bring all blogs and reviews created by a specific user (if page_review_by_id actually refers to the user id) and related to a specific page.
(
SELECT
`microblog`.`userID`,
`microblog`.`blog_content` as `blog or review`,
`microblog`.`post_time`,
`microblog`.`page_id`
from `microblog`
where `microblog`.`page_id`='1' and `microblog`.`userID`='1'
)
union
(
SELECT
`page_review`.`page_review_by_id`,
`page_review`.`page_review_content`,
`page_review`.`page_review_time`,
`page_review`.`page_id`
from `page_review`
where `page_review`.`page_id`='1' and `page_review`.`page_review_by_id`='1'
)
======== Edit== Suggesting a schema with foreign keys ================
Because I don't see any foreign keys in your schema if I could suggest optionaly a schema that applies foreign keys I present one below.
These rules are supported by this schema:
Blogs belong to the site and not to the user so there is not on delete cascade applied.
Blogs are created by users and a foreign key is applied so when a user id is inserted the consistency is assured through the foreign key.
The same goes for the page, a foreign key is applid without on delte cascade.
The same goes for the reviews table
If a user or page is deleted no child row is deleted
/********Create ***** ***/
CREATE TABLE user (
user_id int unsigned NOT NULL AUTO_INCREMENT,
username varchar(16) NOT NULL,
userpassword BLOB,
PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE page (
page_id mediumint unsigned NOT NULL AUTO_INCREMENT,
title varchar(55) NOT NULL,
PRIMARY KEY (page_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE microblog (
blog_id int unsigned NOT NULL AUTO_INCREMENT,
blog_content text NOT NULL,
date_created datetime NOT NULL,
author_id int unsigned NOT NULL,
page_id mediumint unsigned NOT NULL,
PRIMARY KEY (blog_id),
CONSTRAINT blogfk1 FOREIGN KEY (author_id)
REFERENCES user (user_id),
/NO ON DELETE CASCADE/
CONSTRAINT blogfk2 FOREIGN KEY (page_id)
REFERENCES page (page_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE page_review (
review_id int unsigned NOT NULL AUTO_INCREMENT,
review_content varchar(555) NOT NULL,
date_created datetime NOT NULL,
author_id int unsigned NOT NULL,
page_id mediumint unsigned NOT NULL,
PRIMARY KEY (review_id),
CONSTRAINT reviewfk1 FOREIGN KEY (author_id)
REFERENCES user (user_id),
/NO ON DELETE CASCADE/
CONSTRAINT reviewfk2 FOREIGN KEY (page_id)
REFERENCES page (page_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/************** ******/
/** ***Insertions*** **/
INSERT INTO user ( username,userpassword)
VALUES ('username11', AES_ENCRYPT('password1',
'encription_key') ),
('username22', AES_ENCRYPT('password2',
'encription_key') );
INSERT INTO page ( title) VALUES
('title1'),('title2');
INSERT INTO microblog (blog_content,date_created,
author_id,page_id) VALUES
('blogcontent1','2011-2-2 12:00','1','1'),
('blogcontent2','2011-2-2 12:00','2','2');
INSERT INTO page_review (review_content,
date_created,author_id,page_id) VALUES
('reviewcontent1','2011-2-2 12:00','1','1'),
('reviewcontent2','2011-2-2 12:00','2','2');
/***** *******/
/******* Queries *** /
/Help on Identifing a user/
SELECT username
FROM user WHERE username ='username22'
and userpassword=AES_ENCRYPT('password2','encription_key')
(
SELECT
microblog.blog_content as blog or content,
microblog.date_created,
microblog.author_id,
microblog.page_id
from microblog
where microblog.author_id='1' and microblog.page_id='1'
)
union
(
SELECT
page_review.review_content,
page_review.date_created,
page_review.author_id,
page_review.page_id
from page_review
where page_review.author_id='1' and page_review.page_id='1'
)

Categories