Select n rows without LIMIT mysql - php

I have a problem. I would like to get only 300 rows from table without touching LIMIT. I need LIMIT for pagination. Is this possible in MySQL?
My current query:
SELECT a.title, a.askprice, a.picture, a.description, a.userid, a.id
FROM mm_ads AS a WHERE a.category = 227 AND a.status = 1
ORDER BY id DESC LIMIT 40,20
Edit:
Simple explanation: I need to get from a system last 300 ads but I need to keep pagination, because I don't want to have 300 rows listed in one page..

SELECT *
FROM (
SELECT a.title, a.askprice, a.picture, a.description, a.userid, a.id
FROM mm_ads AS a
WHERE a.category = 227 AND a.status = 1
ORDER BY id DESC
LIMIT 300
) t
LIMIT 40,20
If the purpose is to speed up the query, then you can create a composite index:
ALTER TABLE `mm_ads`
ADD INDEX `mm_ads_index` (`category` ASC, `status` ASC, `id` DESC);

Use SQL_CALC_FOUND_ROWS after your SELECT:
SELECT SQL_CALC_FOUND_ROWS *
EDIT:
And in php, run this row to get the amount of rows:
list($int_rows) = mysql_fetch_row(mysql_query("SELECT FOUND_ROWS()"));
This will go through all the rows, get the total amount, but not fetch all the rows.
EDIT2:
May have misunderstod your question, however this is a common solution for pagination.

Simple solution is
Fits count only amount of result you need and use it in your pagination
then use limit in your query to load data on each page
SELECT a.title, a.askprice, a.picture, a.description, a.userid, a.id
FROM mm_ads AS a WHERE a.category = 227 AND a.status = 1
ORDER BY id DESC LIMIT 40,20
it dosen't matter how large your data base is it only gives you the 20 results (although it search for full database)

One more thing that you can do is just fetch all the 300 rows from database and save it in an array and then paginate the array indexes

Related

How we can get the data from the table by limiting the number of identical columns MySql

Yesterday I tried to retrieve data from my db table using 'user_id' as a criterion to limit the amount of data per user.
I tried to get data from table https://prnt.sc/p53zhp in format like this https://prnt.sc/p541wk and limit the number of output records for user_id where limit will be 2 (count(user_id) <= 2), but i don't understand how to do that. What kind of sql request can i use to get this data?
Assuming that your RDBMS, here is a solution yo select only the top 2 records per user. You can use ROW_NUMBER() in a subquery to rank records by id within groups of records having the same user_id, and the filter out unerelevant records in the outer query, like:
SELECT *
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY id)
FROM mytable
) x WHERE rn <= 2
On earlier versions of MySQL, you could use self-LEFT JOIN the table and use GROUP BY and HAVING COUNT(...) < 2 to limit the results to first two records per group:
SELECT
t.id,
t.user_id,
t.vip,
t.title,
t.description,
t.data
FROM mytable t
LEFT JOIN mytable t1 ON t1.user_id = t.user_id AND t1.id > t.id
GROUP BY
t.id,
t.user_id,
t.vip,
t.title,
t.description,
t.data
HAVING COUNT(t1.id) < 2
I don't understand if your problem is a Transact-SQL or your code.
In SQL you can limit record with "LIMIT": https://www.w3schools.com/sql/sql_top.asp
In code, you can use a condition IF.

How to 'GROUPT BY' after 'ORDER BY' in MySQL

I'm using the following query to get a list of users having maximum 'speed'.
With group by:
SELECT users.email, speed.speed
FROM users INNER JOIN speed ON users.email=speed.email
GROUP BY users.email
ORDER BY speed.speed DESC LIMIT 15
How ever on running the query, the 'ORDER BY' is not working. It always show the result in the top.
If I remove 'GROUP BY', I got the order list. But I only want 1 row with same email ids. How can i apply group by on this?
Without Group By:
SELECT users.email, speed.speed
FROM users INNER JOIN speed ON users.email=speed.email
ORDER BY speed.speed DESC LIMIT 15
Without an aggregate function, GROUP BY will show you the grouped column with whichever value is selected last from non-grouped columns. You'll want to use an aggregate function on your speed.speed column if you want it sorted.
If you want each user with their maximum speed you'll want to do something like
SELECT users.email, MAX(speed.speed) FROM users INNER JOIN speed ON users.email=speed.email ORDER BY speed.speed DESC LIMIT 15
Or if you wanted the minimum
SELECT users.email, MIN(speed.speed) FROM users INNER JOIN speed ON users.email=speed.email ORDER BY speed.speed DESC LIMIT 15
Or Both
SELECT users.email, MAX(speed.speed) as maxspeed, MIN(speed.speed) as minspeed FROM users INNER JOIN speed ON users.email=speed.email ORDER BY speed.speed DESC LIMIT 15
If you just want the 15 highest speeds:
SELECT s.email, s.speed
FROM speed s
ORDER BY s.speed DESC
LIMIT 15;
If you want the users with the highest speed:
SELECT s.email, s.speed
FROM speed s
WHERE s.speed = (SELECT MAX(s2.speed) FROM speed s2)
LIMIT 15;
Note that joins are not needed for these queries.

