PHP/MYSQL - Which Join Statement To Use To Simplify My Queries? - php

I have these 2 queries and i would like to join them into one but i am unsure of how to go about it.
Query 1:
$query = "SELECT * FROM ".$db_tbl_comics." WHERE ".$db_fld_comics_publisher."='".$pub_id."'
AND ".$db_fld_comics_active."='1' GROUP BY ".$db_fld_comics_arc;
Query 2:
$q2 = mysql_query('SELECT '.$db_fld_arcs_title.' FROM '.$db_tbl_arcs.'
WHERE '.$db_fld_arcs_id.'="'.$result[$db_fld_comics_arc].'"');
Comics Table:
CREATE TABLE IF NOT EXISTS `comics` (
`id` varchar(255) NOT NULL,
`arc` int(255) NOT NULL,
`title` varchar(255) NOT NULL,
`issue` decimal(5,1) DEFAULT NULL,
`price` decimal(10,2) NOT NULL,
`plot` longtext NOT NULL,
`publisher` int(255) NOT NULL,
`isbn` varchar(255) NOT NULL,
`published` date NOT NULL,
`cover` varchar(255) NOT NULL DEFAULT './images/nopic.jpg',
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`views` int(255) NOT NULL DEFAULT '0',
`active` int(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `arc` (`arc`,`title`,`issue`,`publisher`)
);
Arcs Table:
CREATE TABLE IF NOT EXISTS `arcs` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`plot` longtext NOT NULL,
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `title` (`title`)
);
What I need to do is get the Arcs Title from the arcs table for the respective comic arc.

You need to use INNER JOIN for that since I presume that records are present on both tables.
SELECT a.*, b.title
FROM comics a INNER JOIN arcs b
on a.id = b.id
WHERE a.Title = 'VALUEHERE'
displays all details from comics table and the title of the arc

as simple as (joining 2 queries in one, by selecting only the required field and using IN):
SELECT
'.$db_fld_arcs_title.'
FROM '.$db_tbl_arcs.'
WHERE '.$db_fld_arcs_id.' IN (
SELECT '.$db_fld_comics_arc.'
FROM '.$db_tbl_comics.'
WHERE '.$db_fld_comics_publisher.'='".$pub_id."'
AND '.$db_fld_comics_active.'='1' GROUP BY '.$db_fld_comics_arc.'
)

Related

inner join query selecting from database where lang is en

Hello i have one query with inner join that take a question and 4 answers from the db. I want to make this query to take only the questions that lang table is 'en'
This is the query:
$mysql->query("SELECT Q.id AS id, Q.question, QA.answer1, QA.answer2,
QA.answer3, QA.answer4, QA.correct, QC.name AS cat_name
FROM question Q
INNER JOIN question_answers QA ON QA.questionFK=Q.id
INNER JOIN question_cats QC ON QC.id=Q.categoryFK
ORDER BY rand()
LIMIT 1");
I try to make it like this:
$mysql->query("SELECT Q.id AS id, Q.question, QA.answer1, QA.answer2,
QA.answer3, QA.answer4, QA.correct, QC.name AS cat_name
FROM question Q
INNER JOIN question_answers QA ON QA.questionFK=Q.id
INNER JOIN question_cats QC ON QC.id=Q.categoryFK
WHERE Q.lang='en'
ORDER BY rand()
LIMIT 1");
But it didn't work, it's select everyting...
Where am i wrong and how should i make it?
Those are the 2 tables:
CREATE TABLE IF NOT EXISTS `question` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`question` varchar(255) NOT NULL,
`cnt` int(10) NOT NULL DEFAULT '0',
`correct` int(10) NOT NULL DEFAULT '0',
`categoryFK` int(3) NOT NULL DEFAULT '0',
`from_userFK` int(10) NOT NULL DEFAULT '0',
`correct_points` int(10) DEFAULT NULL,
`ut` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del` enum('yes','no') NOT NULL DEFAULT 'no',
`lang` varchar(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=26 ;
CREATE TABLE IF NOT EXISTS `question_answers` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`questionFK` int(10) NOT NULL,
`answer1` varchar(255) CHARACTER SET cp1251 NOT NULL,
`answer2` varchar(255) CHARACTER SET cp1251 NOT NULL,
`answer3` varchar(255) CHARACTER SET cp1251 NOT NULL,
`answer4` varchar(255) CHARACTER SET cp1251 NOT NULL,
`correct` int(1) NOT NULL,
`ut` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del` enum('yes','no') CHARACTER SET cp1251 NOT NULL DEFAULT 'no',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=25 ;
To me it feels like your filer condition WHERE Q.lang='en' doesn't matches any record and so the outcome. Consider trimming it before comparing like
WHERE TRIM(Q.lang) ='en'

SQL query to find the author of a specific blog post?

Hi i'm trying to pull the first_name of the user who was the author for a certain blog post from my database but having a bit of a problem. I'm really getting confused on how to join the two tables together and can't really find a simple explanation. Here are my two tables:
CREATE TABLE IF NOT EXISTS `goldhub_user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(20) NOT NULL,
`username` varchar(50) NOT NULL,
`password` char(40) NOT NULL,
`first_name` varchar(20) NOT NULL,
`last_name` varchar(20) NOT NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `goldhub_email` (`email`)
)
CREATE TABLE IF NOT EXISTS `goldhub_post` (
`post_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`category_id` int(11) DEFAULT NULL,
`post_content` varchar(255) DEFAULT NULL,
`post_date` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`post_id`),
KEY `user_id` (`user_id`),
KEY `category_id` (`category_id`)
)
Any guidance would be much appreciated.
SELECT goldhub_user.first_name FROM goldhub_post
INNER JOIN goldhub_user ON goldhub_user.user_id = goldhub_post.user_id
WHERE goldhub_post.post_id = ?
Replace the ? with the ID of the post.
Try something like this, it would help me if you post the condition to get the author based on post
SELECT gu.first_name FROM goldhub_user gu
LEFT JOIN goldhub_post gp
ON gu.user_id = gp.user_id
WHERE gp.post_id = ?
AND gp.category_id = ?;

i want to use left and inner join in 3 tables in mysql?

these are my tables. first one is appusers table.
CREATE TABLE IF NOT EXISTS `appusers` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(50) NOT NULL,
`is_active` tinyint(2) NOT NULL DEFAULT '0',
`zip` varchar(20) NOT NULL,
`city` text NOT NULL,
`country` text NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ;
second table is stickeruses table.
CREATE TABLE IF NOT EXISTS `stickeruses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`sticker_id` int(11) NOT NULL,
`count` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;
Third table is Devices
CREATE TABLE IF NOT EXISTS `devices` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`regid` varchar(300) NOT NULL,
`imei` varchar(50) NOT NULL,
`device_type` tinyint(2) NOT NULL,
`notification` tinyint(2) NOT NULL DEFAULT '1',
`is_active` tinyint(2) NOT NULL DEFAULT '0',
`activationcode` int(6) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=28 ;
I Want to find the Sum(stickeruses.count) and COUNT(devices.id) for all appusers.
Here is my query.
SELECT `Appuser`.`id`, `Appuser`.`email`, `Appuser`.`country`, `Appuser`.`created`,
`Appuser`.`is_active`, SUM(`Stickeruse`.`count`) AS total, COUNT(`Device`.`id`)
AS tdevice
FROM `stickerapp`.`appusers` AS `Appuser`
LEFT JOIN `stickerapp`.`stickeruses` AS `Stickeruse`
ON (`Stickeruse`.`user_id`=`Appuser`.`id`)
INNER JOIN `stickerapp`.`devices` AS `Device`
ON (`Device`.`user_id`=`Appuser`.`id`)
WHERE `Appuser`.`is_active` = 1
GROUP BY `Appuser`.`id`
LIMIT 10
When I am applying each join separately the results are right, but I want to combine both joins. And when I am doing it then results are wrong. please help.
When mixing JOIN and LEFT JOIN it is a good idea to use parentheses to make it clear what your intent is.
I don't know what you need, but these syntaxes might give you different results:
FROM a LEFT JOIN ( b JOIN c ON b..c.. ) bc ON a..bc..
FROM ( a LEFT JOIN b ON a..b.. ) ab JOIN c ON ab..c..
Also, you can rearrange them do FROM a JOIN c LEFT JOIN b (plus parentheses) or any of several other arrangements. Granted, some pairs rearrangements are equivalent.
Also, beware; aggregates (such as SUM()) get inflated values when JOINing. Think of it this way: first the JOINs get all appropriate combinations of rows from the tables, then the SUM adds them up. With that in mind, see if this works better:
SELECT a.`id`, a.`email`, a.`country`, a.`created`, a.`is_active`,
( SELECT SUM(`count`)
FROM stickerapp.stickeruses
WHERE user_id = a.id
) AS total,
( SELECT COUNT(*)
FROM stickerapp.devices
WHERE user_id = a.id
) AS tdevice
FROM stickerapp.`appusers` AS a
WHERE a.`is_active` = 1
GROUP BY a.`id`
LIMIT 10

Improve speed of MySQL query [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
EDIT:
I reworked the query as follows:
SELECT
a.title, count(*),at.search_code
FROM
`qitz3_attributes_type` at
left join
qitz3_attributes a
on
a.attribute_type_id = at.id
left join
qitz3_attributes_property ap
on
ap.attribute_id = a.id
left join
qitz3_helloworld h
on
h.id = ap.property_id
where
at.id in (1,2,8,9,11)
and
a.search_filter = 1
and
h.area=506
and
h.expiry_date >= '2013-02-20 13:28:04'
group by
a.title
order by search_code
This seems much faster but I am still getting a using temporary and using filesort on the explain...
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE at range PRIMARY PRIMARY 4 NULL 5 Using where; Using temporary; Using filesort
1 SIMPLE a ref PRIMARY,Attribute type ID,Search filter,Attribute ... Attribute type ID 4 password.at.id 6 Using where
1 SIMPLE ap ref Property ID,Attribute ID,Attribute Property Attribute Property 4 password.a.id 142 Using where; Using index
1 SIMPLE h eq_ref PRIMARY,Area indexes,Expiry date PRIMARY 4 password.ap.property_id 1 Using where
ENDEDIT
I am working on a search component for a site I am developing and while it is all working there are a couple of queries that I would like to see running a touch faster.
In order to populate a set of search filters (display the count of the number of properties that have each facility or are of a particular type) I am using the following two queries. The first will get a list of IDs that I then plug into the second query as follows:
Based on the following info can anyone suggest a more efficient way to do this? I would really like to speed the first query up as it seems a little slow compared to the others.
Is 150ms actually that slow? 15ms would be better...
Thanks,
Adam
Query 1 (takes around 150ms):
SELECT h.id, h.parent_id, h.level, h.title as property_title, h.area, h.region, h.department, h.city,
LEFT(h.description, 250) as description, h.thumbnail, h.occupancy, h.swimming, g.path, (single_bedrooms + double_bedrooms + triple_bedrooms + quad_bedrooms + twin_bedrooms) as bedrooms, c.title as location_title, ( select min(tariff)
from qitz3_tariffs
where id = h.id ) as price, e.title as tariff_based_on, f.title as base_currency, a.title as property_type, a2.title as accommodation_type, ( select count(*)
from qitz3_reviews
where property_id = h.id
group by h.id ) as reviews
FROM qitz3_classifications c
LEFT JOIN qitz3_helloworld h
on c.id = h.area
LEFT JOIN qitz3_attributes_property ap
ON ap.property_id = h.id
LEFT JOIN qitz3_attributes_type at
ON at.id = ap.attribute_id
LEFT JOIN qitz3_attributes a
ON a.id = ap.attribute_id
LEFT JOIN qitz3_attributes_property ap2
ON ap2.property_id = h.id
LEFT JOIN qitz3_attributes_type at2
ON at2.id = ap2.attribute_id
LEFT JOIN qitz3_attributes a2
ON a2.id = ap2.attribute_id
LEFT JOIN qitz3_attributes e
ON e.id = h.tariff_based_on
LEFT JOIN qitz3_attributes f
ON f.id = h.base_currency
LEFT JOIN qitz3_classifications g
ON g.id = h.city
WHERE a.attribute_type_id = 1
AND a2.attribute_type_id = 2
AND c.id = 506
AND h.expiry_date >= '2013-02-20 12:05:13'
AND h.id > 1
Explain:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY c const PRIMARY PRIMARY 4 const 1
1 PRIMARY h ref PRIMARY,Area indexes,Expiry date Area indexes 4 const 615 Using where
1 PRIMARY ap ref Property ID,Attribute ID Property ID 4 password.h.id 21 Using where
1 PRIMARY at eq_ref PRIMARY PRIMARY 4 password.ap.attribute_id 1 Using index
1 PRIMARY a eq_ref PRIMARY,Attribute type ID PRIMARY 4 password.ap.attribute_id 1 Using where
1 PRIMARY ap2 ref Property ID,Attribute ID Property ID 4 password.ap.property_id 21 Using where
1 PRIMARY at2 eq_ref PRIMARY PRIMARY 4 password.ap2.attribute_id 1 Using index
1 PRIMARY a2 eq_ref PRIMARY,Attribute type ID PRIMARY 4 password.ap2.attribute_id 1 Using where
1 PRIMARY e eq_ref PRIMARY PRIMARY 4 password.h.tariff_based_on 1
1 PRIMARY f eq_ref PRIMARY PRIMARY 4 password.h.base_currency 1
1 PRIMARY g eq_ref PRIMARY PRIMARY 4 password.h.city 1
3 DEPENDENT SUBQUERY qitz3_reviews ref Property ID Property ID 4 password.h.id 1 Using index; Using temporary; Using filesort
2 DEPENDENT SUBQUERY qitz3_tariffs ref Property ID Property ID 4 password.h.id 2
Query 2 (takes around 30ms):
SELECT a.id,count(attribute_id) as count, a.title AS attribute, a.published, at.title as facility_type, at.search_code
FROM qitz3_attributes AS a
LEFT JOIN qitz3_attributes_type at
on at.id = a.attribute_type_id
LEFT JOIN qitz3_attributes_property ap
on ap.attribute_id = a.id
WHERE search_filter = 1
AND a.published = 1
AND property_id in (152843,103180,152845,4628,5653,3865,107553,155945,106029,107575,149052,837,104264,98635,98636,98637,98638,3667,106838,3672,157278,155743,157791,157792,151153,151155,100725,106109,157569,157576,107145,150666,103310,5780,3480,102041,154016,3490,154018,932,153518,151991,154041,154042,4288,5832,149451,157646,102094,148444,153822,157407,153839,151536,157393,157395,157428,157429,102236,104770,157378,157380,157381,157382,157383,157654,104768,103746,153683,150175,4618,101050,104942,157229,157230,98515,104771,104944,3612,148721,104212,5307,3432,156676,102706,404,5518,156359,5252,102697,5271,98979,101827,149524,102676,107551,5685,101736,156538,152703,4730,151881,95838,3759,149769,5269,98429,153729,5233,703,5579,98943,157433,3157,155661,107347,147545,147547,5216,106345,156533,93833,158091,96403,3491,968,158195,158196,157580,104148,3030,94686,154725,150582,103027,99062,102462,4384,5634,153874,157974,101669,47,105285,102481,102234,5749,156793,153748,96404,151467,154292,147645,97471,100551,102090,4841,3563,155643,4656,98424,157243,150601,157415,4701,102283,100719,100738,5643,98425,98972,103261,531,3105,98108,150592,5719,150616,157532,3974,3212,157581,97469,97470,149183,157638,149730,102114,156395,153621,102560,102913,94684,5609,157578,98423,98971,102151,146734,150585,104287,155296,104956,94592,102433,147575,156325,106344,101766,107058,106560,103026,157848,98973,4303,5620,149767,150563,4407,104268,97876,156784,156786,149922,701,154317,153821,102480,348,102778,102779,102780,102781,102479,352,103025,98677,5254,98697,3995,156322,100305,98532,3833,5374,150172,151435,102368,102380,157228,103171,147740,152870,103579,3870,104037,103016,4995,105104,157605,5811,955,147643,156648,107802,101502,94685,3569,148755,150293,4122,157013,157297,98676,156794,102848,157635,157640,95717,98980,102764,102777,102782,36,101765,154373,149829,154955,107683,158176,102557,157552,103163,5760,104627,153561,266,151335,151176,147620,147379,3085,155760,106339,151424,106759,5145,104990,97877,155495,5241,156407,156625,3236,152782,96066,147617,3860,4614,3497,147883,158207,102985,104622,101816,157275,149037,4792,149226,3496,101825,102538,150571,105015,97874,157391,158192,102562,155032,5383,102558,104194,156740,101446,147615,5815,107081,155992,97473,148817,945,101751,158074,4249,101792,4532,152828,104316,157319,156071,157508,157510,148836,4745,153823,157942,3859,157442,100017,102555,147629,149272,157845,151256,101481,154735,154737,157652,106232,97991,4660,3309,157597,407,157658,154152,157374,153385,148037,158214,100452)
GROUP BY a.id
This query gives a count of the number of properties with each attribute (e.g. Golf, Air conditioning, property type etc). The good thing about this is that only attributes are shown that have properties. So as the user drills down attributes with no properties are not shown. This is basically down to the first query where I get a list of the properties matching a particular set of attributes.
The tables are as follows:
--
-- Table structure for table qitz3_attributes
CREATE TABLE IF NOT EXISTS `qitz3_attributes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`attribute_type_id` int(11) NOT NULL,
`title` varchar(75) NOT NULL,
`ordering` int(11) NOT NULL,
`state` tinyint(4) NOT NULL DEFAULT '1',
`published` int(11) NOT NULL,
`search_filter` bit(1) NOT NULL,
`language_code` varchar(6) NOT NULL DEFAULT 'en-GB',
PRIMARY KEY (`id`),
KEY `Attribute type ID` (`attribute_type_id`),
KEY `Search filter` (`search_filter`),
KEY `Published` (`published`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1522 ;
--
-- Table structure for table qitz3_attributes_property
CREATE TABLE IF NOT EXISTS `qitz3_attributes_property` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`attribute_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `Property ID` (`property_id`),
KEY `Attribute ID` (`attribute_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=66261 ;
--
-- Table structure for table qitz3_attributes_type
CREATE TABLE IF NOT EXISTS `qitz3_attributes_type` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(75) NOT NULL,
`language_code` varchar(6) NOT NULL,
`field_name` varchar(25) NOT NULL,
`search_code` varchar(25) NOT NULL,
`state` int(11) NOT NULL DEFAULT '1',
`published` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=34 ;
--
-- Table structure for table qitz3_classifications
CREATE TABLE IF NOT EXISTS `qitz3_classifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(10) unsigned NOT NULL DEFAULT '0',
`lft` int(11) NOT NULL DEFAULT '0',
`rgt` int(11) NOT NULL DEFAULT '0',
`level` int(10) unsigned NOT NULL DEFAULT '0',
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`path` varchar(255) NOT NULL DEFAULT '',
`alias` varchar(255) NOT NULL,
`access` tinyint(3) unsigned NOT NULL DEFAULT '0',
`published` int(11) NOT NULL,
`longitude` float(10,6) NOT NULL,
`latitude` float(10,6) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_left_right` (`lft`,`rgt`),
KEY `Alias index` (`alias`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=158052 ;
--
-- Table structure for table qitz3_helloworld (Property table)
CREATE TABLE IF NOT EXISTS `qitz3_helloworld` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(10) NOT NULL DEFAULT '0',
`lft` int(11) NOT NULL DEFAULT '0',
`rgt` int(11) NOT NULL DEFAULT '0',
`level` int(10) unsigned NOT NULL,
`alias` varchar(250) NOT NULL DEFAULT '',
`access` tinyint(3) unsigned NOT NULL DEFAULT '0',
`path` varchar(255) NOT NULL DEFAULT '',
`title` varchar(120) NOT NULL,
`area` int(11) NOT NULL DEFAULT '0',
`region` int(11) NOT NULL DEFAULT '0',
`department` int(11) NOT NULL DEFAULT '0',
`city` int(11) NOT NULL DEFAULT '0',
`params` text NOT NULL,
`created_by` int(10) NOT NULL DEFAULT '0',
`created_on` datetime NOT NULL,
`modified` datetime DEFAULT NULL,
`expiry_date` date DEFAULT NULL,
`availability_last_updated_on` datetime DEFAULT NULL,
`modified_by` int(11) DEFAULT NULL,
`lang` varchar(5) NOT NULL DEFAULT 'en-GB',
`description` mediumtext NOT NULL COMMENT 'The summary and description for this accommodation',
`internal_facilities_other` varchar(1000) NOT NULL,
`external_facilities_other` varchar(1000) NOT NULL,
`activities_other` varchar(5000) NOT NULL,
`location_details` varchar(5000) NOT NULL,
`getting_there` varchar(5000) NOT NULL,
`thumbnail` varchar(150) NOT NULL,
`occupancy` int(11) DEFAULT NULL,
`single_bedrooms` int(11) NOT NULL,
`double_bedrooms` int(11) NOT NULL,
`triple_bedrooms` int(11) DEFAULT NULL,
`quad_bedrooms` int(11) DEFAULT NULL,
`twin_bedrooms` int(11) DEFAULT NULL,
`childrens_beds` int(11) DEFAULT NULL,
`cots` int(11) DEFAULT NULL,
`extra_beds` int(11) DEFAULT NULL,
`bathrooms` int(11) NOT NULL,
`toilets` int(11) DEFAULT NULL,
`swimming` int(11) NOT NULL,
`latitude` decimal(10,7) DEFAULT NULL,
`longitude` decimal(10,7) DEFAULT NULL,
`nearest_town` varchar(50) DEFAULT NULL,
`distance_to_coast` int(11) DEFAULT NULL,
`additional_price_notes` varchar(3000) DEFAULT NULL,
`base_currency` int(11) DEFAULT NULL,
`tariff_based_on` int(11) DEFAULT NULL,
`linen_costs` varchar(250) DEFAULT NULL,
`changeover_day` int(11) DEFAULT NULL,
`published` tinyint(4) NOT NULL DEFAULT '0',
`video` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_left_right` (`lft`,`rgt`),
KEY `Area indexes` (`area`,`region`,`department`),
KEY `Expiry date` (`expiry_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=158249 ;
--
-- Table structure for table qitz3_reviews
CREATE TABLE IF NOT EXISTS `qitz3_reviews` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`title` varchar(150) NOT NULL,
`review_text` varchar(4000) NOT NULL,
`date` date NOT NULL,
`rating` int(11) NOT NULL,
`guest_name` varchar(75) NOT NULL,
`guest_email` varchar(150) NOT NULL,
`state` tinyint(3) NOT NULL DEFAULT '0',
`published` tinyint(1) NOT NULL DEFAULT '0',
`created` datetime NOT NULL,
`created_by` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `Property ID` (`property_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=921 ;
--
-- Table structure for table qitz3_tariffs
CREATE TABLE IF NOT EXISTS `qitz3_tariffs` (
`tariff_id` int(11) NOT NULL AUTO_INCREMENT,
`id` int(11) NOT NULL COMMENT 'Denotes the property listing ID',
`start_date` date NOT NULL,
`end_date` date NOT NULL,
`tariff` int(11) NOT NULL COMMENT 'Price per booking period between the dates specified. dated spec',
PRIMARY KEY (`tariff_id`),
KEY `Property ID` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9267 ;
Quick play, but trying to move the subselects out from the field list.
SELECT h.id, h.parent_id, h.level, h.title as property_title, h.area, h.region, h.department, h.city, LEFT(h.description, 250) as description, h.thumbnail, h.occupancy, h.swimming, g.path, (single_bedrooms + double_bedrooms + triple_bedrooms + quad_bedrooms + twin_bedrooms) as bedrooms, c.title as location_title,
Sub1.price,
e.title as tariff_based_on, f.title as base_currency, a.title as property_type, a2.title as accommodation_type,
Sub2.reviews
FROM qitz3_classifications c
LEFT JOIN qitz3_helloworld h on c.id = h.area
LEFT JOIN qitz3_attributes_property ap ON ap.property_id = h.id
LEFT JOIN qitz3_attributes_type at ON at.id = ap.attribute_id
LEFT JOIN qitz3_attributes a ON a.id = ap.attribute_id
LEFT JOIN qitz3_attributes_property ap2 ON ap2.property_id = h.id
LEFT JOIN qitz3_attributes_type at2 ON at2.id = ap2.attribute_id
LEFT JOIN qitz3_attributes a2 ON a2.id = ap2.attribute_id
LEFT JOIN qitz3_attributes e ON e.id = h.tariff_based_on
LEFT JOIN qitz3_attributes f ON f.id = h.base_currency
LEFT JOIN qitz3_classifications g ON g.id = h.city
LEFT JOIN ( SELECT id, MIN(tariff) AS price FROM qitz3_tariffs GROUP BY id) Sub1 ON Sub1.Id = h.id
LEFT JOIN ( SELECT property_id, COUNT(*) AS reviews FROM qitz3_reviews GROUP BY property_id ) as Sub2 ON Sub2.property_id = h.id
WHERE a.attribute_type_id = 1
AND a2.attribute_type_id = 2
AND c.id = 506
AND h.expiry_date >= '2013-02-20 12:05:13'
AND h.id > 1
When you need more speed in searching data you should take a look at Solr or Sphinx. With this index servers you can index your MySQL-Data and query them.
Its much more faster then MySQL.
There's quite a lot wrong in your first query:
The first 7 LEFT JOINs should be INNER JOINs. For qitz3_attributes you should consider normalizing the data less aggressively (use multiple columns instead of multiple rows to describe the data.

How do I select and match from multiple tables?

This is my table layout:
-- Table structure for table `areas`
CREATE TABLE IF NOT EXISTS `areas` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`country` varchar(20) NOT NULL,
`city` varchar(20) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- Table structure for table `matches`
CREATE TABLE IF NOT EXISTS `matches` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`view_id` bigint(20) unsigned NOT NULL,
`status` enum('h','n') NOT NULL,
`exp_date` date NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
-- Table structure for table `users`
CREATE TABLE IF NOT EXISTS `users` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`limit_age` varchar(5) NOT NULL DEFAULT '18:30',
`limit_gender` varchar(2) DEFAULT NULL,
`notifications` int(11) NOT NULL DEFAULT '0',
`name` varchar(30) NOT NULL,
`email` varchar(40) NOT NULL,
`image_big` varchar(120) NOT NULL,
`image_small` varchar(120) NOT NULL,
`crop_data` int(11) DEFAULT NULL,
`visible` tinyint(1) NOT NULL DEFAULT '0',
`age` int(11) DEFAULT NULL,
`registered_at` datetime NOT NULL,
`views` bigint(20) unsigned NOT NULL DEFAULT '0',
`hots` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;
I will try to explain this better:
I have a given ID.
I would like to select one entry from users which is not the ID i have given
AND which user_id does not exist in matches
AND has visible = 1
AND where any country + city matches the given users country + city
Is this the correct way to do it (12 is an example of an given ID):
SELECT *
FROM users a
INNER JOIN areas ON areas.user_id = a.id
WHERE a.id NOT IN (SELECT user_id FROM matches)
AND NOT a.id = '12'
AND a.limit_age = '18:30'
AND a.visible = '1'
AND areas.country = 'sverige'
AND areas.city = 'gbg'
Sorry for the confusion :)
Ok, I'll make an attempt at this:
SELECT *
FROM users a
INNER JOIN areas ON areas.user_id = a.id
WHERE a.id NOT IN (SELECT user_id FROM matches)
AND a.visible = '1'
AND a.limit_age = '18:30'
AND a.limit_gender = 'f'
AND areas.country = ?
AND areas.city = ?;
This is SELECTing from "users", and returning a result only if that user also has an entry in the "areas" table. The first item in the WHERE clause ensures that a row will not be returned if the users.id (a.id) is found in the user_id field on the "matches" table. Next, I added checks for visible = 1, limit_age, and limit_gender as specified in his attempt. Finally, I left country and city parameterized so that they can be added as parameters in the php code. If anything that should give you a starting point.

Categories