How can I optimize this mysql query having left joins as columns? - mysql

This query is taking over 4 seconds to run killing the performance on the page.
The query is doing a sum of points getting the max point by day for a product for a particular month. The purpose is to display a ranking for a given month ordered by the sum of points.
SELECT eriginal_asin, DATE_FORMAT(date_time,'%m/%d/%Y %h:%i:%s') as date_time, SUM(maxpoints) as points, `o1`.`value` as value,
`o2`.`value` as value1, `o3`.`value` as value2, `o4`.`value` as value3, `o5`.`value` as value4, `o6`.`value` as value5,
`o7`.`value` as value6, `o8`.`value` as value7, `o9`.`value` as value8, `o10`.`value` as value9, `o11`.`value` as value10,
`o12`.`value` as value11, `o13`.`value` as value12, `o14`.`value` as value13, `o15`.`value` as value14, `o16`.`value` as value15,
`o17`.`value` as value16, property.id, user.name_surname, user.name_last
from
(SELECT id, eriginal_asin, max(points) as maxpoints, DATE_FORMAT(date_time,'%m/%d/%Y %h:%i:%s') as date_time
from ranking
where date_time >= '2015-09-01'
and date_time <= '2015-09-30 23:59:59'
and points > 0
group by eriginal_asin, region, date(date_time)
)rankmax, property
LEFT JOIN `property_user` ON `property`.`id` = `property_user`.`property_id`
LEFT JOIN `user` ON `property_user`.`user_id` = `user`.`id`
LEFT JOIN `property_value` o1 ON `property`.`id` = `o1`.`property_id` and o1.option_id = 17
LEFT JOIN `property_value` o2 ON `property`.`id` = `o2`.`property_id` and o2.option_id = 10
LEFT JOIN `property_value` o3 ON `property`.`id` = `o3`.`property_id` and o3.option_id = 54
LEFT JOIN `property_value` o4 ON `property`.`id` = `o4`.`property_id` and o4.option_id = 64
LEFT JOIN `property_value` o5 ON `property`.`id` = `o5`.`property_id` and o5.option_id = 65
LEFT JOIN `property_value` o6 ON `property`.`id` = `o6`.`property_id` and o6.option_id = 5
LEFT JOIN `property_value` o7 ON `property`.`id` = `o7`.`property_id` and o7.option_id = 6
LEFT JOIN `property_value` o8 ON `property`.`id` = `o8`.`property_id` and o8.option_id = 10
LEFT JOIN `property_value` o9 ON `property`.`id` = `o9`.`property_id` and o9.option_id = 63
LEFT JOIN `property_value` o10 ON `property`.`id` = `o10`.`property_id` and o10.option_id = 55
LEFT JOIN `property_value` o11 ON `property`.`id` = `o11`.`property_id` and o11.option_id = 56
LEFT JOIN `property_value` o12 ON `property`.`id` = `o12`.`property_id` and o12.option_id = 57
LEFT JOIN `property_value` o13 ON `property`.`id` = `o13`.`property_id` and o13.option_id = 58
LEFT JOIN `property_value` o14 ON `property`.`id` = `o14`.`property_id` and o14.option_id = 59
LEFT JOIN `property_value` o15 ON `property`.`id` = `o15`.`property_id` and o15.option_id = 60
LEFT JOIN `property_value` o16 ON `property`.`id` = `o16`.`property_id` and o16.option_id = 61
LEFT JOIN `property_value` o17 ON `property`.`id` = `o17`.`property_id` and o17.option_id = 62
where property.is_activated = 1
and o1.value = eriginal_asin
GROUP BY DATE(date_time), eriginal_asin
order by points desc

