MySQL - Combine two queries, or limit results - php

I have a table that tracks recently updated pages, each page has a type. I want to limit the results so that we only pull 3 pages of type x, and 3 of type y, but still have them sorted by lastUpdated. I can't figure out how to do this in mysql
SELECT * from recentlyUpdated WHERE type = 'x' DESC LIMIT 3
SELECT * from recentlyUpdated WHERE type = 'y' DESC LIMIT 3
then ...
ORDER BY lastUpdated DESC

This may help you;)
(SELECT * from recentlyUpdated WHERE type = 'x'lastUpdated ORDER BY DESC LIMIT 3)
UNION ALL
(SELECT * from recentlyUpdated WHERE type = 'y'lastUpdated ORDER BY DESC LIMIT 3)
ORDER BY lastUpdated DESC

One obvious way to do it is using UNION:
SELECT *
FROM (
SELECT *
FROM recentlyUpdated
WHERE type = 'x'
LIMIT 3
UNION ALL
SELECT *
FROM recentlyUpdated
WHERE type = 'y'
LIMIT 3) AS t
ORDER BY lastUpdated DESC
Alternatively, you can use variables:
SELECT *
FROM (
SELECT *,
#seq := IF(#t = type, #seq + 1,
IF(#t := type, 1, 1)) AS seq
FROM recentlyUpdated
CROSS JOIN (SELECT #seq := 0, #t := '') AS vars
WHERE type IN ('x', 'y')
ORDER BY type) AS t
WHERE t.seq <= 3
ORDER BY lastUpdated DESC

Related

get 10 comments for each answer by one query

i have a comments table, like this:
id, answer_id, content
now i want to get latest 10 comments for EACH answer id.
list of answer ids are provided like (1,5,11,27,82)
is it possible to get all related comments by just one query ?
i currently do this by php's foreach:
foreach ($answers as $answer) { // query mysql for its comments
You can use UNION ALL for each answer_id:
(select id, answer_id, content from comments where answer_id=1 order by id desc limit 10)
union all
(select id, answer_id, content from comments where answer_id=5 order by id desc limit 10)
union all
(select id, answer_id, content from comments where answer_id=11 order by id desc limit 10)
union all
(select id, answer_id, content from comments where answer_id=27 order by id desc limit 10)
union all
(select id, answer_id, content from comments where answer_id=82 order by id desc limit 10);
This is a pain in MySQL, but you can use variables:
select c.*
from (select c.*,
(#rn := if(#a = c.answer_id, #rn + 1,
if(#a := c.answer_id, 1, 1)
)
) as rn
from comments c cross join
(select #rn := 0, #a := -1) params
order by answer_id, id desc
) c
where rn <= 10;
This assumes that larger values of id are more recent.

How to add multiple limits in mysql query?

I want to select SUM of last 200,100 and 50 rows of close price from a table in a single query.
given below is the query for 200 rows.
SELECT SUM(Close_price) as tot200 FROM cash_data ORDER BY date_added LIMIT 0,200
can anyone help me with this.
You can use sub queries -
SELECT
(SELECT SUM(Close_price) FROM cash_data ORDER BY date_added LIMIT 0,200) as tot200,
(SELECT SUM(Close_price) FROM cash_data ORDER BY date_added LIMIT 0,100) as tot100,
(SELECT SUM(Close_price) FROM cash_data ORDER BY date_added LIMIT 0,50) as tot50
To make it in a single select without any subselects you can use a ranking varaible and sum conditionally
SELECT #rank := #rank + 1,
SUM(case when #rank <= 50 then Close_price else 0 end) as top_50_sum,
SUM(case when #rank <= 100 then Close_price else 0 end) as top_100_sum,
SUM(case when #rank <= 200 then Close_price else 0 end) as top_200_sum
FROM cash_data
cross join (select #rank := 0) r
ORDER BY date_added
LIMIT 0,200
Thanks for all the replies. Actually both the answers are working but i choose the second one and made some changes for my need. Below is the final query
SELECT
(SELECT SUM(Close_price)/200 FROM (SELECT Close_price FROM cash_data WHERE SERIES='$series' AND SYMBOL='$symbol' AND date_added <= '$date' ORDER BY date_added DESC LIMIT 0,200) as tot200) as avg200,
(SELECT SUM(Close_price)/100 FROM (SELECT Close_price FROM cash_data WHERE SERIES='$series' AND SYMBOL='$symbol' AND date_added <= '$date' ORDER BY date_added DESC LIMIT 0,100) as tot100) as avg100,
(SELECT SUM(Close_price)/50 FROM (SELECT Close_price FROM cash_data WHERE SERIES='$series' AND SYMBOL='$symbol' AND date_added <= '$date' ORDER BY date_added DESC LIMIT 0,50) as tot50) as avg50
Thank you all.

How to get limit records with in Clause

I have a following query
I am getting id as a string
SELECT * from table_name
where id in (1,2,3,4)
order by created desc
limit 0,4
this Query is giving me only 4 records
i want to get 4 records from each id
Any idea ?
select * from
(
SELECT * from table_name where id = 1 order by created desc limit 4
union all
SELECT * from table_name where id = 2 order by created desc limit 4
union all
SELECT * from table_name where id = 3 order by created desc limit 4
union all
SELECT * from table_name where id = 4 order by created desc limit 4
) tmp
order by created desc

Echo data from several sql tables

I have never tried this but want to echo data from several different tables and order them by their timestamp. The code I have comes up with a booleon and i dont know why.
<?php
$result = mysql_query("SELECT * FROM artists ORDER BY timestamp DESC
UNION
SELECT * FROM news ORDER BY timestamp DESC
UNION
SELECT * FROM tracks ORDER BY timestamp DESC
UNION
SELECT * FROM gigs ORDER BY timestamp DESC
UNION
SELECT * FROM feature ORDER BY timestamp DESC");
while($row = mysql_fetch_array($result)){echo'News: '.$row['name'].$row['title'].$row['trackname'].$row['gigname'].'<br>' ;}
?>
Assuming your tables fall within the constraints of the UNION function..
Try:
SELECT * FROM
(SELECT * FROM artists ORDER BY timestamp DESC
UNION
SELECT * FROM news ORDER BY timestamp DESC
UNION
SELECT * FROM tracks ORDER BY timestamp DESC
UNION
SELECT * FROM gigs ORDER BY timestamp DESC
UNION
SELECT * FROM feature ORDER BY timestamp DESC) as temp
ORDER by timestamp DESC;

Limit the amount of results from mySQL conditionally?

Here is my query:
SELECT * FROM Photos WHERE Event_ID IN ($eventidstring)
I know I can limit the total amount of results from this query using LIMIT 5
I need the Limit the amount of results Per value in $eventidstring.
So if $eventidstring = 23,41,23*
*And there are 10 results WHERE Event_ID = 23, I want to limit this amount to 5. The same for all the other values in $eventidstring.
You may have some joy doing something similar to Oracle's RANK by PARITION in MySQL.
Sadly this feature is not available in MySQL though you can work around it using this method
Dump that in an inline view and then select those rows with rank <= 5;
Hence:
SELECT t.* FROM (
SELECT (
CASE Event_id
WHEN #curEventId
THEN #curRow := #curRow + 1
ELSE #curRow := 1 AND #curEventId := Event_Id END
) AS rank,
p.*
FROM Photos p INNER JOIN (SELECT #curRow := 0, #curEventId := '') r
ORDER BY p.Event_Id DESC
) t
WHERE t.rank <= 5 ORDER BY t.Event_Id asc;
Consider how you are going to 'choose' the top five by Event_Id too. You can always add in more after the ORDER BY p.Event_Id DESC to decide this.
I take it you're writing that query somewhere inside your PHP, so you need to split the $eventidstring into it's component values, form a SELECT for each and UNION all after the first one.
You sould do this with a loop of some sort, and concatenate the query strings in the loop...
If I understand correctly and you want to get five of each, you can use this:
(SELECT * FROM Photos WHERE Event_ID = 23 LIMIT 5)
UNION
(SELECT * FROM Photos WHERE Event_ID = 41 LIMIT 5)
UNION
(SELECT * FROM Photos WHERE Event_ID = ... LIMIT 5)
...
Maybe with a SELECT UNION but you need a new select for each value:
SELECT * FROM Photos WHERE Event_ID = 23 LIMIT 5
UNION SELECT * FROM Photos WHERE Event_ID = 41 LIMIT 5
UNION SELECT ...

Categories