I want to count and group a subset of a table - mysql

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?

Related

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: Remove rows from a GROUP BY result if it only grouped 1 row

When selecting data, I'm able to show how many rows were grouped from using GROUP BY by running:
SELECT id, created, COUNT(id) `count` FROM table
GROUP BY id
LIMIT 0,30
The count field easily outputs how many rows were affected by the GROUP BY. In MySQL is it possible to automatically not include any row which only has a count value of 1?
You should consider using a HAVING clause which lets you add conditions after the grouping has been done.
SELECT id, created, COUNT(id) cnt FROM table
GROUP BY id
HAVING cnt > 1
LIMIT 0,30
Another thing to mention is that the grouping might not be correct. If you group by id and you select id, created then the value for created is undetermined. MySQL will choose any of them for a given id if they differ. You might be interested in grouping by that field too or applying an aggregate function (eg: max(created)).
A second thing to mention is that COUNT(id) won't count the amount of rows but rather the amount of rows that have id not null. If id is never null then it would result in the same value as doing count(*).
Yes. You can use HAVING to limit the results of an aggregate function like COUNT (MAX,MIN,SUM, etc).
SELECT id, created, COUNT(id) `count`
FROM table
GROUP BY id
HAVING COUNT(id) > 1
LIMIT 0,30
Show the manual and find HAVING
... HAVING COUNT(id) > 1
http://dev.mysql.com/doc/refman/5.1/de/select.htmlhavinh

MySQL - Select highest values from one column, then re-order based on a second column?

I think what I need to do can be done using one query, but I'm really not sure - and I'd like to avoid performing a query and then sorting the resultant array if possible.
Basically, I have one table, which includes the following columns:
product_name, price, sold
From these columns, I'd like to do the following:
Select the highest 20 values from the 'sold' column DESC;
Order the 20 results by price ASC.
Sounds so simple, but can't figure out how to accomplish this to save my life, and SQL is not my strong point. If anyone could help out, it would be appreciated!
You can use subqueries for this:
select t.*
from (select t.*
from t
order by sold desc
limit 20
) t
order by price asc
You have a query that does a bunch of stuff. I'll call this . Here is what you do:
select t.*
from (select t.*
from (<subquery
) t
order by sold desc
limit 20
) t
order by price asc
I think this will do what you are looking for:
select * from table
order by sold desc, price asc

Determine total amount of top result returned

I would like to determine two things from a single query:
Most prevalent column in a table
The amount of times such column was located upon querying the table
Example Table:
user_id some_field
1 data
2 data
1 data
The above would return user_id # 1 as being the most prevalent in the table, and it would return (2) for the total amount of times that it was located in the table.
I have done my research and I came across two types of queries.
GROUP BY user_id ORDER BY COUNT(*) DESC
SUM
The problem is that I can't figure out how to use these two queries in conjunction with one another. For example, consider the following query which successfully returns the most prevalent column.
$top_user = "SELECT user_id FROM table_name GROUP BY user_id ORDER BY COUNT(*) DESC";
The above query returns "1" based on the example table shown above. Now, I would like to be able to return "2" for the total amount of times the user_id (1) was found in the table.
Is this by any chance possible?
Thanks,
Evan
You can include count(*) in the SELECT list:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC;
If you want only the first one:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC LIMIT 1;

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

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.