one thing is, you can do it with one LEFT JOIN. I have made a sample (not with all columns) to test if it works better
SELECT eriginal_asin,
DATE_FORMAT(date_time,'%m/%d/%Y %h:%i:%s') AS date_time,
SUM(maxpoints) AS points,
coalesce( IF( o.property_id = 17, `o`.`value`, NULL )) AS value_1,
coalesce(IF (o.property_id = 10, `o`.`value`, NULL )) AS value_
coalesce(IF (o.property_id = 54, `o`.`value`, NULL )) AS value_3,
coalesce(IF (o.property_id = 64, `o`.`value`, NULL )) AS value_4,
property.id,
user.name_surname,
user.name_last
FROM
(SELECT id,
eriginal_asin,
max(points) AS maxpoints,
DATE_FORMAT(date_time,'%m/%d/%Y %h:%i:%s') AS date_time
FROM ranking
WHERE date_time >= '2015-09-01'
AND date_time <= '2015-09-30 23:59:59'
AND points > 0
GROUP BY eriginal_asin,
region,
date(date_time) )rankmax,
property
LEFT JOIN `property_user` ON `property`.`id` = `property_user`.`property_id`
LEFT JOIN `user` ON `property_user`.`user_id` = `user`.`id`
LEFT JOIN `property_value` o ON `property`.`id` = `o`.`property_id`
WHERE property.is_activated = 1
AND o1.value = eriginal_asin
GROUP BY o.property_id,
DATE(date_time),
eriginal_asin
ORDER BY points DESC;

A few things... Can you please provide some sample data of your "Property_Value" table records... what are the "values". Ranking.ID... Is that the ID associated to the property? You have no join condition to that and THAT may be causing a Cartesian result.
Does the Ranking table have a "Property_ID" column to join against. Do you have index on your property_value table on ( value, id, option_id )... A combination/multi-field index would significantly help too.
Also, it is unclear exactly how / where the property ID is based on the RankMax table -- or does the property table have the "eriginal_asin" column (doubt it).
Existing table structures and some sample data (space formatting of data instead of tabs preferred) would help myself and/or others to helping you out.
EXAMPLE ONLY OF DATA (you can copy/paste in your original question and adjust content as needed), but your join criteria really is missing somewhere.
Property Table
ID Is_Activiated OtherDescript
1 1 Test Sample
2 0 Another Property
3 1 last
User Table
ID UserName
PropertyUser Table
ID Property_ID
1 3
2 1
3 2
Property_value table
ID Property_ID Option_ID Value
1 3 17 blah
1 3 10 another
1 3 54 blah 2

Related

How to merge two queries into a subqueries

I have database like this http://sqlfiddle.com/#!9/e52c43
First query is :
SELECT m.tanggal, sum(mi.qty) as totalMuatan, mi.idPlastik
FROM tblMuatan m
LEFT JOIN tblMuatanIsi mi ON m.idMuatan = mi.idMuatan
WHERE m.tanggal='2020-03-15'
GROUP BY mi.idPlastik
The result is:
tanggal totalMuatan idPlastik
2020-03-15 85 1
2020-03-15 10 2
And second query is :
SELECT s.tanggal, sum(si.qty) as totalStok, si.idPlastik
FROM tblStok s
LEFT JOIN tblStokIsi si ON s.idStok = si.idStok
WHERE s.tanggal = '2020-03-15'
GROUP BY si.idPlastik
The result is :
tanggal totalStok idPlastik
2020-03-15 100 1
2020-03-15 200 2
I want to merge that 2 queries into single query with subquery
tanggal totalStok totalMuatan netTotal idPlastik
2020-03-15 100 85 15 1
2020-03-15 200 10 190 2
How to do the subquery in example above? Thank you for the support
Better to use COALESCE since you're using LEFT JOIN for the tables you are calculating SUM from to avoid no result for the records that have NULL values.
select m.tanggal, t.totalStok, sum(mi.qty) as totalMuatan, coalesce(t.totalStok,0)-coalesce(sum(mi.qty),0) as netTotal, mi.idPlastik
from tblMuatan m
LEFT JOIN tblMuatanIsi mi ON m.idMuatan = mi.idMuatan
JOIN (SELECT s.tanggal, sum(si.qty) as totalStok, si.idPlastik
FROM tblStok s
LEFT JOIN tblStokIsi si ON s.idStok = si.idStok
WHERE s.tanggal='2020-03-15'
GROUP BY s.tanggal,si.idPlastik) t on m.tanggal=t.tanggal and mi.idPlastik = t.idPlastik
group by m.tanggal, t.totalStok,mi.idPlastik
Please try..
SELECT T1.tanggal, T2.totalStok, T1.totalMuatan, (T2.totalStok - T1.totalMuatan), T1.idPlastik
FROM
(SELECT m.tanggal, sum(mi.qty) as totalMuatan, mi.idPlastik
FROM tblMuatan m
LEFT JOIN tblMuatanIsi mi ON m.idMuatan = mi.idMuatan
WHERE m.tanggal='2020-03-15'
GROUP BY mi.idPlastik)
as T1,
(SELECT s.tanggal, sum(si.qty) as totalStok, si.idPlastik
FROM tblStok s
LEFT JOIN tblStokIsi si ON s.idStok = si.idStok
WHERE s.tanggal = '2020-03-15'
GROUP BY si.idPlastik)
as T2
WHERE
T1.tanggal = T2.tanggal;
SELECT a.tanggal,
b.totalstok,
a.totalmuatan,
( totalstok - totalmuatan ) netTotal,
a.idplastik
FROM (SELECT convert(varchar, m.tanggal, 23) tanggal,
Sum(mi.qty) AS totalMuatan,
mi.idplastik
FROM #tblmuatan m
LEFT JOIN #tblmuatanisi mi
ON m.idmuatan = mi.idmuatan
WHERE m.tanggal = 1
GROUP BY mi.idplastik,
convert(varchar, m.tanggal, 23)) a
JOIN (SELECT convert(varchar, s.tanggal, 23) tanggal,
Sum(si.qty) AS totalStok,
si.idplastik
FROM #tblstok s
LEFT JOIN #tblstokisi si
ON s.idstok = si.idstok
WHERE s.tanggal = 1
GROUP BY si.idplastik,
convert(varchar, s.tanggal, 23)) b
ON a.idplastik = b.idplastik

