SQL - Query multiple rooms with different Adults/Children per hotel - mysql

I have a simple query where I select available x Rooms with x Adults + x Children per hotel that matches a date range, but I'm having a hard time trying to figure out how to query a list of rooms per hotel like this:
1 Room with 2 Adults / 0 Children
1 Room with 4 Adults / 2 Children
1 Room with 2 Adults / 1 Children
Here is my query:
SELECT COUNT(pl.day) AS Days,
p.property_ID AS Hotel_ID,
p.name AS Hotel_Name,
r.room_name AS Room_Name,
r.room_type_ID AS Room_ID
FROM property p
INNER JOIN room_type r ON p.property_ID=r.property_ID
AND (r.max_adults >= 3
AND r.max_children >= 0)
INNER JOIN plan pl ON pl.room_type_ID=r.room_type_ID
AND (pl.day >= "2014-07-07"
AND pl.day <= "2014-07-11")
GROUP BY Room_ID,
Hotel_ID HAVING Days = 4
EDIT
How do I add 'No_of_Room' in SELECT that differentiates the room_types by the room number, example result of a single room:
Array
(
[Room_Price] => 160.00
[Days] => 4
[Hotel_ID] => 1
[Hotel_Name] => Hotel Alfa
[Room_Name] => Room type C
[Room_ID] => 3
[Max_Adults] => 3
[Max_Children] => 1
[No_of_Room] => 1 // What number of room does this room_type belongs to
)
Then I can show the results like:
EDIT
Rooms table
Rooms(
ID,
hotel_id
room_name,
max_Adults,
max_Children
);
-- Populate
INSERT INTO Rooms VALUES (1,1,"Room A",2,1),(2,1,"Room B",2,5),(3,1,"Room C",3,0);
INSERT INTO Rooms VALUES (1,2,"Room A",2,1),(2,2,"Room B",2,5),(3,3,"Room C",3,4);

