I have one table with two columns (client_id and spent). Each client bought something more than 20 times. I want to sum spendings for each client.
I know that I can use sum and group by to do that, but I want to use sum not for all values in the groups but for only first 10 values. How can I do that?
I have tried with top 10 and limit 10, but It does not work.
I have 10 different clients and more than 200 rows. Clients are not scattered, they are in order, so I have 20 rows on client1 than 20 rows of on client2... Each client appears more than 20 times. I want to use sum and group by, but I do not want to sum all values (more than 20 for each row) , i want to sum first 10 values. Its ordered by time for each client
select client_id, sum(spendings)
from my_table
group by client_id
If you are using Mysql 8.0, You can do this by using window function.
select client_id, sum(spendings)
from (select client_id, spendings, row_number() over (partition by client_id order by <timecol>) rn
from my_table) t
where rn < 11
group by client_id
For MySQL, try this following code-
SELECT client_id,SUM(spendings)
FROM
(
select client_id,
spendings,
#row_num :=IF(client_id = #client_id,#row_num+1,1)AS RowNumber,
#client_id := client_id
FROM my_table
ORDER BY client_id
-- You may need to add here appropriate ordering
-- To get your desired 10 rows for group by in the result
)A
WHERE A.RowNumber < 11
GROUP BY client_id
Related
I have a table that looks like this:
id
count
1
100
2
50
3
10
4
10
I want to run select * query ,by using a new column called cumulative_sum , such that this new column is not create to the table rather is being queried (calculated) every time and use to select rows lying between limit and offset, + 1 more row after it.
Suppose I provide offset =130 and limit= 25 (i.e. range 130 to 155) then it should return row 2 row3 and row 4 (ie. last row + 1)
id
count
cumulative_sum
1
100
100
2
50
150
3
10
160
4
10
170
How to write a Mysql query for the above condition?
I trying to achieve this for quite some time now please help me to understand how to do this?
Cummulative sum column is just sum of = last rows cummulative sum + count of present row
On MySQL 8+, we can simply use SUM() as an analytic function:
SELECT id, count, SUM(count) OVER (ORDER BY id) AS cumulative_sum
FROM yourTable
ORDER BY id;
On earlier versions of MySQL, we can use a correlated subquery to find the rolling sum:
SELECT id, count,
(SELECT SUM(t2.count) FROM yourTable t2
WHERE t2.id <= t1.id) AS cumulative_sum
FROM yourTable t1
ORDER BY id;
Use Window function to achieve this (works with MySQL 8.0 and above):
SELECT id, count, sum(count) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as cummulative_sum
FROM your_table
ORDER BY id
I have a clients mysql table and I´d like to get a cumulatie count of clients grouped by month-year.
I have tried the next, but no look:
SELECT DATE_FORMAT(datacad,'%m-%y') AS month-year, count(id) OVER(ORDER BY id) AS cumulative_count
FROM clients;
clients
-------
id datacad
1 2001-10-10
2 2001-10-11
3 2002-11-12
4 2001-12-14
5 2003-12-15
6 2003-12-16
7 2003-12-17
//required result
month-year cumulative_count
----------------------------
10-2001 3
11-2002 4
12-2003 10
Additional Info:
When I use:
SELECT DATE_FORMAT(datacad,'%m-%y') AS label, count(*) as total FROM clients
GROUP BY label
order by datacad
I get:
label,total
03-2011,1
04-2011,1268
05-2011,1365
06-2011,1244
07-2011,1102
08-2011,315
02-2013,1
03-2013,1
03-2014,1
06-2014,1
07-2014,1
01-2017,1
02-2017,1
01-2018,4
05-2018,2
08-2018,1
09-2019,1
04-2020,3
06-2020,1
But when I use:
SELECT DATE_FORMAT(datacad,'%m-%y') AS month_year,
SUM(COUNT(id)) OVER (ORDER BY id) AS cumulative_count
FROM clients
GROUP BY month_year
ORDER BY MIN(datacad);
I get:
month_year,cumulative_count
03-11,1271
04-11,1268
05-11,2636
06-11,3880
07-11,4982
08-11,5297
02-13,5298
03-13,5299
03-14,5300
06-14,5301
07-14,5302
01-17,5303
02-17,5304
01-18,5308
05-18,1270
08-18,5309
09-19,5310
04-20,5313
06-20,5314
The results from both don´t match.
You need a GROUP BY and to SUM() the counts for a cumulative sum:
SELECT DATE_FORMAT(datacad,'%m-%y') AS month_year,
SUM(COUNT(id)) OVER (ORDER BY MIN(datacad)) AS cumulative_count
FROM clients
GROUP BY month_year
ORDER BY MIN(datacad);
I also assume you want the data in date order, so I added an ORDER BY.
I have a query that returns following values:
TemplateCode Total
1418 35
7419 31
7418 31
8325 17
15623 17
4997 17
I want all the rows with top 3 Total values
In my query if I include LIMIT 3 in the query then it gives only 3 which I don't want. I don't want to include LIMIT because count may vary from time to time.
How can I include condition on Total and always get top 3 count values
My current query is like:
select TemplateCode, count(*) as Total from table group by TemplateCode
order by Total desc
limit 3
I think this does what you want:
select t.*
from t
where t.Total >= (select distinct t2.Total
from t t2
order by t2.Total desc
limit 2, 1
);
This assumes that you want the third distinct value. If you just want the third value, remove the distinct.
You could use a inner join on subquery for the top 3 total
select m.TemplateCode , m.total
from my_table m
inner join (
select Total
from my_table
order by Total Desc
limit 3
) t on t.total = m.total
order by m.total, m.TemplateCode
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
TABLE quotation
id clientid
1 25
2 25
3 25
4 25
5 26
How can I query how many different clients exist in TABLE quotation? I don't want duplicate entries to be counted more than once.
I need the answer to be 2, in 1 row, because the only non-duplicated entries are (25, 26).
select count(distinct clientid) from quotation
read more
I find a way out
SELECT COUNT(*) as total FROM (SELECT COUNT(*) FROM quotation GROUP BY
clientid) t1
If you want to count the total number of unique entries this will return a number in column count.
SELECT COUNT(*) as total FROM (SELECT COUNT(*) FROM quotation GROUP BY clientid having count(*) > 1) t1
If you want to count the total number of entries with duplicate rows then use the following mysql.
SELECT COUNT(*) as total FROM (SELECT COUNT(*) FROM quotation GROUP BY clientid having count(*) >= 2) t1
I tried the following on a MySQL 5.x database.
id is an integer and clientid is an integer. I populated with two rows:
id clientid
1 25
2 25
This SQL query will print the rows that have exactly 2 elements:
select * from test1 group by clientid having count(*) = 2;
If you want 2 or more elements, replace = 2 in the example above with >= 2.
select * from test1 group by clientid having count(*) >= 2;
SELECT clientid, COUNT(clientid) FROM quotation
GROUP BY clientid