Slow Mysql Inner joins with multiple OR

I'm helping a friend with an e-commerce site. He has options for users to select different colours, styles, use and type of the products he's selling. The query the adds the following to the query:
INNER JOIN tbl_coloursProducts col ON ( p.product_id = col.productID AND (col.colourID = 2 OR col.colourID = 3 OR col.colourID = 5 OR col.colourID = 8 OR col.colourID = 10))
INNER JOIN tbl_useProducts tbluse ON ( p.product_id = tbluse.productID AND (tbluse.useID = 15 OR tbluse.useID = 16 OR tbluse.useID = 17 OR tbluse.useID = 18))
INNER JOIN tbl_styleProducts style ON ( p.product_id = style.productID AND (style.styleID = 39 OR style.styleID = 44))
INNER JOIN tbl_typeProducts type ON ( p.product_id = type.productID AND (type.typeID = 46 OR type.typeID = 48 OR type.typeID = 50))
The query loads fast enough when only a few options are selecting, but some users are selecting multiple or each which is causing the query to run in excess of 30 seconds and timing out.
Without altering the table structure is there a better way to optimise the query?
This is the full query:
SELECT *,
p.product_id,
Coalesce((SELECT p2sp.price
FROM ab_product_specials p2sp
WHERE p2sp.product_id = p.product_id
AND p2sp.customer_group_id = '1'
AND ( ( p2sp.date_start = '0000-00-00'
OR p2sp.date_start < Now() )
AND ( p2sp.date_end = '0000-00-00'
OR p2sp.date_end > Now() ) )
ORDER BY p2sp.priority ASC,
p2sp.price ASC
LIMIT 1), p.price) AS final_price,
pd.name AS name,
m.name AS manufacturer,
ss.name AS stock,
(SELECT Avg(r.rating)
FROM ab_reviews r
WHERE p.product_id = r.product_id
GROUP BY r.product_id) AS rating,
(SELECT Count(rw.review_id)
FROM ab_reviews rw
WHERE p.product_id = rw.product_id
GROUP BY rw.product_id) AS review
FROM ab_products p
LEFT JOIN ab_product_descriptions pd
ON ( p.product_id = pd.product_id
AND pd.language_id = '1' )
LEFT JOIN ab_products_to_stores p2s
ON ( p.product_id = p2s.product_id )
LEFT JOIN ab_manufacturers m
ON ( p.manufacturer_id = m.manufacturer_id )
LEFT JOIN ab_stock_statuses ss
ON ( p.stock_status_id = ss.stock_status_id
AND ss.language_id = '1' )
LEFT JOIN ab_products_to_categories p2c
ON ( p.product_id = p2c.product_id )
INNER JOIN tbl_coloursproducts col
ON ( p.product_id = col.productid
AND ( col.colourid = 2
OR col.colourid = 3
OR col.colourid = 5
OR col.colourid = 8
OR col.colourid = 10 ) )
INNER JOIN tbl_useproducts tbluse
ON ( p.product_id = tbluse.productid
AND ( tbluse.useid = 15
OR tbluse.useid = 16
OR tbluse.useid = 17
OR tbluse.useid = 18 ) )
INNER JOIN tbl_styleproducts style
ON ( p.product_id = style.productid
AND ( style.styleid = 39
OR style.styleid = 44 ) )
INNER JOIN tbl_typeproducts type
ON ( p.product_id = type.productid
AND ( type.typeid = 46
OR type.typeid = 48
OR type.typeid = 50 ) )
WHERE p.status = '1'
AND p.date_available <= Now()
AND p2s.store_id = 0
AND p2c.category_id = 131
GROUP BY p.product_id
ORDER BY p.product_id DESC
LIMIT 0, 8
Without the custom bits the query runs fine.
Looking at that query, not sure the ORs are the problem themselves (although you could possibly make the code more compact by using and IN clause for each one). Rather I suspect that selecting more and more options results in more rows being returned. And this is causing problems with the sub queries in the SELECT clause.
Can you try the query with the sub queries removed from the SELECT clause and see the effect that has.
You can remove the sub queries quite easily.
SELECT *,
p.product_id,
Coalesce(sub1.price, p.price) AS final_price,
pd.name AS name,
m.name AS manufacturer,
ss.name AS stock,
sub0.rating,
sub0.review
FROM ab_products p
INNER JOIN
(
SELECT r.product_id,
Avg(r.rating) AS rating,
Count(rw.review_id) AS review
FROM ab_reviews r
GROUP BY r.product_id
) sub0
ON p.product_id = sub0.product_id
LEFT OUTER JOIN
(
SELECT p2sp.product_id,
SUBSTRING_INDEX(GROUP_CONCAT(p2sp.price ORDER BY p2sp.priority ASC, p2sp.price ASC ), ',', 1) AS price
FROM ab_product_specials p2sp
WHERE p2sp.customer_group_id = '1'
AND ( p2sp.date_start = '0000-00-00' OR p2sp.date_start < NOW() )
AND ( p2sp.date_end = '0000-00-00' OR p2sp.date_end > NOW() )
GROUP BY p2sp.product_id
) sub1
ON p.product_id = sub1.product_id
LEFT JOIN ab_product_descriptions pd
ON ( p.product_id = pd.product_id
AND pd.language_id = '1' )
LEFT JOIN ab_products_to_stores p2s
ON ( p.product_id = p2s.product_id )
LEFT JOIN ab_manufacturers m
ON ( p.manufacturer_id = m.manufacturer_id )
LEFT JOIN ab_stock_statuses ss
ON ( p.stock_status_id = ss.stock_status_id
AND ss.language_id = '1' )
LEFT JOIN ab_products_to_categories p2c
ON ( p.product_id = p2c.product_id )
INNER JOIN tbl_coloursproducts col
ON ( p.product_id = col.productid
AND ( col.colourid = 2
OR col.colourid = 3
OR col.colourid = 5
OR col.colourid = 8
OR col.colourid = 10 ) )
INNER JOIN tbl_useproducts tbluse
ON ( p.product_id = tbluse.productid
AND ( tbluse.useid = 15
OR tbluse.useid = 16
OR tbluse.useid = 17
OR tbluse.useid = 18 ) )
INNER JOIN tbl_styleproducts style
ON ( p.product_id = style.productid
AND ( style.styleid = 39
OR style.styleid = 44 ) )
INNER JOIN tbl_typeproducts type
ON ( p.product_id = type.productid
AND ( type.typeid = 46
OR type.typeid = 48
OR type.typeid = 50 ) )
WHERE p.status = '1'
AND p.date_available <= Now()
AND p2s.store_id = 0
AND p2c.category_id = 131
GROUP BY p.product_id
ORDER BY p.product_id DESC
LIMIT 0, 8
As an aside, when you read from ab_product_specials you are checking for the date_start and date_end to be 0000-00-00 (ie, dates), but also comparing them with NOW() which returns a date / time field. Are those fields date or date / time fields?
My first though was to use IN to make the query eaier to read:
INNER JOIN tbl_coloursProducts col
ON p.product_id = col.productID AND col.colourID IN ( 2, 3, 5, 8, 10 )
Then I thought, I wonder if they are dynamically building SQL text to squirt into the database logic?! The optimizer is unlikely to do well at optimizing queries when they are constantly mutating in this way.
Consider a scratch table (pseudo code):
-- One time:
CREATE TABLE SratchColours ( colourID INT NOT NULL UNQIUE );
-- For each query:
DELETE FROM SratchColours;
INSERT INTO SratchColours VALUES ( 2 ), ( 3 ), ( 5 ), ( 8 ), ( 10 );
Now you dynamic list of values simply becomes just another join:
tbl_coloursProducts NATURAL JOIN SratchColours
(or you could use an inner join if you must!)
Now, having one base table for every concurrent user is probably not a great way to scale a system. Therefore, consider how to pass a bag of colourID values to the database logic (say, a stored proc), put them into a table (say, a temporary table), then join from there to your base tables.