EXAMPLES OF USING VIEWS TO MAKE THINGS NICER.
For this project authors may have aliases, for example one book may have "S. Lang" as the author, another might have "Serge Lang", the primary author is the main form (Serge Lang) and the secondaries are things like "S. Lang".
It is important to relate these, ideally I'd like a table with "AuthorId" and "PrimaryAuthorId" as columns, that way I could just select PrimaryAuthorId from it on AuthorId being equal to something.
To do this the view is defined as:
select
`BookSystem_AuthorList`.`AuthorId` AS `AuthorId`,
if((`BookSystem_AuthorList`.`duplicateOf` = 0),
`BookSystem_AuthorList`.`AuthorId`,
`BookSystem_AuthorList`.`duplicateOf`
) AS `PrimaryAuthorId`
from `BookSystem_AuthorList`;
Then
SELECT PrimaryAuthorId FROM BookSystem_PrimaryAuthorId WHERE AuthorId=10;
gives:
7
Which is much nicer for joining!
I then use this view to define another view (EditionAuthorsWithPrimaryId) - this gets the authors of an edition - and the primary author (I can then join to get names as needed)
select
`BookSystem_EditionAuthors`.`BindingId` AS `BindingId`,
`BookSystem_EditionAuthors`.`EditionId` AS `EditionId`,
`BookSystem_EditionAuthors`.`AuthorId` AS `AuthorId`,
`BookSystem_EditionAuthors`.`Position` AS `Position`,
(select
`BookSystem_PrimaryAuthorId`.`PrimaryAuthorId`
from `BookSystem_PrimaryAuthorId`
where (`BookSystem_PrimaryAuthorId`.`AuthorId` = `BookSystem_EditionAuthors`.`AuthorId`)
) AS `PrimaryAuthorId`
from `BookSystem_EditionAuthors`;
Now I can do:
SELECT * FROM BookSystem_EditionAuthorsWithPrimary WHERE EditionId=10;
BindingId, EditionId, AuthorId, Position, PrimaryAuthorId
10, 10, 10, 0, 7
Much nicer!
this next query is a great example
select
`BookSystem_BookList`.`BookId` AS `Id`,
`BookSystem_BookList`.`Title` AS `Name`,
`BookSystem_BookList`.`UserId` AS `UserId`,
`BookSystem_BookList`.`BookType` AS `Subtype`,
1 AS `IsBook`,0 AS `IsSeries`,
0 AS `IsAuthor`
from `BookSystem_BookList`
union
select
`BookSystem_SeriesList`.`SeriesId` AS `Id`,
`BookSystem_SeriesList`.`SeriesName` AS `Name`,
`BookSystem_SeriesList`.`UserId` AS `UserId`,
'' AS `Subtype`,
0 AS `IsBook`,
1 AS `IsSeries`,
0 AS `IsAuthor`
from `BookSystem_SeriesList`
union
select
`BookSystem_AuthorList`.`AuthorId` AS `Id`,
concat(
`BookSystem_AuthorList`.`AuthorSurname`,', ',`BookSystem_AuthorList`.`AuthorForename`,
ifnull(
(select concat(
' (AKA: ',
group_concat(
concat(
`BookSystem_AuthorList`.`AuthorSurname`,
', ',
`BookSystem_AuthorList`.`AuthorForename`
) separator '; '
),')'
) AS `AKA` from `BookSystem_AuthorList`
where
(`BookSystem_AuthorList`.`duplicateOf` = `Id`)
group by (`BookSystem_AuthorList`.`duplicateOf` = `Id`)
),'')) AS `Name`,
`BookSystem_AuthorList`.`UserId` AS `UserId`,
'' AS `SubType`,
0 AS `IsBook`,
0 AS `IsSeries`,
1 AS `IsAuthor`
from `BookSystem_AuthorList`
where (`BookSystem_AuthorList`.`duplicateOf` = 0) order by `Name`;
IS HUGE!
But now I can get all the things for UserId=1 easily:
mysql> SELECT * FROM BookSystem_Index WHERE UserId = 1;
+----+----------------------------------------+--------+-------------+--------+----------+----------+
| Id | Name | UserId | Subtype | IsBook | IsSeries | IsAuthor |
+----+----------------------------------------+--------+-------------+--------+----------+----------+
| 4 | A First Course in Calculus | 1 | Normal | 1 | 0 | 0 |
| 2 | A First Course in Real Analysis | 1 | Normal | 1 | 0 | 0 |
| 2 | Algebra | 1 | | 0 | 1 | 0 |
| 13 | Analysis II assignments | 1 | Assignments | 1 | 0 | 0 |
| 14 | Author Test | 1 | Normal | 1 | 0 | 0 |
| 8 | b, g | 1 | | 0 | 0 | 1 |
| 7 | b, g (AKA: t, lll; Teal, lll) | 1 | | 0 | 0 | 1 |
| 1 | Calculus of Several Variables | 1 | Normal | 1 | 0 | 0 |
| 4 | DuBois, Paul | 1 | | 0 | 0 | 1 |
| 1 | Lang, Serge (AKA: Lang, S. E. R. G. E) | 1 | | 0 | 0 | 1 |
| 5 | Linear Algebra | 1 | Normal | 1 | 0 | 0 |
| 3 | Morrey, C. B. | 1 | | 0 | 0 | 1 |
| 6 | MySQL | 1 | Normal | 1 | 0 | 0 |
| 7 | Principles of Mathematical Analysis | 1 | Normal | 1 | 0 | 0 |
| 2 | Protter, M. H. | 1 | | 0 | 0 | 1 |
| 5 | Rudin, Walter | 1 | | 0 | 0 | 1 |
| 10 | t | 1 | Normal | 1 | 0 | 0 |
| 3 | Test | 1 | | 0 | 1 | 0 |
| 12 | Test 1 | 1 | Normal | 1 | 0 | 0 |
| 11 | Test 4.4.2014 | 1 | Normal | 1 | 0 | 0 |
| 8 | Topology and Analysis | 1 | Normal | 1 | 0 | 0 |
| 3 | Undergraduate Algebra | 1 | Normal | 1 | 0 | 0 |
| 1 | Undergraduate Texts in Mathematics | 1 | | 0 | 1 | 0 |
| 9 | w | 1 | Normal | 1 | 0 | 0 |
+----+----------------------------------------+--------+-------------+--------+----------+----------+
24 rows in set (0.00 sec)
The optimiser sees the view properly, it wont generate the full view, it effectively substitutes the required selects.
(Taken from a testing DB, not production, hence weird names like "TESTING")

