Mysql max date within a subquery - mysql

i cant work out how to get this subquery working to get the latest date for the row.
SELECT Thread_Heading.*, Thread_Articles.*, Thread_ArticlesPost.*
FROM Thread_Heading
LEFT JOIN Thread_Articles
ON Thread_Articles.Thread_Article_Head_id=Thread_Heading.Thread_Head_id
LEFT JOIN
(
SELECT Thread_ArticlesPost.*
FROM Thread_ArticlesPost
ORDER BY Thread_ArticlePost_DT DESC
) Thread_ArticlesPost
ON Thread_ArticlesPost.Thread_ArticlePost_Article_id=Thread_Articles.Thread_Article_id
WHERE Thread_Head_Level = '5'
GROUP BY Thread_Heading.Thread_Head_id
ORDER BY Thread_ArticlePost_DT DESC
I need to order the article post date by the latest post for each Thread article.
Fairly new to sql and php i just cant work this one out any help would be appreciated.
T
ABLE: Thread_Heading |
Thread_Head_id
Thread_Head_Name
Thread_Head_Type
Thread_Head_Creator
Thread_Head_Date
Thread_Head_Level
TABLE: Thread_Articles |
Thread_Article_id
Thread_Article_Head_id
Thread_Article_Creator
Thread_Article_DT
Thread_Article_Level
Thread_Article_Type
Thread_Article_Title
TABLE: Thread_ArticlesPost |
Thread_ArticlePost_id
Thread_ArticlePost_Head_id
Thread_ArticlePost_Article_id
Thread_ArticlePost_Creator
Thread_ArticlePost_DT
Thread_ArticlePost_Level
Thread_ArticlePost_Type
Thread_ArticlePost_Title
Thread_ArticlePost_Content
I need to display the date like so:
Head Name | Article title | ORDER BY LATEST ArticlePost DT | ArticlePost Creator
The reason i used left joins was to get the left data even if there are no article or article replys.
Appreciate the help.
Have used this to display data Thanks to Blue
SELECT *
FROM
( SELECT th.Thread_Head_Name,
ta.,
tp1.maxdate,
tp2.
FROM Thread_Heading th
LEFT JOIN Thread_Articles ta
ON th.Thread_Head_id = ta.Thread_Article_Head_id
LEFT JOIN
(
SELECT max(Thread_ArticlePost_DT) maxDate,
Thread_ArticlesPost.*
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) tp1
ON tp1.Thread_ArticlePost_Article_id=ta.Thread_Article_id
LEFT JOIN Thread_ArticlesPost tp2
ON tp1.Thread_ArticlePost_Article_id = tp2.Thread_ArticlePost_Article_id
AND tp1.maxdate = tp2.Thread_ArticlePost_DT
WHERE th.Thread_Head_Level = '5'
ORDER BY tp1.maxdate DESC) m
GROUP BY Thread_Head_Name
ORDER BY Thread_ArticlePost_DT DESC

Without seeing your full table schemas you will want do something similar to this:
SELECT th.*, ta.*, tp.*
FROM Thread_Heading th
LEFT JOIN Thread_Articles ta
ON th.Thread_Head_id = ta.Thread_Article_Head_id
LEFT JOIN
(
SELECT max(Thread_ArticlePost_DT) maxDate, Thread_ArticlesPost.*
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) Thread_ArticlesPost tp
ON tp.Thread_ArticlePost_Article_id=ta.Thread_Article_id
WHERE Thread_Head_Level = '5'
GROUP BY th.Thread_Head_id
ORDER BY tp.maxdate DESC
Based on your edit the following should return the data you want:
SELECT th.Thread_Head_Name,
ta.Thread_Article_Title,
tp1.maxdate,
tp2.Thread_ArticlePost_Creator
FROM Thread_Heading th
LEFT JOIN Thread_Articles ta
ON th.Thread_Head_id = ta.Thread_Article_Head_id
LEFT JOIN
(
SELECT max(Thread_ArticlePost_DT) maxDate,
Thread_ArticlesPost.Thread_ArticlePost_Article_id
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) tp1
ON tp1.Thread_ArticlePost_Article_id=ta.Thread_Article_id
LEFT JOIN Thread_ArticlesPost tp2
ON tp1.Thread_ArticlePost_Article_id = tp2.Thread_ArticlePost_Article_id
AND tp1.maxdate = tp2.Thread_ArticlePost_DT
WHERE th.Thread_Head_Level = '5'
ORDER BY tp1.maxdate DESC
Edit #2, based on your comments, I think the below query should resolve any remaining issues:
SELECT th.Thread_Head_id,
th.Thread_Head_Name,
ta.Thread_Article_Title,
tp.Thread_ArticlePost_Creator,
tap.MaxPostDate
FROM Thread_Heading th
LEFT JOIN
(
SELECT max(ta.Thread_Article_DT) MaxArticleDate,
ta.Thread_Article_Head_id,
max(tp.Thread_ArticlePost_DT) MaxPostDate
FROM Thread_Articles ta
LEFT JOIN Thread_ArticlesPost tp
ON ta.Thread_Article_id = tp.Thread_ArticlePost_Article_id
GROUP BY Thread_Article_Head_id
) tap
ON th.Thread_Head_id = tap.Thread_Article_Head_id
LEFT JOIN Thread_Articles ta
ON tap.Thread_Article_Head_id = ta.Thread_Article_Head_id
AND tap.MaxArticleDate = ta.Thread_Article_DT
LEFT JOIN Thread_ArticlesPost tp
ON tap.MaxPostDate = tp.Thread_ArticlePost_DT
WHERE th.Thread_Head_Level = '5'
ORDER BY MaxPostDate desc
See SQL Fiddle With Demo

