i have a table in my database named subscriber which contains two rows one for the subscriber id and another one for points earned by each subscriber .
My Select query :
SELECT 1000 * ( LOYALTY_POINTS DIV 1000 ) AS 'from', 1000 * ( LOYALTY_POINTS DIV 1000 ) +1000 AS 'to', COUNT( * ) AS NUMBER FROM SUBSCRIBER GROUP BY LOYALTY_POINTS DIV 1000
should return for each range of points the number of subscribers but unfortunately it only returns the number of subscribers different than zero.
My result is:
from to NUMBER
0 1000 8
1000 2000 2
3000 4000 1
I want the query to return records with zero coun also.
The result should be:
from to NUMBER
0 1000 8
1000 2000 2
2000 3000 0
3000 4000 1
How to do it? Thank you in advance.
You need to generate some numbers to indicate your range
SELECT 0 as RangeStart UNION Select 1000 UNION Select 2000 UNION Select 3000
and LEFT JOIN this to your results.
SELECT
RangeStart, RangeStart + 999 as RangeEnd, RangeCount
FROM
(SELECT 0 as RangeStart UNION Select 1000 UNION Select 2000 UNION Select 3000) range
LEFT JOIN
(Select LoyaltyPoints DIV 1000 as loyaltypoints, count(*) as RangeCount group by LoyaltyPoints DIV 1000 ) counts
ON range.rangestart = counts.loyaltypoints
Related
Given I have following table
Id
FileSizeMB
1
100
2
100
3
100
4
100
5
100
6
100
I want to select oldest records exceeding a cumulative value, in this case say 500.
So something like this
Id
Cumulative_FileSizeMB
6
100
5
200
4
300
3
400
2
500
1
600
I want to select only records with id 2 and 1 as they are >= 500.
Goal is to delete them.
Thanks
For anyone with same problem.
I have reached this solution using Mysql window functions,
and also there is no need to declare a variable for cumulative total
SELECT * from (
SELECT
id,
FileSizeMB,
SUM(FileSizeMB) OVER (ORDER BY id DESC) AS TotalFileSizeMB
FROM table
) as t1
WHERE TotalFileSizeMB > 500
I am writing an MySQL query that will take a table, split it into buckets of equal size of a given column, and then return a count of values within each bucket. This isnt the same as 10 equal "count" buckets - I am expecting the number of records in each bucket to vary - but for them to be split equally by a given column.
I have data as follows:
User | Followers
----------------
User 1 | 100
User 2 | 1000
User 3 | 1300
User 4 | 2000
User 5 | 10000
I would like to split the data into 5 equal sized "follower" buckets - ie buckets of increasing 2000 followers. So there would be an output as follows:
Bucket | Count
-----------------------
1.(0 - 2000) | 3
2.(2000 - 4000) | 1
3.(4000 - 6000) | 0
4.(6000 - 8000) | 0
4.(8000 - 10000)| 1
So far I've tried the following:
SELECT (followers)%(bucket_size),COUNT(*) FROM (SELECT (ROUND((MAX(followers)/MIN(followers))/10,0)) as bucket_size FROM users
WHERE followers > 0) as a
INNER JOIN users
GROUP BY (followers)%(bucket_size)
But this is providing me with all distinct values.
You can use aggregation as follows:
select 1 + (t.followers - 1) % b.bucket_size bucket, count(*) no_users
from mytable t
cross join (select 2000 bucket_size) b
group by t.followers % b.bucket_size
On the other hand, if you want to also return empty buckets, as shown in your desired results, it is a bit different. You can use an inline query to list the buckets, then bring the table with a left join:
select n bucket, count(t.followers) cnt
from (select 2000 bucket_size) b
cross join (select 1 bucket union all select 2 union all select 3 union all select 4 union all select 5) n
left join mytable t on (t.followers - 1) % b.bucket_size = n.bucket - 1
group by n.bucket
If having empty buckets is not important, here is a simple and readable solution:
select bucket as Bucket,
count(*) as Count
from (
select case when followers between 0 and 1999 then '(0-2000)'
when followers between 2000 and 3999 then '(2000-4000)'
when followers between 4000 and 5999 then '(4000-6000)'
when followers between 6000 and 7999 then '(6000-8000)'
when followers between 8000 and 10000 then '(8000-10000)'
end as bucket
from users
) buckets
group by bucket
You can also play around with the above query here: db-fiddle
I'm trying to get the most resent result for every amount linked to a duration.
This is my table :
SELECT * FROM financement;
id amount duration total
8 200 5 result8
7 200 4 result7
6 100 5 result6
5 100 4 result5
4 200 5 result4
3 200 4 result3
2 100 5 result2
1 100 4 result1
There is is a total for every amount linked to a duration.
My problematic is that, they can be multiple row for the same amout x duration and I only want the most recent.
For exemple in my case :
id amount duration total
5 100 4 result5
1 100 4 result1
I tried to use a GROUP BY like this:
SELECT * FROM `financement` GROUP BY amout, duration ORDER BY `id` DESC
But with this method, even with the ORDER BY id DESC, I still get the most ancien ROW.
I also tried to SELECT max() in a sub query like this, but the query is extremely long and it times out.
SELECT * financement where id in (select max(id) from financement group by amount, duration);
How can I get this output ?
id amount duration total
8 200 5 result8
7 200 4 result7
6 100 5 result6
5 100 4 result5
This should work:
SELECT * FROM `financement`
WHERE id IN (
SELECT max(id) as id FROM `financement` GROUP BY duration, amount
)
ORDER BY `id` DESC
I think you want filtering. You can use a scalar subquery:
select f.*
from financement f
where f.id = (select max(f2.id)
from financement f2
where f2.amount = f.amount and f2.duration = f.duration
);
Try this query:
SELECT * FROM financement ORDER BY id DESC
output of this query
I am new with mysql and working to change a store application to make it have two stock. I created a table to store stock quantity:
Then I plan to create a view with stock quantity, per store, per SKU. I using the following query:
SELECT
`stockList`.`sku`,
SUM(A.`stockQty`) AS 'store1',
SUM(B.`stockQty`) AS 'store2',
SUM(`stockList`.`stockQty`) AS 'total'
FROM `stockList`
LEFT JOIN (
SELECT * FROM `stockList` WHERE `idStock`=1
) AS A
ON `stockList`.`sku`=A.`sku`
LEFT JOIN (
SELECT * FROM `stockList` WHERE `idStock`=2
) AS B
ON `stockList`.`sku`=B.`sku`
GROUP BY `stockList`.`sku`
Per resulting table, calculation is not proper and I could not identify the logic:
SKU 43 should show for store1 = 9 and for store2 = 10, total = 19. This is what they show if I execute the select queries alone. Please, let me know if I misunderstood how this sum logic works.
You might to use SUM on subquery to calculate Totle price by sku
LEFT JOIN may make some fields not match causing NULL so use IFNULL to preset value 0
You can try this.
SELECT
T.sku,
SUM(T.stockQty) as totle,
IFNULL(A.`store1`,0) AS `store1`,
IFNULL(B.`store2`,0) AS `store2`
FROM `stockList` AS T
LEFT JOIN
(
SELECT sku,SUM(`stockQty`) as `store1`
FROM `stockList`
WHERE `idStock`=1
GROUP BY sku
) as A ON A.sku = T.sku
LEFT JOIN
(
SELECT sku,SUM(`stockQty`) as `store2`
FROM `stockList`
WHERE `idStock`=2
GROUP BY sku
) AS B ON T.sku =B.sku
GROUP BY T.sku
sqlfiddle
Your query is much more complicated than it needs to be. You can just do this:
SELECT
sku,
SUM(stockQty) as total,
SUM(IF(idStock=1,stockQty,0)) AS `store1`,
SUM(IF(idStock=2,stockQty,0)) AS `store2`
FROM `stockList`
GROUP BY sku
Output:
sku total store1 store2
36 10 10 0
37 3 3 0
38 4 4 0
39 3 3 0
40 10 10 0
41 12 12 0
42 12 12 0
43 19 9 10
I need to limit my result to 3 row (an example), but if 3rd result is equal to 4th, print also 4th, and so on.
To explain: from this table
id punteggio
1 100
2 200
3 70
4 100
5 54
6 201
7 200
if I do
SELECT * FROM table ORDER BY punteggio DESC LIMIT 3
i need in every case to print following situation:
id punteggio
6 201
2 200
7 200
1 100
4 100
Because my "three" best points are in reality 5 of 7, cause 2 and 7 have same points, like 1 and 4...
I dont'know in advance min and max points, otherwise i would do
"WHERE punteggio >= 100"
Thank you very much!
UPDATE
Unfortunately my scenario changed:
punteggio born from SUM from another table:
id idPersona punteggio
1 1 30
2 1 -10
3 2 50
4 3 60
5 2 -10
6 3 150
7 1 190
and so on...
i've tried do:
SELECT persone.nome,
SUM(transazioni.importoFinale) AS punti
FROM transazioni
INNER JOIN persone ON persone.idPersona = transazioni.idPersona
INNER JOIN
(SELECT DISTINCT(SUM(transazioni.importoFinale)) AS punti,
persone.nome
FROM transazioni
INNER JOIN persone on persone.idPersona = transazioni.idPersona
GROUP BY persone.idPersona
ORDER BY punti DESC
LIMIT 3) subq ON transazioni.punti = subq.punti
ORDER BY punti DESC
but it doens't function...
Thank you to all!
Use a subquery join to get the DISTINCT set of 3 greatest values for punteggio and join it against the main table to retrieve all rows that have those values.
SELECT
id,
punteggio
FROM
yourtable
/* subquery gets the top 3 values only */
/* and the INNER JOIN matches it to all rows in the main table having those values */
INNER JOIN (
SELECT DISTINCT punteggio as p
FROM yourtable
ORDER BY punteggio DESC
LIMIT 3
) subq ON yourtable.punteggio = subq.p
ORDER BY punteggio DESC
Here's a demo on SQLFiddle.com
SELECT id, punteggio
FROM yourtable
WHERE punteggio IN (
SELECT * FROM (
SELECT DISTINCT punteggio
FROM yourtable
ORDER BY punteggio DESC
LIMIT 3
) AS temp
);
Note that the select * is present to work around mysql not supporting limits in subqueries in an IN() clause.