MySQL aggregation query - mysql

I am currently trying to aggregate the people who visited a sports facility and how much it cost them.
I have run the following code successfully but need to aggregate the people.
How can I do that.
The tables used for the code is here
Tables
SELECT CONCAT( members.firstname, " ", members.surname ) AS fullname,
CASE WHEN slots >0
THEN (
bookings.slots * facilities.membercost + bookings.slots * facilities.guestcost
)
ELSE NULL
END AS "cost"
FROM `Bookings` AS bookings
LEFT JOIN `Members` AS members ON bookings.memid = members.memid
LEFT JOIN Facilities AS facilities ON bookings.facid = facilities.facid
WHERE bookings.starttime LIKE '2012-09-14%'
AND (
bookings.slots * facilities.membercost + bookings.slots * facilities.guestcost
) >30
ORDER BY 1 DESC
OutputScreenshot

I got throught with this....
Here is my solution:
SELECT CONCAT (members.firstname," ",members.surname) AS fullname,
SUM(bookings.slots*facilities.membercost + bookings.slots*facilities.guestcost) AS cost
FROM `Bookings` AS bookings
LEFT JOIN `Members` AS members
ON bookings.memid = members.memid
LEFT JOIN Facilities as facilities
ON bookings.facid =facilities.facid
WHERE bookings.starttime LIKE '2012-09-14%' AND (bookings.slots*facilities.membercost + bookings.slots*facilities.guestcost) >30
GROUP BY 1
ORDER BY 2 DESC

Related

Slow query performance in MySQL

I would like to find out what causes the slow execution of my MySQL query here. It's 1 row fetched in 0.0017s (3.6215s) How can i optimize this?
SELECT hadmlog.hpercode as 'HOSPITAL NUMBER', FLOOR (hadmlog.patage) as 'AGE', CONCAT (hperson.patlast, ', ', hperson.patfirst, ' ',hperson.patmiddle) as 'PROFILE', hcity.ctyname as 'DISTRICT', hadmlog.disdate as 'DISCHARGED DATE'
FROM hadmlog
INNER JOIN hperson ON hadmlog.hpercode=hperson.hpercode
INNER JOIN haddr ON hadmlog.hpercode=haddr.hpercode
INNER JOIN hcity ON haddr.ctycode=hcity.ctycode
WHERE hadmlog.patage BETWEEN '1' AND '4'
AND hperson.patsex = 'M'
AND DATE(hadmlog.disdate) = DATE(curdate())
AND haddr.haddrdte = ( select max(haddrdte)
from haddr
where haddr.hpercode = hperson.hpercode )
ORDER BY Profile;
First, fix the query:
SELECT al.hpercode as HOSPITAL_NUMBER, FLOOR(al.patage) as AGE,
CONCAT_WS(' ', p.patlast, p.patfirst, p.patmiddle) as PROFILE,
c.ctyname as DISTRICT, al.disdate as DISCHARGED_DATE
FROM hadmlog al JOIN
hperson p
ON al.hpercode = p.hpercode JOIN
haddr a
ON al.hpercode = a.hpercode JOIN
hcity c
ON a.ctycode = c.ctycode
WHERE al.patage BETWEEN 1 AND 4 AND
p.patsex = 'M' AND
al.disdate >= curdate() AND
al.disdate < curdate() + INTERVAL 1 day AND
a.haddrdte = (select max(h2.haddrdte)
from haddr h2
where h2.hpercode = p.hpercode
)
ORDER BY Profile;
Some of the changes are cosmetic (such as the table aliases and CONCAT_WS()). The more relevant changes are:
patage appears to be a number, so make the comparisons numbers. Strings can impede the optimizer.
date(disdate) can also impede the optimizer.
Then, for this query, I am guessing that you want an indexes:
hadmlog(disdate, patage)
And then you want indexes on the JOIN keys used for the other tables.