You don't have to have a GROUP BY clause outside side your post are already grouped on the subquery based on your latest post. Try this one,
SELECT a.*, b.*, c.*
FROM Thread_Heading a
LEFT JOIN Thread_Articles b
ON b.Thread_Article_Head_id = a.Thread_Head_id
LEFT JOIN Thread_ArticlesPost c
ON c.Thread_ArticlePost_Article_id = b.Thread_Article_id
LEFT JOIN
(
SELECT Thread_ArticlePost_Article_id, MAX(Thread_ArticlePost_DT) maxDate
FROM Thread_ArticlesPost
GROUP BY Thread_ArticlePost_Article_id
) d ON d.Thread_ArticlePost_Article_id = b.Thread_Article_id AND
c.Thread_ArticlePost_DT = d.maxDate
WHERE Thread_Head_Level = '5'
-- GROUP BY a.Thread_Head_id
ORDER BY Thread_ArticlePost_DT DESC

Related

group and order in mysql

I have to write a query in which I need the given output.
I tried different queries but didn't work.
Actual data :
and I need Output like :
Queries like :
SELECT VCD.id,VCD.effective_date, `VCD`.`charge_id`, `C`.`head`,
`VCD`.`per`, `VCD`.`currency`, `VCD`.`amount`, `VCD`.`remarks`
FROM `vendor_charge` `VC` INNER JOIN `vendor_charge_details` `VCD`
ON `VC`.`id` = `VCD`.`vc_id` LEFT JOIN `charges` `C`
ON `C`.`id` = `VCD`.`charge_id`
WHERE `VC`.`vendor_id` = '12' AND `VCD`.`effective_date` <= '2018-05-22'
GROUP BY `VCD`.`charge_id`, `VCD`.`per`, `VCD`.`currency`
ORDER BY `C`.`head` DESC
and
SELECT VCD.id,VCD.effective_date, `VCD`.`charge_id`, `C`.`head`,
`VCD`.`per`, `VCD`.`currency`, `VCD`.`amount`, `VCD`.`remarks`
FROM `vendor_charge` `VC` INNER JOIN `vendor_charge_details` `VCD`
ON `VC`.`id` = `VCD`.`vc_id` LEFT JOIN `charges` `C`
ON `C`.`id` = `VCD`.`charge_id`
WHERE `VC`.`vendor_id` = '12' AND `VCD`.`effective_date` <= '2018-05-22'
GROUP BY `VCD`.`charge_id`, `VCD`.`per`, `VCD`.`currency`
ORDER BY `VCD`.`effective_date` DESC
I think all you need here is an additional join to a subquery which finds the latest effective_date for each charge_id:
SELECT
VCD.id,
VCD.effective_date,
VCD.charge_id,
C.head,
VC.per,
VCD.currency,
VCD.amount,
VCD.remarks
FROM vendor_charge VC
INNER JOIN vendor_charge_details VCD
ON VC.id = VCD.vc_id
INNER JOIN
(
SELECT charge_id, MAX(effective_date) AS max_effective_date
FROM vendor_charge_details
GROUP BY charge_id
) t
ON VCD.charge_id = t.charge_id AND VCD.effective_date = t.max_effective_date
LEFT JOIN charges C
ON C.id = VCD.charge_id
WHERE VC.vendor_id = '12' AND VCD.effective_date <= '2018-05-22'
ORDER BY
C.head DESC;