How to remove range check in query

I have the following query, when I do an explain for the query it says "Range checked for each record (index map: 0x8)". I am assuming this is one reason the query is as slow, how can I improve this
The query looks as follow currently,
explain select
*
from
(select
CASE WHEN dd.parentId IS NOT NULL
THEN CONCAT(dd.`profileId`,dd.`orgId`,dd.parentId)
ELSE CONCAT(dd.`profileId`,dd.`orgId`,dd.id) END as ticketId,dd.*
from
t_dtls_prod dd where dd.currentlyActive = true and dd.dataSource ='SAND' AND msgCreatedOn BETWEEN '2016-09-01 00:00:00'
AND '2016-10-03 00:00:00' and dd.profileId = 148 group by ticketId ) as d
left join basket_prod b on b.basketId=d.toBasketId
left join lead_social_accts_prod a on a.orgId=1002
AND (
(
(
(a.`type`='TWITTER' and d.channel in (1,34)) or (a.`type`='FACEBOOK' and d.channel in (6,7))
or (a.`type`='GOOGLEPLUS' and d.channel in (5,25)) or (a.`type`='LINKEDIN' and d.channel =30)
or (a.`type`='GOOGLEPLUS' and d.channel=36) or ((a.`type`='YOUTUBE' or a.`type`='GOOGLEPLUS') and d.channel=27)
or (a.`type`='TUMBLR' and d.channel in (29,31)) or
( a.`type`='INSTAGRAM' and d.channel=35)
)
AND
d.userChannelId=a.socialId) OR
(a.`type`='BLOG' and d.channel in (9,11,15,21) AND d.msgId=a.socialId))
left join lead_prod l on l.leadId=a.leadId and l.orgId=1002 where d.profileId = 148 limit 0,1000
The results seem to come out in a descent time upto 1000 rows, but beyond that it just dies.
This should be better
EXPLAIN SELECT
d.*, b.*, a.*, l.*,
(CASE WHEN d.parentId IS NOT NULL
THEN CONCAT(d.`profileId`, d.`orgId`, d.parentId)
ELSE CONCAT(d.`profileId`, d.`orgId`, d.id) END) as ticketId
FROM
t_dtls_prod d
LEFT JOIN basket_prod b ON b.basketId = d.toBasketId
LEFT JOIN lead_social_accts_prod a ON a.orgId = 1002 AND
(
(d.msgId = a.socialId AND d.channel in (9,11,15,21) AND a.`type`='BLOG')
OR
(
d.userChannelId = a.socialId
AND
(
(d.channel IN (1,34) AND a.`type`='TWITTER')
OR
(d.channel IN (6,7) AND a.`type`='FACEBOOK')
OR
(d.channel IN (5, 25, 36) AND a.`type`='GOOGLEPLUS')
OR
(d.channel = 30 AND a.`type`='LINKEDIN')
OR
(d.channel=27 AND a.`type` IN ('YOUTUBE', 'GOOGLEPLUS'))
OR
(d.channel IN (29,31) AND a.`type`='TUMBLR')
OR
(d.channel = 35 AND a.`type`='INSTAGRAM')
)
)
)
LEFT JOIN lead_prod l ON l.leadId = a.leadId AND l.orgId = 1002
WHERE
d.currentlyActive = true AND d.dataSource ='SAND' AND msgCreatedOn BETWEEN '2016-09-01 00:00:00' AND '2016-10-03 00:00:00' AND d.profileId = 148
GROUP BY ticketId
LIMIT 0,1000
LEFT JOIN lead_social_accts_prod a ON a.orgId = 1002 here you forgot connection to t_dtls_prod or basket_prod like a.someId = b.someId