How to use grouping by XXX, and using aggregate funtion correctly? WITH MIN VALUES

I am trying to fetch records from 4 tables by using joins. These tables are rates, carriers, depots and margin. I am able to get the records that needed from this 4 table, but when I am using a group by and aggregate function (MIN), my min sell column is correct, however, the other data such as carrierID, depotID and ratesID are different.
I have OriginType (OT) and DestinatioType (DT)and there are 2 cases for each; Depot and Door. So when I group them, I get four options as (services):
Depot To Depot
Depot To Door
Door To Depot
Door To Door
I am trying to fetch the min(rates) as 'Sell' for each of these service and display it. The Sell is calculated as:
autoRate table as A has a column Buy, carrier, OT, DT, Origin (Value: Canberra), Destination (Value: Melbourne) and Car (Value :4WD/Van)
Left Join with carriers as C with A.carrier = C.ID
C.Fuellevy column as Percentage ((C.FuelLevy * A.buy) + C.FuelLevy) as EQ1
((EQ1 * 10%) + EQ1) as EQ2
EQ2 price for each row with have a Margin table Percentage. For example, if the EQ2 value is 400, then It will look in the Margin table, find the range (low and high as 350(low) and 500(high)) and its percentage is 25%, so ((EQ2 * 25%)+ EQ2) gives the sell value.
I am not too sure how to upload my data and database table here, so I tried to explain here what I want.
the query I build is:-
Select Depo.*, DL.id as DepoID, DL.carrier as CarNo, DL.depotCity, DL.depoSuburb, min(Depo.Sell) as sellcost , Depo.OriginType as OT From (
Select Mar.*, M.MarginPer, round((eq2 * M.MarginPer) + eq2)as Sell From (
Select GST.* , EQ1 as 'FinalEQ1' , round((EQ1 * .10) + EQ1,2) as eq2 From (
Select A.ID as RateID, A.Origin, A.OriginState, A.Destination, A.DestinationState, A.Carrier as RateCarrier, A.Car as CarType, A.Buy as Buy, A.OriginType, A.DestinationType ,
C.ID as CarrierID, C.Carrier, C.FuelLevy , round((A.buy * C.FuelLevy) + A.Buy, 2) As EQ1,
CONCAT(A.OriginType, ' to ' ,A.DestinationType ) as service,
D.id as DepoID, D.carrier as CarNo, D.depotCity, D.depoSuburb
from carrier C
left join autorates A on A.carrier = C.ID
left join dList D on D.carrier = C.ID
where A.origin = 'Canberra' and A.destination = 'Melbourne' and A.car = '4WD/Van' AND D.carrier = A.carrier AND A.goodsAllowed = 0
AND C.Disabled = 0
AND D.depotCity = 'Canberra'
order by EQ1
) As GST
order by eq2
) As Mar
Left Join margin M on Mar.eq2 >= M.low and Mar.eq2 <= M.high
order by Sell
) As Depo
Left Join dList DL on DL.Carrier = Depo.RateCarrier
Where DL.depotCity = 'Melbourne'
group by OT
order by sellcost
Results before the Group by and MIN():-
As we see the sellcost value 412 and the carNo is 51 here
And in this screenshot, the carrierno has changed, but the the MIN value remains the same.
I Just managed the get query. This will Work as I have tested on my SQL-WB
SELECT DepoD.*, DL2.id, DL2.carrier AS a, DL2.depotCity
, DL2.depoSuburb AS 'PickupSub', MIN(Sell) AS sellcost
FROM (
SELECT Depo.*, DL.id AS DepoID, DL.carrier AS CarNo, DL.depotCity, DL.depoSuburb AS 'PickupSub'
, DL.depoSuburb AS 'DestSub', MIN(Sell) AS sellcost, Depo.OriginType AS OT
FROM (
SELECT Mar.*, M.MarginPer, MIN(round((eq2 * M.MarginPer) + eq2)) AS Sell
FROM (
SELECT GST.*, EQ1 AS 'FinalEQ1', MIN(round((EQ1 * .10) + EQ1, 2)) AS eq2
FROM (
SELECT A.ID AS RateID, A.Origin, A.OriginState, A.Destination, A.DestinationState
, A.Carrier AS RateCarrier, A.Car AS CarType, A.Buy AS Buy, A.OriginType
, A.DestinationType, C.ID AS CarrierID, C.Carrier, C.FuelLevy
, round((A.buy * C.FuelLevy) + A.Buy, 2) AS EQ1
, CONCAT(A.OriginType, ' to ', A.DestinationType ) AS service
FROM carrier C
LEFT JOIN autorates A ON A.carrier = C.ID
WHERE A.origin = 'Melbourne'
AND A.destination = 'Canberra'
AND A.car = '4WD/Van'
AND A.goodsAllowed = 0
AND C.Disabled = 0
ORDER BY EQ1 ASC
) AS GST
GROUP BY service, CarrierID
ORDER BY eq2
) AS Mar
LEFT JOIN margin M ON Mar.eq2 >= M.low AND Mar.eq2 <= M.high
GROUP BY service
ORDER BY Sell
) AS Depo
LEFT JOIN dList AS DL ON DL.Carrier = Depo.RateCarrier
WHERE DL.depotCity IN('Melbourne', 'Canberra')
GROUP BY carrier, service
ORDER BY sellcost
) AS DepoD
LEFT JOIN dList DL2 ON DL2.Carrier = DepoD.RateCarrier
WHERE DL2.depotCity IN('Melbourne', 'Canberra')
GROUP BY carrier, service
ORDER BY sellcost
NOTE: Not a final answer, but a query to test and see if this part works. If so, I'll provide the rest of the query.
If you break the problem down, I think what you have to do is to identify the lowest Sell for each combination of OriginType and DestinationType. Then join to the tables to get the matching rows.
The query below doesn't get all of the detail info, but it should get the rows with the lowest Sell value. If it works, then I can add to the query to get the other, matching data.
One aspect that question is the use of LEFT JOIN. That might include rows that do not match up with the ON clauses, essentially adding columns with null values. This might impact performance, and using just a JOIN might work better. If you test this and it works as stated below, run it again without the LEFT that is in front of each of the JOIN clauses. If you get the same results, let me know in the comments.
Give it a try and see if you get the four values for each of the combinations of OriginType and DestinationType. If it does, I'll update the answer with the rest of the query.
SELECT
A.OriginType,
A.DestinationType,
round(A.buy * (1.0 + C.FuelLevy), 2) AS EQ1,
round(round(A.buy * (1.0 + C.FuelLevy), 2) * 1.10, 2) AS eq2,
MIN(round((eq2 * (1.0 + M.MarginPer)))) AS Sell
FROM carrier C
LEFT JOIN autorates A
ON A.carrier = C.ID
LEFT JOIN dList D
ON D.carrier = A.carrier
LEFT JOIN margin M
ON round(round(A.buy * (1.0 + C.FuelLevy), 2) * 1.10, 2) BETWEEN M.low AND M.high
WHERE A.origin = 'Canberra'
AND A.destination = 'Melbourne'
AND A.car = '4WD/Van'
AND A.goodsAllowed = 0
AND C.Disabled = 0
AND D.depotCity = 'Canberra'
GROUP BY LOWER(A.OriginType), LOWER(A.DestinationType)
ORDER BY Sell