Combine query that relies on resultset of another

I run this query to get 20 random items from my wordpress database based on things like rating, category, etc
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY RAND()
LIMIT 20
Then, for each result of the random items, I want to find a corresponding item that is very similar to the random item (around the same rating) but not identical and also one the user has not seen:
SELECT ABS($site_rating-(A.user_votes/A.user_voters)) as diff, (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category ,IFNULL(F.count,0) as count
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
LEFT JOIN (
SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as F ON (A.post_id = F.post_id_winner OR A.post_id = F.post_id_loser)
WHERE
E.name = '$category' AND
B.ID <> '$post_id' AND
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY count ASC, diff ASC
LIMIT 1
Where the following php variables refer to the result of the previous query
$post_id = $result['post_id'];
$category = $result['category'];
$site_rating = $result['site_rating'];
and $_SERVER['REMOTE_ADDR'] refers to the user's IP.
Is there a way to combine the first query with the 20 additional queries that need to be called to find corresponding items, so that I need just 1 or 2 queries?
Edit: Here is the view that simplifies the joins
CREATE VIEW `versus_random` AS
SELECT (A.user_votes/A.user_voters) as site_rating, B.ID as post_id, B.post_author, B.post_date,E.name as category
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
My attempt now with the view:
SELECT post_id,
(
SELECT INNER_TABLE.post_id
FROM `versus_random` as INNER_TABLE
WHERE
INNER_TABLE.post_id <> OUTER_TABLE.post_id
ORDER BY (SELECT COUNT(*) FROM `versus` WHERE ip = '54' AND (INNER_TABLE.post_id = post_id_winner OR INNER_TABLE.post_id = post_id_loser)) ASC
LIMIT 1
) as innerquery
FROM `versus_random` as OUTER_TABLE
ORDER BY RAND()
LIMIT 20
However the query just timesout and freezes my mysql.
I think it should work like this, but I don't have any Wordpress at hand to test it. The second query that gets the related post is embedded in the other query, when it gets just the related_post_id. The whole query is turned into a subquery itself, given the alias 'X' (although you are free to use 'G', if you want to continue your alphabet.)
In the outer query, the tables for posts and data-article are joined again (RA and RP) to query the relevant fields of the related post, based on the related_post_id from the inner query. These two tables are left joined (and in reverse order), so you still get the main post if no related post was found.
SELECT
X.site_rating,
X.post_id,
X.post_author,
X.post_date,
X.category,
RA.user_votes / RA.user_voters as related_post_site_rating,
RP.ID as related_post_id,
RP.post_author as related_post_author,
RP.post_date as related_post_date,
RP.name as related_category,
FROM
( SELECT
(A.user_votes/A.user_voters) as site_rating,
B.ID as post_id, B.post_author, B.post_date,E.name as category,
( SELECT
RB.ID as post_id
FROM `wp_gdsr_data_article` as RA
INNER JOIN `wp_posts` as RB ON (RA.post_id = RB.id)
INNER JOIN wp_term_relationships RC ON (RB.ID = RC.object_id)
INNER JOIN wp_term_taxonomy RD ON (RC.term_taxonomy_id = RD.term_taxonomy_id)
INNER JOIN wp_terms RE ON (RD.term_id = RE.term_id)
LEFT JOIN (
SELECT *,COUNT(*) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as RF ON (RA.post_id = RF.post_id_winner OR RA.post_id = RF.post_id_loser)
WHERE
RE.name = E.name AND
RB.ID <> B.ID AND
RB.post_type = 'post' AND
RB.post_status = 'publish' AND
RD.taxonomy='category' AND
RE.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY count ASC, diff ASC
LIMIT 1) as related_post_id
FROM `wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
ORDER BY RAND()
LIMIT 20
) X
LEFT JOIN `wp_posts` as RP ON RP.id = X.related_post_id
LEFT JOIN `wp_gdsr_data_article` as RA.post_id = RP.id
I can't test my proposal so take it with the benefit of the doubt. Anyway i hope it could be a valid starting point for some of the issues faced.
I can not imagine a solution that does not pass through a temporary table, cabling onerous computations present in your queries. You could also have the goal to not interfere with the randomization of the first phase. In the following I try to clarify.
I'll start with these rewritings:
-- first query
SELECT site_rating, post_id, post_author, post_date, category
FROM POSTS_COMMON
ORDER BY RAND()
LIMIT 20
-- second query
SELECT ABS(R.site_rating_A - R.site_rating_B) as diff, R.site_rating_B as site_rating, P.post_id, P.post_author, P.post_date, P.category, F.count
FROM POSTS_COMMON AS P
INNER JOIN POSTS_RATING_DIFFS AS R ON (P.post_id = R.post_id_B)
LEFT JOIN (
/* post_id_winner, post_id_loser explicited; COUNT(*) NULL treatment anticipated */
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count FROM `verus` WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as F ON (P.post_id = F.post_id_winner OR P.post_id = F.post_id_loser)
WHERE
P.category = '$category'
AND R.post_id_A = '$post_id'
ORDER BY count ASC, diff ASC
LIMIT 1
with:
SELECT A.post_id_A, B.post_id_B, A.site_rating as site_rating_A, B.site_rating as site_rating_B
INTO POSTS_RATING_DIFFS
FROM POSTS_COMMON as A, POSTS_COMMON as B
WHERE A.post_id <> B.post_id AND A.category = B.category
CREATE VIEW POSTS_COMMON AS
SELECT A.ID as post_id, A.user_votes, A.user_voters, (A.user_votes / A.user_voters) as site_rating, B.post_author, B.post_date, E.name as category
FROM wp_gdsr_data_article` as A
INNER JOIN `wp_posts` as B ON (A.post_id = B.post_id)
INNER JOIN wp_term_relationships C ON (B.ID = C.object_id)
INNER JOIN wp_term_taxonomy D ON (C.term_taxonomy_id = D.term_taxonomy_id)
INNER JOIN wp_terms E ON (D.term_id = E.term_id)
WHERE
B.post_type = 'post' AND
B.post_status = 'publish' AND
D.taxonomy='category' AND
E.name NOT IN ('Satire', 'Declined', 'Outfits','Unorganized', 'AP')
POSTS_COMMON isolates a common view between the two queries.
With POSTS_RATING_DIFFS, a temporary table populated with the ratings combinations and diffs, we have "the trick" of transforming the inequality join criteria on post_id(s) in an equality one (see R.post_id_A = '$post_id' in the second query).
We also take advantage of a temporary table in having precomputed ratings for the combinatory explosion of A.post_id <> B.post_id (with post category equality), and moreover being useful for other sessions.
Also extracting the RAND() ordering in a temporary table could be advantageous. In this case we could limit the ratings combinations and diffs only on the 20 randomly chosen.
Original limiting to one single row in the dependent second level query is done by mean of ordering and limit statements.
The proposed solution avoids elaborating a LIMIT 1 on an ORDER BY resultset in the second level query wich become a subquery.
The single row calculation in the subquery is done by mean of a WHERE criteria on the maximum of a single value calculated from the columns values on which ORDER BY clause is used.
The combination into a single value must be valid in preserving the correct ordering. I'll leave in pseudo-code as:
'<combination of count and diff>'
For example, using combination of the two values into a string type, we could have:
CONCAT(LPAD(CAST(count AS CHAR), 10, '0'), LPAD(CAST(ABS(diff) AS CHAR), 20, '0'))
The structure of the single query would be:
SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1
, Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1
, Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2
, Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2
, Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2
, Q_LVL_2.count
FROM POSTS_COMMON AS Q_LVL_1
, /* 1-row-selection query placed side by side for each Q_LVL_1's row */
(
SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count
FROM POSTS_COMMON AS P
INNER JOIN (
SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_P.count
FROM (
/*
selection of posts with post_id(s) different from first level query,
not already taken and with the topmost value of
'<combination of count and diff>'
*/
) AS CORE_P
GROUP BY CORE_P.count, ABS(CORE_P.diff)
/* the one row selector */
) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id
) AS Q_LVL_2
ORDER BY RAND()
LIMIT 20
CORE_P selection could have more post_id(s) corresponding to the topmost value '<combination of count and diff>', so the use of GROUP BY and FIRST clauses to reach the single row.
This brings to a possible final implementation:
SELECT (Q_LVL_1.user_votes/Q_LVL_1.user_voters) as site_rating_LVL_1, Q_LVL_1.post_id as post_id_LVL_1
, Q_LVL_1.post_author as post_author_LVL_1, Q_LVL_1.post_date as post_date_LVL_1
, Q_LVL_1.category as category_LVL_1, Q_LVL_2.post_id as post_id_LVL_2
, Q_LVL_2.diff as diff_LVL_2, Q_LVL_2.site_rating as site_rating_LVL_2
, Q_LVL_2.post_author as post_author_LVL_2, Q_LVL_2.post_date as post_date_LVL_2
, Q_LVL_2.count
FROM POSTS_COMMON AS Q_LVL_1
, (
SELECT CORE_P.post_id, CORE_P.ABS_diff as diff, P.site_rating, P.post_author, P.post_date, CORE_P.count
FROM POSTS_COMMON AS P
INNER JOIN
(
SELECT FIRST(CORE_P.post_id) as post_id, ABS(CORE_P.diff) as ABS_diff, CORE_F.count
FROM (
SELECT CORE_RATING.post_id as post_id, ABS(CORE_RATING.diff) as ABS_diff, CORE_F.count
FROM (
SELECT post_id_B as post_id, site_rating_A - site_rating_B as diff
FROM POSTS_RATING_DIFFS
WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
) as CORE_RATING
LEFT JOIN (
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count
FROM `verus`
WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as CORE_F ON (CORE_RATING.post_id = CORE_F.post_id_winner OR CORE_RATING.post_id = CORE_F.post_id_loser)
WHERE
POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
AND '<combination of CORE_F.count and CORE_RATING.diff>'
= MAX (
SELECT '<combination of CORE_F_2.count and CORE_RATING_2.diff>'
FROM (
SELECT site_rating_A - site_rating_B as diff
FROM POSTS_RATING_DIFFS
WHERE POSTS_RATING_DIFFS.post_id_A = Q_LVL_1.post_id
) as CORE_RATING_2
LEFT JOIN (
SELECT post_id_winner, post_id_loser, IFNULL(COUNT(*), 0) as count
FROM `verus`
WHERE ip = '{$_SERVER['REMOTE_ADDR']}'
) as CORE_F_2 ON (CORE_RATING_2.post_id = CORE_F_2.post_id_winner OR CORE_RATING_2.post_id = CORE_F_2.post_id_loser)
) /* END MAX */
) AS CORE_P
GROUP BY CORE_P.count, ABS(CORE_P.diff)
) AS CORE_ONE_LINER ON P.post_id = CORE_ONE_LINER.post_id
) AS Q_LVL_2
ORDER BY RAND()
LIMIT 20

Complex mysql query probably build subquery

In my case, I have data from multiple tables that I want to extract a single query. It's about football statistics. In one minute table recorded the dates of the matches and the other recorded data and results of the matches.
The problem is that I want to limit the applications of dates, not the number of matches, as in a day has a few games.
Managed to build a complex query that displays all my data, but it displays the results on the number of games rather than the dates so I can not use limitation, because eating in this case becomes more games rather than dates.
My question is is it possible to build an application that has a limitation on the dates and at the same time to display the results of all matches played in the dates?
Here is the code of the application that I use now:
SELECT
MAIN.id,
SECTION.type,
MAIN.date as date_,
MAIN.prognosis,
HOME_TEAM.team_name as home_team,
GUEST_TEAM.team_name as guest_team,
FIRST_INDEX.index as f_index,
SECOND_INDEX.index as s_index,
THIRD_INDEX.index as t_index,
DATA.home_result,
DATA.guest_result,
DATA.coefficient,
DATA.success,
MAIN.total_coefficient,
MAIN.total_success
FROM ssdt_matches_main as MAIN
LEFT JOIN ssdt_section_type as SECTION ON (MAIN.type_id = SECTION.id)
LEFT JOIN ssdt_matches_data as DATA ON (DATA.matches_main_id = MAIN.id )
LEFT JOIN ssdt_matches_teams as HOME_TEAM ON (HOME_TEAM.id = DATA.home_team_id )
LEFT JOIN ssdt_matches_teams as GUEST_TEAM ON (GUEST_TEAM.id = DATA.guest_team_id )
LEFT JOIN ssdt_matches_index as FIRST_INDEX ON (FIRST_INDEX.id = DATA.first_index_id )
LEFT JOIN ssdt_matches_index as SECOND_INDEX ON (SECOND_INDEX.id = DATA.second_index_id )
LEFT JOIN ssdt_matches_index as THIRD_INDEX ON (THIRD_INDEX.id = DATA.third_index_id )
WHERE SECTION.type = 'Risk prognosis'
ORDER BY MAIN.id DESC
You want to limit the dates in a where clause like:
where MAIN.date between date('2012-01-01') and date('2012-12-31');
If you want to get the records from, say, the most recent 10 days (with a match), you can do something like this:
select . . .
from . . . join
(select date
from ssdt_matches_main md
group by date
order by date desc
limit 10
) datel
on datel.date = MAIN.date
This uses a join to select a list of dates and then a join to do the filtering.
EDIT:
Your from clause would look like:
FROM ssdt_matches_main as MAIN
LEFT JOIN ssdt_section_type as SECTION ON (MAIN.type_id = SECTION.id)
LEFT JOIN ssdt_matches_data as DATA ON (DATA.matches_main_id = MAIN.id )
LEFT JOIN ssdt_matches_teams as HOME_TEAM ON (HOME_TEAM.id = DATA.home_team_id )
LEFT JOIN ssdt_matches_teams as GUEST_TEAM ON (GUEST_TEAM.id = DATA.guest_team_id )
LEFT JOIN ssdt_matches_index as FIRST_INDEX ON (FIRST_INDEX.id = DATA.first_index_id )
LEFT JOIN ssdt_matches_index as SECOND_INDEX ON (SECOND_INDEX.id = DATA.second_index_id )
LEFT JOIN ssdt_matches_index as THIRD_INDEX ON (THIRD_INDEX.id = DATA.third_index_id )
join (select date
from ssdt_matches_main md
group by date
order by date desc
limit 10
) datel
on datel.date = MAIN.date
I fixed the query.
I would not have done it without your help.
Thank you very much!
SELECT
MAIN.id,
SECTION.type,
MAIN.date as date_,
MAIN.prognosis,
HOME_TEAM.team_name as home_team,
GUEST_TEAM.team_name as guest_team,
FIRST_INDEX.index as f_index,
SECOND_INDEX.index as s_index,
THIRD_INDEX.index as t_index,
DATA.home_result,
DATA.guest_result,
DATA.coefficient,
DATA.success,
MAIN.total_coefficient,
MAIN.total_success
FROM ssdt_matches_main as MAIN
LEFT JOIN ssdt_section_type as SECTION ON (MAIN.type_id = SECTION.id)
LEFT JOIN ssdt_matches_data as DATA ON (DATA.matches_main_id = MAIN.id )
LEFT JOIN ssdt_matches_teams as HOME_TEAM ON (HOME_TEAM.id = DATA.home_team_id )
LEFT JOIN ssdt_matches_teams as GUEST_TEAM ON (GUEST_TEAM.id = DATA.guest_team_id )
LEFT JOIN ssdt_matches_index as FIRST_INDEX ON (FIRST_INDEX.id = DATA.first_index_id )
LEFT JOIN ssdt_matches_index as SECOND_INDEX ON (SECOND_INDEX.id = DATA.second_index_id )
LEFT JOIN ssdt_matches_index as THIRD_INDEX ON (THIRD_INDEX.id = DATA.third_index_id )
JOIN (SELECT id
FROM ssdt_matches_main md
WHERE type_id = 2
ORDER BY id DESC
LIMIT 0,5
) datel
ON datel.id = DATA.matches_main_id
ORDER BY MAIN.id DESC

How do I optimize this mysql query with nested joins?

Below is my query which I need to optimize.
SELECT
UPPER(IFNULL(op.supplier_payment_method,s.default_payment_method)) AS Payment_Method,
op.supplier_payment_date AS Payment_Date,
Date_format(IFNULL(op.supplier_payment_date,op.ship_date),'%M %Y') AS Payment_Month,
s.supplier_name AS Farm,
op.sub_order_id AS Order_num,
Date_format(op.ship_date,'%b-%d-%Y') AS Ship_Date,
op.farm_credit AS Farm_Credit,
op.credit_memo AS Credit_Memo,
op.credit_description AS Credit_Description,
opb.boxes AS Box_Type,
CONCAT('$',FORMAT(op.box_charge,2)) AS Box_Charge,
op.invoice_num AS Invoice_num,
CONCAT('$',FORMAT(op.invoice_amt,2)) AS Invoice_Amt,
CONCAT('$',FORMAT(op.total_invoice_amt,2)) AS Total_Invoice_Amt,
CONCAT(op.UM_qty,' ',op.UM_type) AS St_Bu_Qty,
op.PO_Product_Name AS Invoice_desc,
CONCAT('$',FORMAT((op.price_um*op.um_qty),2)) AS Cost_product_cms,
op.supplier_invoice_note AS Supplier_Invoice_Notes,
CONCAT('$',FORMAT(op.cms_invoice_cost,2)) AS CMS_Invoice_diff,
CONCAT('$',FORMAT(op.total_farm_cost,2)) AS Farm_Cost
FROM
orders_products op
INNER JOIN
suppliers s ON s.supplier_id = op.supplier_name
LEFT JOIN
(
SELECT
sub_order_id,
GROUP_CONCAT(CONCAT(box_type_qty,' ',bo.box_option_name) SEPARATOR ', ') AS boxes
FROM
order_products_boxes opb
INNER JOIN box_options bo ON bo.id=opb.box_type_id
GROUP BY
opb.sub_order_id
) opb ON opb.sub_order_id = op.sub_order_id
WHERE
op.order_active=0
AND op.ship_date>='2013-03-01'
AND op.ship_date<='2013-04_01'
ORDER BY op.ship_date DESC
As you can see, the query comprises of 4 tables, each containing around 20k-30k rows each. So as soon as I add in the sub-query, the query becomes exceptionally slow. It takes approx 1.5mins to fetch just 500 rows of record. Is there a way to speed things up within a single query?
Your left-join query that pre-concatenates the sub-box options is querying the ENTIRE DATABASE FIRST, then only joins to those that are within the criteria you are limiting for the outer WHERE clause. It may be a little more effort, but pull the same outer criteria into your inner query should significantly help. As for doing a field-level sql-select on a per-every-row basis could be a performance killer.
You should only need to change at the "FROM" clause...
from
orders_products op
INNER JOIN suppliers s
ON op.supplier_name = s.supplier_id
LEFT JOIN
( SELECT
opb2.sub_order_id,
GROUP_CONCAT(CONCAT(box_type_qty,' ',bo.box_option_name) SEPARATOR ', ') AS boxes
FROM
orders_products op2
JOIN order_products_boxes opb2
on op2.sub_order_id = opb2.sub_order_id
INNER JOIN box_options bo
ON opb2.box_type_id = bo.id
WHERE
op2.order_active = 0
AND op2.ship_date >= '2013-03-01'
AND op2.ship_date <= '2013-04_01'
GROUP BY
opb2.sub_order_id ) opb
ON op.sub_order_id = opb.sub_order_id
WHERE
op.order_active = 0
AND op.ship_date >= '2013-03-01'
AND op.ship_date <= '2013-04_01'
SELECT
UPPER(IFNULL(op.supplier_payment_method,s.default_payment_method)) AS Payment_Method,
op.supplier_payment_date AS Payment_Date,
Date_format(IFNULL(op.supplier_payment_date,op.ship_date),'%M %Y') AS Payment_Month,
s.supplier_name AS Farm,
op.sub_order_id AS Order_num,
Date_format(op.ship_date,'%b-%d-%Y') AS Ship_Date,
op.farm_credit AS Farm_Credit,
op.credit_memo AS Credit_Memo,
op.credit_description AS Credit_Description,
(
SELECT
GROUP_CONCAT(CONCAT(box_type_qty,' ',bo.box_option_name) SEPARATOR ', ')
FROM
order_products_boxes opb
INNER JOIN box_options bo ON bo.id=opb.box_type_id
GROUP BY
opb.sub_order_id
) AS Box_Type,
CONCAT('$',FORMAT(op.box_charge,2)) AS Box_Charge,
op.invoice_num AS Invoice_num,
CONCAT('$',FORMAT(op.invoice_amt,2)) AS Invoice_Amt,
CONCAT('$',FORMAT(op.total_invoice_amt,2)) AS Total_Invoice_Amt,
CONCAT(op.UM_qty,' ',op.UM_type) AS St_Bu_Qty,
op.PO_Product_Name AS Invoice_desc,
CONCAT('$',FORMAT((op.price_um*op.um_qty),2)) AS Cost_product_cms,
op.supplier_invoice_note AS Supplier_Invoice_Notes,
CONCAT('$',FORMAT(op.cms_invoice_cost,2)) AS CMS_Invoice_diff,
CONCAT('$',FORMAT(op.total_farm_cost,2)) AS Farm_Cost
FROM
orders_products op
INNER JOIN
suppliers s ON s.supplier_id = op.supplier_name
LEFT JOIN
order_products_boxes opb (
INNER JOIN box_options bo ON bo.id=opb.box_type_id
) opb ON opb.sub_order_id = op.sub_order_id
WHERE
op.order_active=0
AND op.ship_date>='2013-03-01'
AND op.ship_date<='2013-04_01'
ORDER BY op.ship_date DESC

SQL Query Problem

I've been at this for a bit now. Basically, I'm needing to add a derived column to count the hits to a weblog entry in the database. The problem is, the hits are being totaled and shown on only on the first record. Any Ideas? I've emboldened the parts of the query I'm talking about. The query is below:
SELECT DISTINCT(t.entry_id),
exp_categories.rank,
**exp_hits.hits,**
t.entry_id,
t.weblog_id,
t.forum_topic_id,
t.author_id,
t.ip_address,
t.title,
t.url_title,
t.status,
t.dst_enabled,
t.view_count_one,
t.view_count_two,
t.view_count_three,
t.view_count_four,
t.allow_comments,
t.comment_expiration_date,
t.allow_trackbacks,
t.sticky,
t.entry_date,
t.year,
t.month,
t.day,
t.entry_date,
t.edit_date,
t.expiration_date,
t.recent_comment_date,
t.comment_total,
t.trackback_total,
t.sent_trackbacks,
t.recent_trackback_date,
t.site_id as entry_site_id,
w.blog_title,
w.blog_name,
w.search_results_url,
w.search_excerpt,
w.blog_url,
w.comment_url,
w.tb_return_url,
w.comment_moderate,
w.weblog_html_formatting,
w.weblog_allow_img_urls,
w.weblog_auto_link_urls,
w.enable_trackbacks,
w.trackback_use_url_title,
w.trackback_field,
w.trackback_use_captcha,
w.trackback_system_enabled,
m.username,
m.email,
m.url,
m.screen_name,
m.location,
m.occupation,
m.interests,
m.aol_im,
m.yahoo_im,
m.msn_im,
m.icq,
m.signature,
m.sig_img_filename,
m.sig_img_width,
m.sig_img_height,
m.avatar_filename,
m.avatar_width,
m.avatar_height,
m.photo_filename,
m.photo_width,
m.photo_height,
m.group_id,
m.member_id,
m.bday_d,
m.bday_m,
m.bday_y,
m.bio,
md.*,
wd.*
FROM exp_weblog_titles AS t
LEFT JOIN exp_weblogs AS w ON t.weblog_id = w.weblog_id
LEFT JOIN exp_weblog_data AS wd ON t.entry_id = wd.entry_id
LEFT JOIN exp_members AS m ON m.member_id = t.author_id
LEFT JOIN exp_member_data AS md ON md.member_id = m.member_id
LEFT JOIN exp_category_posts ON wd.entry_id = exp_category_posts.entry_id
**LEFT JOIN
(
SELECT COUNT(*) AS hits, exp_hits.entry_id FROM exp_hits ORDER BY exp_hits.entry_id
) exp_hits ON t.entry_id = exp_hits.entry_id**
LEFT JOIN
(
SELECT exp_categories.cat_id, cat_name as rank
FROM exp_categories
WHERE exp_categories.group_id = '9'
) exp_categories ON exp_categories.cat_id = exp_category_posts.cat_id
WHERE t.entry_id IN (2,3,4) ORDER BY exp_categories.rank DESC, **exp_hits.hits DESC**, entry_date desc
Try changeing the subselect to
SELECT COUNT(*) AS hits,
exp_hits.entry_id
FROM exp_hits
GROUP BY exp_hits.entry_id
Out of curiosity, is your hits functionality something that can't be accomplished with the view_count_one/two/three/four fields already present in the database and supported by ExpressionEngine template tags?