First, the room type selection needs to be framed correctly. The following join would probably work.
EDIT:
The query has been edited to return only properties with all three room types. It has also been joined with the plan table.
SELECT
COUNT(pl.day) AS Days,
p.property_ID AS Hotel_ID,
p.name AS Hotel_Name,
r.room_name AS Room_Name,
r.room_type_ID AS Room_ID,
r.max_adults as Max_Adults,
r.max_children as Max_Children
FROM property p
INNER JOIN room_type r
ON p.property_ID=r.property_ID
INNER JOIN plan pl
ON pl.room_type_ID=r.room_type_ID
AND (pl.day >= '2014-07-07' AND pl.day <= '2014-07-11')
WHERE EXISTS
(SELECT 1
FROM room_type r1
WHERE p.property_ID=r1.property_ID
AND r1.max_adults = 2 AND r1.max_children = 0)
AND EXISTS
(SELECT 1
FROM room_type r2
WHERE p2.property_ID=r2.property_ID
AND r2.max_adults = 4 AND r2.max_children = 2)
AND EXISTS
(SELECT 1
FROM room_type r3
WHERE P.PROPERTY_ID=R3.PROPERTY_ID
AND r3.max_adults = 2 AND r3.max_children = 1)
GROUP BY
p.property_ID,
p.name,
r.room_name,
r.room_type_ID,
r.max_adults,
r.max_children
HAVING
COUNT(pl.day) = 4;

Related

How can I group by latest dates and IDs, yet take into account all data from previous dates?

So my example table is like this -
I have a mysql version 5.7 database which I can connect to. Read-only rights.
My table goes like this:
human_id | dog_id | dog_bought_at | amount_paid_for_dog | purchase_place | buyer_has_criminal_past
1 | 1 | 27-12-2019 | 100 | Tokyo | 0
1 | 2 | 03-01-2020 | 200 | Moscow | 0
2 | 3 | 03-01-2020 | 200 | Los Angeles | 0
3 | 4 | 03-01-2020 | 50 | Washington | 0
3 | 3 | 05-01-2020 | 30 | Dallas | 0
4 | 2 | 06-01-2020 | 150 | Texas | 1
What I need to show is this:
dog_id | last_owner_id | total_amount_paid_for_dog | last_purchase_date | last_purchase_place
1 | 1 | 100 | 27-12-2019 | Tokyo
2 | 4 | 350 | 06-01-2020 | Moscow
3 | 3 | 230 | 05-01-2020 | Dallas
4 | 3 | 50 | 03-01-2020 | Washington
Last_purchase_place is shown only for those humans, which do not have criminal past.
what I have tried:
SELECT
e.dog_id
,MAX(e.human_id) last_owner_id
,SUM(e.amount_paid_for_dog) total_amount_paid_for_dog
,MAX(e.dog_bought_at) last_purchase_date
,e_filter.purchase_place last_purchase_place
FROM example e
LEFT JOIN (
SELECT
dog_id
,dog_bought_at
,purchase_place
,human_id
FROM example
WHERE buyer_has_criminal_past != 1
) e_filter ON e.dog_id = e_filter.dog_id AND e.dog_bought_at = e_filter.dog_bought_at
But I am stuck on the logic, that allows to sum up ALL amounts, yet filter out unneeded values.
This is my first question here, so if this is a duplicate or not well written, please say it. Any help appreciated.
SELECT e1.dog_id,
e1.human_id last_owner_id,
sq1.total_amount_paid_for_dog,
e1.dog_bought_at last_purchase_date,
e2.purchase_place last_purchase_place
FROM example e1
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at,
SUM(amount_paid_for_dog) total_amount_paid_for_dog
FROM example
GROUP BY dog_id ) sq1 ON e1.dog_id = sq1.dog_id
AND e1.dog_bought_at = sq1.dog_bought_at
LEFT JOIN example e2 ON e1.dog_id = e2.dog_id
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at
FROM example
WHERE buyer_has_criminal_past = 0
GROUP BY dog_id ) sq2 ON e2.dog_id = sq2.dog_id
AND e2.dog_bought_at = sq2.dog_bought_at
fiddle