mysql grouping mre than one query

I try to explain the matter:
I have a hotel management system built with php+mysql.
I need to extract the number of:
current reservations visitors
arriving visitors
leaving visitors
and I need to know this numbers grouped by "region" (Region is either a country or a region of a country. I get this info from a stored function).
I have tried many times, but I always get values not in line with what I expect.
I have tried grouping by sum, by region, by the two of them, I have tried nesting the queries (horrible result...i'm not that good at subqueries).
Here are the 3 main queries:
Current visitors:
select p.num_persone, IFNULL(getcoderegione(c.regione),getNazioneCodeIstat(c.nazione)) regione, p.*, c.nazione, c.regione from prenota2015 p INNER JOIN clienti c ON c.idclienti = p.idclienti where p.iddatainizio < 94 and p.iddatafine >= 93 and p.idclienti != '0';
Arriving visitors:
select p.num_persone, IFNULL(getcoderegione(c.regione),getNazioneCodeIstat(c.nazione)) regione, p.*, c.nazione, c.regione from prenota2015 p INNER JOIN clienti c ON c.idclienti = p.idclienti where p.iddatainizio < 94 and p.iddatainizio >= 93 and p.idclienti != '0';
Leaving visitors:
select p.num_persone, IFNULL(getcoderegione(c.regione),getNazioneCodeIstat(c.nazione)) regione, p.*, c.nazione, c.regione from prenota2015 p INNER JOIN clienti c ON c.idclienti = p.idclienti where p.iddatafine < 93 and p.iddatafine >= 92 and p.idclienti != '0';
The IFNULL stuff checks if it should present the country code or the region code.
Table 'clienti' contains the value of the region or country for IFNULL check mentioned above and it is important for the grouping clause.
what I expect is something like:
| region code | visitors present | visitors arriving | visitors leaving
------------------------------------------------------------------------
| 219 | 3 | 1 | 1 |
------------------------------------------------------------------------
| 186 | 2 | 0 | 0 |
and so on.
Question time: I would you do it?
I tried last time with:
SELECT DISTINCT
IFNULL(getcoderegione(c.regione),getNazioneCodeIstat(c.nazione)) regione,
pres.presenze,
part.partenze,
arr.arrivi
FROM
(
select COUNT(p.idprenota) partenze, p.idclienti
from prenota2015 p
INNER JOIN clienti c ON c.idclienti = p.idclienti
where
p.iddatafine < 91
and p.iddatafine >= 90
GROUP BY regione
) as part,
(
select COUNT(p2.idprenota) arrivi, p2.idclienti
from prenota2015 p2
INNER JOIN clienti c ON c.idclienti = p2.idclienti
where
p2.iddatainizio < 91
and p2.iddatainizio >= 90
GROUP BY regione
) as arr,
(
select COUNT(p3.idprenota) presenze, p3.idclienti
from prenota2015 p3
INNER JOIN clienti c ON c.idclienti = p3.idclienti
where
p3.iddatainizio < 91
and p3.iddatafine >= 90
GROUP BY regione
) as pres,
clienti c
but it was a desperate attempt to try to understand how to move around it.
Any help? Suggestions?
Thank you very much
SELECT q1.regione,
q1.total AS current_visitors,
q2.total AS arriving_visitors,
q1.total AS leaving_visitors
FROM (
SELECT sum(p.num_persone) total,
IFNULL(getcoderegione(c.regione), getNazioneCodeIstat(c.nazione)) regione
FROM prenota2015 p
INNER JOIN clienti c ON c.idclienti = p.idclienti
WHERE p.iddatainizio < 94
AND p.iddatafine >= 93
AND p.idclienti != '0'
GROUP BY regione
) q1
INNER JOIN (
SELECT sum(p.num_persone) total,
IFNULL(getcoderegione(c.regione), getNazioneCodeIstat(c.nazione)) regione
FROM prenota2015 p
INNER JOIN clienti c ON c.idclienti = p.idclienti
WHERE p.iddatainizio < 94
AND p.iddatainizio >= 93
AND p.idclienti != '0'
GROUP BY regione
) q2 ON q1.regione = q2.regione
INNER JOIN (
SELECT sum(p.num_persone) total,
IFNULL(getcoderegione(c.regione), getNazioneCodeIstat(c.nazione)) regione
FROM prenota2015 p
INNER JOIN clienti c ON c.idclienti = p.idclienti
WHERE p.iddatafine < 93
AND p.iddatafine >= 92
AND p.idclienti != '0'
GROUP BY regione
) q3 ON q1.regione = q3.regione;
or, as moo suggested, create views of your three queries, which would make this one a lot neater

MySQL select two columns multiple name value pair

I need help about generating query for multiple column.
part of my tbl_advert_specific_fields_values table look like:
id advert_id field_name field_value
1 654 t1_sqft 50
2 655 t1_yearbuilt 1999
3 1521 t2_doorcount 5
4 656 t1_yearbuilt 2001
5 656 t1_sqft 29
6 654 t1_yearbuilt 2004
SELECT p.*, p.id AS id, p.title AS title, usr.id as advert_user_id,
p.street_num, p.street,c.icon AS cat_icon,c.title AS cat_title,c.title AS cat_title,
p.description as description,
countries.title as country_name,
states.title as state_name,
date_FORMAT(p.created, '%Y-%m-%d') as fcreated
FROM tbl AS p
LEFT JOIN tbl_advertmid AS pm ON pm.advert_id = p.id
INNER JOIN tbl_usermid AS am ON am.advert_id = p.id
LEFT JOIN tbl_users AS usr ON usr.id = am.user_id
INNER JOIN tbl_categories AS c ON c.id = pm.cat_id
INNER JOIN tbl_advert_specific_fields_values AS asfv ON asfv.advert_id = p.id
LEFT JOIN tbl_countries AS countries ON countries.id = p.country
LEFT JOIN tbl_states AS states ON states.id = p.locstate
WHERE p.published = 1 AND p.approved = 1 AND c.published = 1
AND (asfv.field_name = 't1_yearbuilt'
AND CONVERT(asfv.field_value,SIGNED) <= 2004 )
AND (asfv.field_name = 't1_sqft'
AND CONVERT(asfv.field_value,SIGNED) <= 50)
AND p.price <= 10174945 AND (p.advert_type_id = 1)
AND (c.id = 43 OR c.parent = 43)
GROUP BY p.id
ORDER BY p.price DESC
ok, the problem is in this asfv query part that are generated dynamically. It belong to objects which represent adverts by its specific fields. asfv is actually advert_specific_fields_values table (table name say all about it).
Without part:
AND (asfv.field_name = 't1_yearbuilt'
AND CONVERT(asfv.field_value,SIGNED) <= 2004 )
AND (asfv.field_name = 't1_sqft'
AND CONVERT(asfv.field_value,SIGNED) <= 50)
query return all adverts that belong on advert_type_id and price of them are less than 10.174.945,00 €.
All what I need is query update that return only adverts, for example t1_yearbuilt less than 2005 and t1_sqft less than 51 (advert_id => 654,656).
I also need query for values between for example t1_sqft >=30 AND t1_sqft <=50 (advert_id => 654).
Can anybody know how, update this query?
TNX