How to SUM() from an offset through the end of the table? - mysql

If SELECT SUM(amount) FROM transactions ORDER BY order LIMIT 0, 50 sums the amount field for the first 50 records in a table, how do a sum all records after the first 50? In other words, I'd like to do something like SELECT SUM(amount) from transactions ORDER BY order LIMIT 50, *, but that doesn't work.

SELECT SUM(amount)
FROM (
SELECT amount
FROM transactions
ORDER BY
order
LIMIT 50, 1000000000000
) q
Note that your original query:
SELECT SUM(amount)
FROM transactions
ORDER BY
order
LIMIT 0, 50
does not do what you probably think it does. It is synonymous to this:
SELECT a_sum, order
FROM (
SELECT SUM(amount) AS a_sum, order
FROM transactions
) q
ORDER BY
order
LIMIT 0, 50
The inner query (which would normally fail in any other engine but works in MySQL due to its GROUP BY extension syntax) returns only 1 records.
ORDER BY and LIMIT are then applied to that one aggregated record, not to the records of transactions.

The documentation advices to use an incredible large number as second parameter to LIMIT:
To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
SELECT * FROM tbl LIMIT 95,18446744073709551615;

There is probably a more efficient way, but you could run a count query first, to retrieve total # of rows in your table:
SELECT count(*) FROM transactions
Stuff that into a variable and use that variable as your second argument for LIMIT. You could probably do this as a nested mysql query.

Related

MariaDB LIMIT statement brings more than limit

I have 10,000 users on registrations table and want to limit this query to 3500 users from my application. But when I investigate the logs , sometimes it counts more than 3500. I can not understand why that query returns more than limit:
select count(*)
from registrations
where (selectedtime IS NULL
AND expirationtime < NOW()
)
LIMIT 3500;
I tried manually on DB and saw sometimes more than 3500
Your query only returns 1 row, which is less than 3500.
If you want to limit the number of rows that are being counted, you need to put that in a subquery.
SELECT COUNT(*)
FROM (
SELECT 1
FROM registrations
WHERE selectedtime IS NULL AND expirationtime < NOW()
LIMIT 3500) AS x
A SELECT statement with COUNT returns the number of rows retrieved by the SELECT statement.
For performance reasons, the desired result is to limit that count.
Including a LIMIT clause in the SELECT statement will not work since it only restricts the number of rows returned, which is always one.
The solution, what I call “Limited-Count”, is done by limiting a non-count SELECT statement and wrapping it in COUNT(*).
For example:
If your count statement looks like
select count(*) from registrations where (selectedtime IS NULL AND expirationtime < NOW()) LIMIT 3500;
You can limit the results by replacing the query into:
SELECT COUNT(*) AS total
FROM (
SELECT 1
FROM registrations
WHERE selectedtime IS NULL AND expirationtime < NOW()
LIMIT 3500) AS x
If you need to know how many rows your non-count SELECT statement would have returned without the LIMIT, you could use the information function, FOUND_ROWS(). It will fetch the total rows number without running the statement again.
This does what you thought you were doing:
select count(*)
from registrations
where (selectedtime IS NULL
AND expirationtime < NOW()
)
LIMIT ROWS EXAMINED 3500;
(Available since MariaDB 5.5.21 - see https://mariadb.com/kb/en/library/limit-rows-examined/ )

I want to count and group a subset of a table

I want to select the latest 100 rows and then count and group the result, instead of counting and grouping the whole table, but I can't figure out how to do it.
An example of how it might work (but this does not work):
SELECT federal_party, count(federal_party)
From (
SELECT federal_party
FROM database
ORDER BY date_updated DESC LIMIT 100
)
GROUP BY federal_party
Any idea how this would best be done?

MySQL - Order by one column for a limit then by another column for a limit

I'm developing an application that displays rows which have columns "Time created" and "Number of Likes".
I'm trying to return the first 5 results of my query with the rows that have the most likes, and then the remaining 95 by most recent date, without duplication.
My current query only accomplishes ordering by date.
"SELECT * FROM `$category` ORDER BY time DESC LIMIT 100"
Is what I'm attempting to do possible in one query? Or will I have to perform two queries and filter out duplicate rows?
UNION automatically removes duplicate rows and LIMIT outside the parethesis applies to the whole query.
(SELECT *, like_count AS likes FROM category ORDER BY like_count DESC LIMIT 5)
UNION
(SELECT *, 0 AS likes FROM category ORDER BY time DESC)
ORDER BY likes DESC, time DESC
LIMIT 100

How can I limit query's results without using LIMIT

I need to show ordered 20 records on my grid but I can't use LIMIT because of my generator(Scriptcase) using LIMIT to show lines per page. It's generator's bug but I need to solve it for my project. So is it possible to show 20 ordered record from my table with a query?
As from comments,if you can't use limit then you can rank your results on basis of some order and in parent select filter limit the results by rank number
select * from (
select *
,#r:=#r + 1 as row_num
from your_table_name
cross join (select #r:=0)t
order by some_column asc /* or desc*/
) t1
where row_num <= 20
Demo with rank no.
Another hackish way would be using group_concat() with order by to get the list of ids ordered on asc/desc and substring_index to pick the desired ids like you need 20 records then join with same table using find_in_set ,But this solution will be very expensive in terms of performance and group_concat limitations if you need more than 20 records
select t.*
from your_table_name t
join (
select
substring_index(group_concat(id order by some_column asc),',',20) ids_list
from your_table_name
) t1 on (find_in_set(t.id , t1.ids_list) > 0)
Demo without rank
What about SELECT in SELECT:
SELECT *
FROM (
-- there put your query
-- with LIMIT 20
) q
So outer SELECT is without LIMIT and your generator can add own.
In a Scriptcase Grid, you CAN use Limit. This is a valid SQL query that selects only the first 20 records from a table. The grid is set to show only 10 records per page, so it will show 20 results split in a total of 2 pages:
SELECT
ProductID,
ProductName
FROM
Products
LIMIT 20
Also the embraced query works out well:
SELECT
ProductID,
ProductName
FROM
(SELECT
ProductID,
ProductName
FROM Products LIMIT 20) tmp

mySQL: Can I make count() honor limit clause?

I'm trying to get a count of records matching certain criteria within a subset of the total records. I tried (and assumed this would work)
SELECT count(*)
FROM records
WHERE status = 'ADP'
LIMIT 0,10
and I assumed this would tell me how many records of status ADP were in that set of 10 records. It doesn't - it returns, in this case 30, which is the total number of ADP records in the table.
How do I just count up the records matching my criteria including the limit?
SELECT count(*)
FROM ( SELECT records
FROM table
WHERE status = 'ADP'
LIMIT 0,10
)
select count(*) from (select * from records where status='ADP' limit 0,10) as t;