Nested JOIN to create custom dynamic columns

I have a table veicoli (vehicles) like this:
-------------------------------
| ID | Modello | Targa |
-------------------------------
| 1 | IVECO | XA123WE |
-------------------------------
| 2 | IVECO | CF556XD |
-------------------------------
| 3 | FIAT | AS332ZZ |
-------------------------------
| 4 | GOLF | GF567YU |
-------------------------------
For each vehicle I have none, one or multiple revisioni_veicolo (revisions) (the one with bigger DateExpiring is the one I need to check if revision is still valid or not based on today date)
-------------------------------------------------------------------
| ID | veicoli_ID | DateExpiring | Pass_Success |
-------------------------------------------------------------------
| 1 | 1 | 2019-07-01 | 1
------------------------------------------------------------------
| 2 | 1 | 2020-10-01 | 0
-------------------------------------------------------------------
| 3 | 2 | 2019-11-25 | 1
-------------------------------------------------------------------
| 4 | 2 | 2018-10-20 | 1
-------------------------------------------------------------------
| 5 | 4 | 2017-10-20 | 1
-------------------------------------------------------------------
Based on my example above (today is 2019-10-29):
Vehicle: ID = 1 has a revision still active (2020-10-01) but not passed (Pass_success = 0)
Vehicle: ID = 2 has a revision still active (2019-11-25) and passed (Pass_success = 1)
Vehicle: ID = 3 has no revision yet
Vehicle: ID = 4 has revision, but no active revision (last expired on 2017-10-20) but the last one passed the check (Pass_success = 1)
What I need is to have 3 new custom columns created dynamically on my query result:
-------------------------------------------------------------------------------------------
| ID | Modello | Targa | RevisionPresent | RevisionStillActive | LastRevisionPassed |
-------------------------------------------------------------------------------------------
| 1 | IVECO | XA123WE | true | true | false
-------------------------------------------------------------------------------------------
| 2 | IVECO | CF556XD | true | true | true
-------------------------------------------------------------------------------------------
| 3 | FIAT | AS332ZZ | false | false | false
-------------------------------------------------------------------------------------------
| 4 | GOLF | GF567YU | true | false | true
-------------------------------------------------------------------------------------------
I tried to start with my old post: MYSQL INNER JOIN to get 3 types of result
But I'm very confused using nested JOIN
I tried starting a fiddle but i'm stuck on syntax error: http://sqlfiddle.com/#!9/3c70bf/2
You need a LEFT JOIN of the tables and conditional aggregation:
select v.ID, v.Modello, v.Targa,
max(r.DataScadenzaRevisione is not null) RevisionPresent,
coalesce(max(r.DataScadenzaRevisione >= current_date()), 0) RevisionStillActive,
max(case when r.DataScadenzaRevisione = g.maxdate then r.EsitoPositivo else 0 end) LastRevisionPassed
from veicoli v
left join revisioni_veicolo r on r.veicoli_ID = v.id
left join (
select veicoli_id, max(DataScadenzaRevisione) maxdate
from revisioni_veicolo
group by veicoli_id
) g on g.veicoli_ID = v.id
group by v.ID, v.Modello, v.Targa
See the demo.
Results:
| ID | Modello | Targa | RevisionPresent | RevisionStillActive | LastRevisionPassed |
| --- | ------- | ------- | --------------- | ------------------- | ------------------ |
| 1 | IVECO | XA123WE | 1 | 1 | 0 |
| 2 | IVECO | CF556XD | 1 | 1 | 1 |
| 3 | FIAT | AS332ZZ | 0 | 0 | 0 |
| 4 | GOLF | GF567YU | 1 | 0 | 1 |
...
LEFT JOIN (SELECT a.veicoli_ID, a.EsitoPositivo AS StatoUltimaRevisione,
a.DataScadenzaRevisione FROM revisioni_veicolo) a
...
There's two things wrong with this.
The alias a is defined for this subquery, so you can't reference it inside the subquery. But you don't need to qualify the columns in this subquery anyway - you didn't do this in other subqueries, so I'm not sure why you did it in this case.
You don't have any join condition for this join. MySQL is a little bit inconsistent about when join conditions are required. But in this case, you need one.
After I tested the query with these two corrections, it works.
Basically you just need to look at the last revision of each vehicule to produce that resultset.
You can do the filtering with a correlated subquery:
select
v.ID,
v.Modello,
v.Targa,
(DataScadenzaRevisione >= now()) RevisionPresent,
(DataScadenzaRevisione >= now() and EsitoPositivo = 1) RevisionStillActive,
(EsitoPositivo = 1) LastRevisionPassed
from
veicoli v
left join revisioni_veicolo r
on r.veicoli_ID = v.ID
and r.DataScadenzaRevisione = (
select max(DataScadenzaRevisione)
from revisioni_veicolo r1
where r1.veicoli_ID = v.ID
)
You can check the results with your sample data in this db fiddle.
Or you can use a window function (this requires MySQL 8.0):
select
v.ID,
v.Modello,
v.Targa,
(DataScadenzaRevisione >= now()) RevisionPresent,
(DataScadenzaRevisione >= now() and EsitoPositivo = 1) RevisionStillActive,
(EsitoPositivo = 1) LastRevisionPassed
from (
select
v.*,
r.*,
row_number() over(partition by ID order by r.DataScadenzaRevisione desc) rn
from veicoli v
left join revisioni_veicolo r on r.veicoli_ID = v.ID
) where coaelesce(rn, 1) = 1