using group by and order by in mysql query correctly

I'm trying to get the latest certificate a user has from the database. I only want to see the latest one and not all the others so I'm using group by and then ordering by the unique id from the main table.
Without group by this works perfectly. I see the last certificate uploaded and then all the others below.
As soon as I add the group by I see the first certificate ever uploaded which is pointless as it could be from years ago.
My query is quite large as I'm drawing in a lot of other information from other tables.
Here is my query.
SELECT
usercert.*,
cert.*,
certCat.certCatName,
certTask.certTaskName ,
certStatus.certStatusName
FROM
`usercert`
INNER JOIN
cert
ON
cert.idcert = usercert.idcert
INNER JOIN
certCat
ON
certCat.idcertCat = cert.idcertCat
INNER JOIN
certTask
ON
certTask.idcertTask = usercert.idcertTask
INNER JOIN
certStatus
ON
certStatus.idcertStatus = usercert.idcertStatus
WHERE
usercert.iduser=%s
GROUP BY
usercert.idcert
ORDER BY
usercert.usercertEnd DESC
SELECT
usercert.*,
cert.*,
certCat.certCatName,
certTask.certTaskName ,
certStatus.certStatusName
FROM
`usercert`
INNER JOIN
cert
ON
cert.idcert = usercert.idcert
INNER JOIN
certCat
ON
certCat.idcertCat = cert.idcertCat
INNER JOIN
certTask
ON
certTask.idcertTask = usercert.idcertTask
INNER JOIN
certStatus
ON
certStatus.idcertStatus = usercert.idcertSttus
WHERE
usercert.iduser=%s
ORDER BY
usercert.usercertEnd
DESC limit 0,1
in this query it will take all the record in descending order it means the last inserted row will come first and the limit 0,1 means it will start from 0 and fetch 1 record that's it ...
You can either use MAX():
SELECT ... FROM ... WHERE ... ORDER BY MAX(usercert.usercertEnd)
Or LIMIT:
SELECT ... FROM ... WHERE ... ORDER BY usercert.usercertEnd DESC LIMIT 1

Not In mysql subquery Limit

Does anybody have any ideas how I can get around a #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' error?
My query is below ( I've read that I can upgrade mysql but this isn't possible):
$query = #mysql_query("SELECT * FROM posts
WHERE postid NOT IN
( SELECT postid FROM log
ORDER BY posted DESC
LIMIT 10)
ORDER BY (RAND() * Multiplier)
LIMIT 1");
According to this bug, you can use this ugly workaround:
SELECT * FROM t1 WHERE s1 NOT IN
(SELECT * FROM (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1) AS alias)
You can rewrite your query using JOIN:
SELECT *
FROM posts NATURAL LEFT JOIN (
SELECT postid FROM log ORDER BY posted DESC LIMIT 10
) t
WHERE t.postid IS NULL
ORDER BY RAND()
LIMIT 1
Be aware, however, that ORDER BY RAND() is very expensive. Not only must a random value be calculated for each record, but then a sort must be performed on the results. Indexes are of no use.
You would fare better if you had a column col containing unique integers, then with an index on col you can very rapidly obtain a random record with:
SELECT *
FROM posts NATURAL LEFT JOIN (
SELECT postid FROM log ORDER BY posted DESC LIMIT 10
) t JOIN (
SELECT RAND() * MAX(col) AS rand FROM posts
) r ON posts.col >= r.rand
WHERE t.postid IS NULL
LIMIT 1
Note that the uniformity of such "randomness" will depend on the distribution of the integers within col after any other filtering has taken place.

Advanced query with mysql: variables/subqueries?

I want to get the latest 5 messages in the inbox.
To get the 5 latest IDs i need to use this:
SELECT
MAX(id)
FROM
samtaler
WHERE
brukerid_mottaker = 1
GROUP BY brukerid_avsender
ORDER BY id DESC
LIMIT 5
This return the correct ID's I need. But in the same query i want to select data from the same table, the row that got the id that returned from this query above.
I have tried out some things, variables and self-join but no luck:
select
p2.title,
p2.message,
#a:=max(p1.id)
from
samtaler p1
join samtaler p2
on (#a = p2.id)
where
p2.brukerid_mottaker = 1
group by p2.brukerid_avsender
order by p2.id DESC
limit 5
Why isnt this working?
This is the current data in the database:
I want to return in this case, row 13 and 4. Sorry for bad english.
Join against a subquery, instead of a plain self join. An IN() clause won't work since LIMIT cannot be used inside an IN(). It should work in the joined subquery though:
SELECT
p1.title,
p1.message,
p2.id
FROM
samtaler p1
JOIN (
SELECT MAX(id) AS id
FROM
samtaler
WHERE
brukerid_mottaker = 1
GROUP BY brukerid_avsender
ORDER BY id DESC
LIMIT 5
) p2 ON p1.id = p2.id
By this method, there is no need for variables.

Categories