MySQL Find Most Recent/Largest Record Per Group by order by

MySQL Find Most Recent/Largest Record Per Group by order by, and how can i minimize / shorten this query and every time it returns the first row value of the group, whereas i like to select the last row value of a group, and sort the values based on ja.id ? I know this is a bad query can anyone suggest or provide me solution to shorten this query . I have used all the necessary Column Indexes in all the tables. How to shorten the query without the use of union all .both the queries in union all are same expect in the where statement.
SELECT
a.previous_status,
a.rejected_status,
a.rejection_reason_text,
a.rejection_reason,
a.rjaId,
a.refer_applied_status,
a.title,
a.playerId,
a.gameId,
a.gamePostDate,
a.game_referal_amount,
a.country,
a.country_name,
a.state,
a.location,
a.state_abb,
a.game_type,
a.appliedId,
a.appliedStatus,
a.admin_review,
a.is_req_referal_check,
a.memberId,
a.appliedEmail,
a.game_id,
a.referred_id,
a.memStateAbb,
a.memState,
a.memZipcode,
a.memCity,
a.memCountryNme,
a.memCountry,
a.appliedMemberName,
a.first_name,
a.primary_contact,
a.last_name,
a.addressbookImage,
a.userImage,
a.last_login,
a.user_experience_year,
a.user_experience_month,
a.current_designation,
a.current_player,
a.appliedDate,
a.addressbook_id,
a.joiningdate,
a.gameStatus,
a.gameReferalAmountType,
a.gameFreezeStatus,
a.gameFreezeMsg,
a.app_assign_back_to_rp_count,
a.applied_source,
a.max_id,
a.gamesApplied,
a.gamesAppliedId,
SUM(a.totalgameApplied) AS totalgameApplied,
a.application_assign_to_rp_status,
a.rpAppliedSource,
a.applied_on
FROM
(
(
SELECT
ja.previous_status,
ja.rejected_status,
ja.rejection_reason_text,
ja.rejection_reason,
rja.id AS rjaId,
rja. STATUS AS refer_applied_status,
jp.title,
jp.user_user_id AS playerId,
jp.id AS gameId,
jp.posted_on AS gamePostDate,
jp.game_referal_amount,
jp.country,
jp.country_name,
jp.state,
jp.location,
jp.state_abb,
jp.game_type,
ja.id AS appliedId,
IFNULL(ja. STATUS, '') AS appliedStatus,
IFNULL(ja.admin_review, '') AS admin_review,
ja.is_req_referal_check,
usr.id AS memberId,
rja.email AS appliedEmail,
rja.game_id,
rja.referred_id,
mem.state_abb AS memStateAbb,
mem.state AS memState,
mem.zipcode AS memZipcode,
mem.city AS memCity,
mem.country_name AS memCountryNme,
mem.country_code AS memCountry,
usc. NAME AS appliedMemberName,
usc.first_name,
IFNULL(
mem.primary_contact,
usc.phone_number
) AS primary_contact,
usc.last_name,
usc.profileimage_path AS addressbookImage,
usr.profile_image AS userImage,
usr.last_login,
mem.user_experience_year,
mem.user_experience_month,
mem.current_designation,
mem.current_player,
rja.create_date AS appliedDate,
rja.addressbook_id,
IFNULL(ja.joining_date, '') AS joiningdate,
jp. STATUS AS gameStatus,
jp.games_referal_amount_type AS gameReferalAmountType,
jp.game_freeze_status AS gameFreezeStatus,
jp.game_freeze_message AS gameFreezeMsg,
ja.app_assign_back_to_rp_count,
ja.applied_source,
MAX(rja.id) AS max_id,
GROUP_CONCAT(
jp.title
ORDER BY
rja.create_date DESC
) AS gamesApplied,
GROUP_CONCAT(DISTINCT(jp.id)) AS gamesAppliedId,
COUNT(DISTINCT(jp.id)) totalgameApplied,
ja.application_assign_to_rp_status,
1 AS rpAppliedSource,
rja.create_date AS applied_on
FROM
(`refer_gameapplied` AS rja)
JOIN `games_post` AS jp ON `jp`.`id` = `rja`.`game_id`
JOIN `user_socialconnections` AS usc ON `rja`.`addressbook_id` = `usc`.`id`
LEFT JOIN `user_user` AS usr ON `usr`.`email` = `rja`.`email`
LEFT JOIN `user_member` AS mem ON `mem`.`user_id` = `usr`.`id`
LEFT JOIN `game_applied` AS ja ON `ja`.`id` = `rja`.`applied_id`
WHERE
`rja`.`referby_id` = '2389'
GROUP BY
`rja`.`email`
)
UNION ALL
(
SELECT
ja.previous_status,
ja.rejected_status,
ja.rejection_reason_text,
ja.rejection_reason,
jr.id AS rjaId,
jrtm. STATUS AS refer_applied_status,
jp.title,
jp.user_user_id AS playerId,
jp.id AS gameId,
jp.posted_on AS gamePostDate,
jp.game_referal_amount,
jp.country,
jp.country_name,
jp.state,
jp.location,
jp.state_abb,
jp.game_type,
ja.id AS appliedId,
IFNULL(ja. STATUS, '') AS appliedStatus,
IFNULL(ja.admin_review, '') AS admin_review,
ja.is_req_referal_check,
usr.id AS memberId,
jrtm.referto_email AS refappliedEmail,
jr.game_id,
jrtm.id,
mem.state_abb AS memStateAbb,
mem.state AS memState,
mem.zipcode AS memZipcode,
mem.city AS memCity,
mem.country_name AS memCountryNme,
mem.country_code AS memCountry,
usc. NAME AS appliedMemberName,
usc.first_name,
IFNULL(
mem.primary_contact,
usc.phone_number
) AS primary_contact,
usc.last_name,
usc.profileimage_path AS addressbookImage,
usr.profile_image AS userImage,
usr.last_login,
mem.user_experience_year,
mem.user_experience_month,
mem.current_designation,
mem.current_player,
jrtm.refer_on AS appliedDate,
jrtm.referto_addressbookid,
IFNULL(ja.joining_date, '') AS joiningdate,
jp. STATUS AS gameStatus,
jp.games_referal_amount_type AS gameReferalAmountType,
jp.game_freeze_status AS gameFreezeStatus,
jp.game_freeze_message AS gameFreezeMsg,
ja.app_assign_back_to_rp_count,
ja.applied_source,
MAX(jrtm.id) AS max_id,
GROUP_CONCAT(
jp.title
ORDER BY
jr.refer_on DESC
) AS gamesApplied,
GROUP_CONCAT(DISTINCT(jp.id)) AS gamesAppliedId,
COUNT(DISTINCT(jp.id)) totalgameApplied,
ja.application_assign_to_rp_status,
2 AS rpAppliedSource,
jrtm.refer_on AS applied_on
FROM
(`game_refer` AS jr)
JOIN `game_refer_to_member` AS jrtm ON `jrtm`.`rid` = `jr`.`id`
JOIN `games_post` AS jp ON `jp`.`id` = `jr`.`game_id`
JOIN `user_socialconnections` AS usc ON `jrtm`.`referto_addressbookid` = `usc`.`id`
LEFT JOIN `user_user` AS usr ON `usr`.`email` = `jrtm`.`referto_email`
LEFT JOIN `user_member` AS mem ON `mem`.`user_id` = `usr`.`id`
LEFT JOIN `game_applied` AS ja ON `ja`.`referred_by` = `jrtm`.`id`
WHERE
`jrtm`.`status` = '1'
AND `jr`.`referby_user_id` = '2389'
AND `jrtm`.`refer_source` NOT IN ('4')
GROUP BY
`jrtm`.`referto_email`
)
) a
GROUP BY
a.appliedEmail
ORDER BY
a.gamesAppliedId DESC
It sounds like a "groupwise-max" problem. I added a tag that you should research.
At least get rid of the columns that are not relevant to the question.
Try tossing the tables other than jrtm and jr to see if the performance problem persists. (I'm thinking that the LEFT JOINs may be red herrings.)
Try with one part of the UNION, then with the other. This may identify which of the two is more of a burden.
Some indexes to add:
rja: (referby_id, create_date)
jrtm: (status, referto_email)
jrtm: (rid, status, referto_email)
jr: (referby_user_id, refer_on)
DISTINCT is not a function. Don't use parents in DISTINCT(jp.id).

mysql big query optimization

I'd need to optimize the following query which takes up to 10 minutes to run.
Performing the explain it seems to be running on all 350815 rows of the "table_3" table and 1 for all the others.
General rules to place indexes the propper way? Should I think about using multidimensional indexes? Where should I use them at first on the JOINS, the WHERE or the GROUP BY, if I remember right there should be a hierarchy to follow. Also If I have 1 row for all tables but one (in the row column of the explain table) how can I optimize usually my optimization consists in ending up with only one row for all columns but one.
All tables average from 100k to 1000k+ rows.
CREATE TABLE datab1.sku_performance
SELECT
table1.sku,
CONCAT(table1.sku,' ',table1.fk_container ) as sku_container,
table1.price as price,
SUM( CASE WHEN ( table1.fk_table1_status = 82
OR table1.fk_table1_status = 119
OR table1.fk_table1_status = 124
OR table1.fk_table1_status = 141
OR table1.fk_table1_status = 131) THEN 1 ELSE 0 END)
/ COUNT( DISTINCT id_catalog_school_class) as qty_returned,
SUM( CASE WHEN ( table1.fk_table1_status In (23,13,44,65,6,75,8,171,12,166))
THEN 1 ELSE 0 END)
/ COUNT( DISTINCT id_catalog_school_class) as qt,
container.id_container as container_id,
container.idden as container_idden,
container.delivery_badge,
catalog_school.id_catalog_school,
LEFT(catalog_school.flight_fair,2) as departing_country,
catalog_school.weight,
catalog_school.flight_type,
catalog_school.price,
table_3.id_table_3,
table_3.fk_catalog_brand,
MAX( LEFT( table_3.note,3 )) AS supplier,
GROUP_CONCAT( product_number, ' by ',FORMAT(catalog_school_class.quantity,0)
ORDER BY product_number ASC SEPARATOR ' + ') as supplier_prod,
Sum( distinct( catalog_school_class.purch_pri * catalog_school_class.quantity)) AS final_purch_pri,
catalog_groupp.idden as supplier_idden,
catalog_category_details.id_catalog_category,
catalog_category_details.cat1 as product_cat1,
catalog_category_details.cat2 as product_cat2,
COUNT( distinct catalog_school_class.id_catalog_school_class) as setinfo,
datab1.pageviewgrouped.pv as page_views,
Sum(distinct(catalog_school_class.purch_pri * catalog_school_class.quantity)) AS purch_pri,
container_has_table_3.position,
max( table1.created_at ) as last_order_date
FROM
table1
LEFT JOIN container
ON table1.fk_container = container.id_container
LEFT JOIN catalog_school
ON table1.sku = catalog_school.sku
LEFT JOIN table_3
ON catalog_school.fk_table_3 = table_3.id_table_3
LEFT JOIN container_has_table_3
ON table_3.id_table_3 = container_has_table_3.fk_table_3
LEFT JOIN datab1.pageviewgrouped
on table_3.id_table_3 = datab1.pageviewgrouped.url
LEFT JOIN datab1.catalog_category_details
ON datab1.catalog_category_details.id_catalog_category = table_3_has_catalog_minority.fk_catalog_category
LEFT JOIN catalog_groupp
ON table_3.fk_catalog_groupp = catalog_groupp.id_catalog_groupp
LEFT JOIN table_3_has_catalog_minority
ON table_3.id_table_3 = table_3_has_catalog_minority.fk_table_3
LEFT JOIN catalog_school_class
ON catalog_school.id_catalog_school = catalog_school_class.fk_catalog_school
WHERE
table_3.status_ok = 1
AND catalog_school.status = 'active'
AND table_3_has_catalog_minority.is_primary = '1'
GROUP BY
table1.sku,
table1.fk_container;
rows per table :
.table1 960096 to 1.3mn rows
.container 9275 to 13000 rows
.catalog_school 709970 to 1 mn rows
.table_3 709970 to 1 mn rows
.container_has_table_3 709970 to 1 mn rows
.pageviewgrouped 500000 rows
.catalog_school_class 709970 to 1 mn rows
.catalog_groupp 3000 rows
.table_3_has_catalog_minority 709970 to 1 mn rows
.catalog_category_details 659 rows
Too much to put into a single comment, so I'll add here and adjust later as possibly needed... You have LEFT JOINs everywhere, but your WHERE clause is specifically qualifying fields from the Table_3, Catalog_School and Table_3_has_catalog_minority. This by default changes them to INNER JOINs.
With respect to your where clause
WHERE
table_3.status_ok = 1
AND catalog_school.status = 'active'
AND table_3_has_catalog_minority.is_primary = '1'
Which table / column would have the smallest results based on these criteria. ex: Table_3.Status_ok = 1 might have 500k records but table_3_has_catalog_minority.is_primary may only have 65k and catalog_school.status = 'active' may have 430k.
Also, some of your columns are not qualified with the table they are coming from. Can you please confirm... such as "id_catalog_school_class" and "product_number"
SOMETIMES, changing the order of the tables, with good knowledge of the makeup of the data and in MySQL adding a "STRAIGHT_JOIN" keyword can improve performance. This was something I've had in the past working with gov't database of contracts and grants with 20+ million records and joining to about 15+ lookup tables. It went from hanging the server to getting the query finished in less than 2 hrs. Considering the amount of data I was dealing with, that was actually a good time.
AFTER dissecting this thing some, I restructured a bit more for readability, added aliases for table references and changed the order of the query and have some suggested indexes. To help the query, I tried moving the Catalog_School table to the first position and added the STRAIGHT_JOIN. The index is based on the STATUS first to match the WHERE clause, THEN I included the SKU as it is first element of the GROUP BY, then the other columns used to join to the subsequent tables. By having these columns in the index, it can qualify the joins without having to go to the raw data.
By changing the group by to the Catalog_School.SKU instead of table_1.SKU the index from catalog_school can be used to help optimize that. It is the same value since the join from the catalog_school.sku = table_1.sku. I also added index references for table_1 and table_3 that are suggestions -- again, to preemptively qualify the joins without going to the raw data pages of the tables.
I would be interested in knowing the final performance (better or worse) from your data.
TABLE INDEX ON...
catalog_school ( status, sku, fk_table_3, id_catalog_school )
table_1 ( sku, fk_container )
table_3 ( id_table_3, status_ok, fk_catalog_groupp )
SELECT STRAIGHT_JOIN
CS.sku,
CONCAT(CS.sku,' ',T1.fk_container ) as sku_container,
T1.price as price,
SUM( CASE WHEN ( T1.fk_table1_status IN ( 82, 119, 124, 141, 131)
THEN 1 ELSE 0 END)
/ COUNT( DISTINCT CSC.id_catalog_school_class) as qty_returned,
SUM( CASE WHEN ( T1.fk_table1_status In (23,13,44,65,6,75,8,171,12,166))
THEN 1 ELSE 0 END)
/ COUNT( DISTINCT CSC.id_catalog_school_class) as qt,
CS.id_catalog_school,
LEFT(CS.flight_fair,2) as departing_country,
CS.weight,
CS.flight_type,
CS.price,
T3.id_table_3,
T3.fk_catalog_brand,
MAX( LEFT( T3.note,3 )) AS supplier,
C.id_container as container_id,
C.idden as container_idden,
C.delivery_badge,
GROUP_CONCAT( product_number, ' by ',FORMAT(CSC.quantity,0)
ORDER BY product_number ASC SEPARATOR ' + ') as supplier_prod,
Sum( distinct( CSC.purch_pri * CSC.quantity)) AS final_purch_pri,
CGP.idden as supplier_idden,
CCD.id_catalog_category,
CCD.cat1 as product_cat1,
CCD.cat2 as product_cat2,
COUNT( distinct CSC.id_catalog_school_class) as setinfo,
PVG.pv as page_views,
Sum(distinct(CSC.purch_pri * CSC.quantity)) AS purch_pri,
CHT3.position,
max( T1.created_at ) as last_order_date
FROM
catalog_school CS
JOIN table1 T1
ON CS.sku = T1.sku
LEFT JOIN container C
ON T1.fk_container = C.id_container
LEFT JOIN catalog_school_class CSC
ON CS.id_catalog_school = CSC.fk_catalog_school
JOIN table_3 T3
ON CS.fk_table_3 = T3.id_table_3
JOIN table_3_has_catalog_minority T3HCM
ON T3.id_table_3 = T3HCM.fk_table_3
LEFT JOIN datab1.catalog_category_details CCD
ON T3HCM.fk_catalog_category = CCD.id_catalog_category
LEFT JOIN container_has_table_3 CHT3
ON T3.id_table_3 = CHT3.fk_table_3
LEFT JOIN datab1.pageviewgrouped PVG
on T3.id_table_3 = PVG.url
LEFT JOIN catalog_groupp CGP
ON T3.fk_catalog_groupp = CGP.id_catalog_groupp
WHERE
CS.status = 'active'
AND T3.status_ok = 1
AND T3HCM.is_primary = '1'
GROUP BY
CS.sku,
T1.fk_container;

MYSQL Select As Case when number of rows statement

I'm trying to find the number of notifications for each user, I am having a little problem, I had the query working perfect for what I needed it for, then I changed my table around just a little bit.
Working query:
$numNotifications = mysql_num_rows(mysql_query("
SELECT
N.*,
P.*
FROM
notifications N,
posts P
WHERE
N.userID='$session'
AND
(
N.action='1' OR N.action='2'
)
AND
N.uniqueID=P.id AND P.state='0'"
));
However, uniqueID is now different for some rows. when N.aciton is "1" then N.uniqueID should be compared to P.id, however when N.action is "2" it should compare a row in that table with P.id.
Example query, (that SHOULD work, but doesn't)
$numNotifications = mysql_num_rows(mysql_query("
SELECT
N.*,
P.*,
C.*,
(CASE WHEN (
N.action = 2 AND N.state = 0
)
THEN
C.postID ELSE N.uniqueID END
) AS postId
FROM
notifications N,
posts P,
comments C
WHERE
N.userID='$session'
AND
(
N.action='1' OR N.action='2'
)
AND
postId=P.id AND P.state='0'"
));
diagram of my 3 table structures:
http://i41.tinypic.com/nyzolg.png
here you go :)
SELECT
COUNT(`notif_id`) AS `number_of_new_notifications`
FROM
(
SELECT
`notifications`.`id` AS `notif_id`
FROM
`notifications`
JOIN
`posts`
ON
`notifications`.`uniqueID`=`posts`.`id`
WHERE
`notifications`.`userID`='$session'
AND
`notifications`.`action`=1
AND
`notifications`.`state`=0
AND
`posts`.`state`=0
UNION ALL
SELECT
`notifications`.`id` AS `notif_id`
FROM
`notifications`
JOIN
`comments`
ON
`notifications`.`uniqueID`=`comments`.`id`
JOIN
`posts`
ON
`comments`.`postID`=`posts`.`id`
WHERE
`notifications`.`userID`='$session'
AND
`notifications`.`action`=2
AND
`notifications`.`state`=0
AND
`comments`.`state`=0
AND
`posts`.`state`=0
) AS notification_ids;