Joining and nesting queries in mysql

Currently, I'm using this nice query:
select
users.name,
sum(race_results.winnings) as total_winnings,
count(CASE WHEN race_results.place=1 THEN 1 ELSE 0 END) AS times_won_first_place
from users
inner join race_results
where race_results.userid = users.id and race_results.place = 1
group by users.id
order by total_winnings desc
to get this
************************************************
| name | total_winnings | times_won_first_place |
| Bob | 4000 | 4 |
| John | 1000 | 1 |
************************************************
the race_results table looks like this
*******************************************
| id | raceid | userid | place | winnings |
| 1 | 1 | 1 | 1 | 1000 |
| 2 | 1 | 2 | 5 | 50 |
| 3 | 1 | 3 | 6 | 50 |
| 4 | 2 | 1 | 1 | 1000 |
| 5 | 2 | 2 | 3 | 250 |
*******************************************
I would like to include four three more columns for something like this
***************************************************************************
| name | total_winnings | total_races | 1st_place | 2nd_place | 3rd_place |
| Bob | 4000 | 5 | 4 | 0 | 0 |
| John | 1000 | 5 | 1 | 1 | 1 |
***************************************************************************
If I were to do separate queries for the new columns, I'd use
select count(raceid) from race_results where userid = 1
select count(raceid) from race_results where userid = 1 and place = 1
select count(raceid) from race_results where userid = 1 and place = 2
select count(raceid) from race_results where userid = 1 and place = 3
to do separate queries would be easy but with the existing query I had to use CASE just to get the count of times a user won 1st place. (using
count(CASE WHEN race_results.place=2 THEN 1 ELSE 0 END)
returns the same results).
How would I nest these or join them into my existing query to get what I want?
You can do it this way:
select
users.name,
sum(race_results.winnings) as total_winnings,
count(*) AS total_races,
sum(race_results.place = 1) AS times_won_first_place ,
sum(race_results.place = 2) AS times_won_second_place,
sum(race_results.place = 3) AS times_won_third_place
from users
inner join race_results
where race_results.userid = users.id
group by users.id
order by total_winnings desc;
With ANSI standard SQL you could use case expressions inside the sum function but since MySQL (and some other databases) evaluate boolean expressions to 1 for true you can replace the case expression with the just the condition to evaluate and then just sum them.
So instead of CASE WHEN race_results.place=1 THEN 1 ELSE 0 END you can do sum(race_results.place=1) and save some space and typing :)
See this SQL Fiddle for an example.

Group by - Need to display on single row

I have the following schema setup :
table name : thing
Column | type
----------------------------
id | auto increment int
ident | int
cost1 | int
cost2 | int
cost3 | int
table name : thing_usage
column | type
---------------------------------
id | auto increment int
thing | int - FK to thing.id
usage_type | int
data | int
duration | int
with some data :
thing :
id | ident | cost1 | cost2 | cost3
------------------------------------------------
1 | 1234 | 1 | 2 | 3
2 | 5678 | 0 | 0 | 0
thing_usage :
id | thing | usage_type | data | duration
--------------------------------------------------------
1 | 1 | 1 | 5555 | 0
2 | 1 | 1 | 3 | 0
3 | 1 | 2 | 0 | 123
4 | 1 | 3 | 232 | 12
All available here -> SQLFiddle
What I would like to output if a single row for each thing like this :
thing | cost1 | usage1 | cost2 | usage2 | cost3 | usage3
------------------------------------------------------------------------
1 | 1 | 5558 | 2 | 00:02:03 | 3 | 232
2 | 0 | 0 | 0 | 0 | 0 | 0
cost1 uses usage_type of 1, cost2 uses usage_type of 2 and so on ...... and cost1 and cost3 use data for its usage and cost2 converts duration from seconds to hh:mm:ss for usage - usage should be summed
At the moment i have to create 2 queries and so this in code - so i loop all thing rows then get the usage for it and output accordingly
Is there any way that I can get the desired output from a single query - perhaps using a subquery of some kind?
Hopefully this is what you were looking for:
SELECT thing_usage1.id
,thing.id
,thing.cost1
,SUM(thing_usage1.data) AS usage1
,thing.cost2
,TIME_FORMAT(SEC_TO_TIME(thing_usage2.duration),'%H:%i:%s') AS usage2
,thing.cost3
,SUM(thing_usage3.data) AS usage3
FROM thing AS thing
INNER JOIN thing_usage AS thing_usage1 ON thing.id = thing_usage1.thing
AND thing.cost1 = thing_usage1.usage_type
INNER JOIN thing_usage AS thing_usage2 ON thing.id = thing_usage2.thing
AND thing.cost2 = thing_usage2.usage_type
INNER JOIN thing_usage AS thing_usage3 ON thing.id = thing_usage3.thing
AND thing.cost3 = thing_usage3.usage_type
GROUP BY thing_usage1.id
,thing.id
,thing.cost1
,thing.cost2
,thing.cost3
Here is an example of it working: http://sqlfiddle.com/#!2/68f430/51
Updated my logic to account for the SUMming piece, as well as the use of duration.
If you want to do it "manually" here is something to get you started:
SELECT
th.ident,
th.cost1,
SUM(tu.data) as usage1data
FROM
thing th
JOIN thing_usage tu
ON th.id = tu.thing
WHERE tu.usage_type = 1
GROUP BY th.id, tu.usage_type
And this query should get you going on collecting all sums in one statement:
SELECT
tu.thing,
SUM(CASE WHEN usage_type=1 THEN tu.data ELSE 0 END) AS usage1,
SUM(CASE WHEN usage_type=2 THEN tu.data ELSE 0 END) AS usage2,
SUM(CASE WHEN usage_type=3 THEN tu.data ELSE 0 END) AS usage3
FROM
thing_usage tu

MySQL Nested SQL with limits

I know it's not possible to use limits within nested INs, but I think there is a way to do this, I'm just not sure how.
I have a table that contains both ratings and comments (simplified for explanation)
mySingleTable:
+----+------------------+-----------+-----------+-----------------+
| id | reviewer_comment | is_rating | parent_id | reviewer_rating |
+----+------------------+-----------+-----------+-----------------+
| 1 | well done rateA | 1 | 0 | 5 Stars |
| 2 | commentAonRateA | 0 | 1 | |
| 3 | commentBonRateA | 0 | 1 | |
| 4 | commentConRateA | 0 | 1 | |
| 5 | commentDonRateA | 0 | 1 | |
| 6 | commentEonRateA | 0 | 1 | |
| 7 | commentFonRateA | 0 | 1 | |
| 8 | well done rateB | 1 | 0 | 4 Stars |
| 9 | well done rateC | 1 | 0 | 5 Stars |
| 11 | well done rateD | 1 | 0 | 3 Stars |
| 12 | well done rateE | 1 | 0 | 2 Stars |
| 13 | well done rateF | 1 | 0 | 5 Stars |
| 14 | well done rateG | 1 | 0 | 3 Stars |
| 15 | commentAonRateD | 0 | 11 | |
+----+------------------+-----------+-----------+-----------------+
So,
if is_rating = 1, its a rating.
if is_rating = 0, its a comment on the rating (its parent rating is where parent_id=id)
so this would look like:
well done rateA *****
commentAonRateA
commentBonRateA
commentConRateA
commentDonRateA
commentEonRateA
commentFonRateA
well done rateB ****
well done rateC *****
well done rateD ***
commentAonRateD
well done rateE **
well done rateF *****
well done rateG ***
What I want to do is select the newest five ratings, with the ASSOCIATED newest 5 comments, using only 1 query
So, some how join these two:
SELECT ratings.*
FROM mySingleTable as ratings
WHERE
is_rating = 1
ORDER BY timestamp DESC LIMIT 0, 5
SELECT comments.*
FROM mySingleTable as comments
Where
comments.parent_id = ratings.id
AND is_rating = 0
ORDER BY timestamp DESC LIMIT 0, 5
The 2nd query needs to somehow know about the ratings query
Please try this query which is now simplified and tested.
SELECT *
FROM
(SELECT *,
IF (group_id = #prev,
#n := #n + 1,
#n := 1 AND #prev := group_id) as position
FROM (
SELECT mySingleTable.*, group_id
FROM mySingleTable
INNER JOIN
(SELECT id AS group_id
FROM mySingleTable
WHERE is_rating = 1
ORDER BY timestamp DESC LIMIT 0, 5
) AS top5ratings
ON mySingleTable.id = group_id OR mySingleTable.parent_id = group_id
ORDER BY group_id DESC,
mySingleTable.parent_id ASC,
timestamp DESC) AS all_reviews
JOIN (SELECT #n := 0, #prev := 0) AS setup) AS reviews
WHERE reviews.position < 7
Keep in mind that SELECT * is bad practice. I used it to simplify reading.
TRY THIS QUERY
SELECT comments.*
FROM
(
SELECT ratings.id
FROM mySingleTable as ratings
WHERE
is_rating = 1
ORDER BY timestamp DESC LIMIT 0, 5 ) AS Top5
INNER JOIN mySingleTable AS comments ON comments.parent_id = Top5.id
WHERE comments.is_rating = 0
ORDER BY comments.timestamp DESC LIMIT 0, 5