Reputation: 1484
I have a column "steak" representing the amount of steak in pounds my firm has bought since day 1 of 2010. I have another column "c_steak" representing the cumulative sum of pounds of steak.
╔═══╦════════════╦═════════════╗
║ ║ steak ║ c_steak ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 0.2 ║ 0.2 ║
║ 2 ║ 0.2 ║ 0.4 ║
║ 3 ║ 0.3 ║ 0.7 ║
╚═══╩════════════╩═════════════╝
How do I sample the table such that a row is taken once we buy another 100 pounds of steak? (sample ONE row immediately after c_steak reaches 100, 200, 300, 400 etc).
Note(EDIT):
c_steak is float. It may not exactly hit 100, 200, 300....
If c_steak goes like ..., 99.5, 105.3, 107.1, ... then the row corresponding to 105.3 will be sampled.
if c_steak goes like ..., 99, 100.1, 100.2, 100.3, 105..., then the row corresponding to 100.1 will be sampled.
Upvotes: 2
Views: 222
Reputation: 6749
You could have supplied some sample data.
Doing it now :
WITH
-- sample data , this will be in the table
input(id,steak_sold) AS (
SELECT 1,30.07
UNION ALL SELECT 2,30.01
UNION ALL SELECT 3,30.02
UNION ALL SELECT 4,30.03
UNION ALL SELECT 5,30.04
UNION ALL SELECT 6,30.05
UNION ALL SELECT 7,30.06
UNION ALL SELECT 8,30.07
UNION ALL SELECT 9,30.08
UNION ALL SELECT 10,30.09
UNION ALL SELECT 11,30.10
UNION ALL SELECT 12,30.11
UNION ALL SELECT 13,30.12
UNION ALL SELECT 14,30.13
UNION ALL SELECT 15,30.14
UNION ALL SELECT 16,30.15
UNION ALL SELECT 17,30.16
)
-- real WITH clause would begin here: creating running sum myself ....
,
runsum AS (
SELECT
*
, SUM(steak_sold) OVER(ORDER BY id) AS c_steak
FROM input
)
SELECT
*
FROM runsum
-- this running sum is above a certain 100
-- previous (running sum - steak_sold) below that 100
-- integer division by 100 of the two differs
WHERE c_steak//100 <> (c_steak - steak_sold) //100;
-- out id | steak_sold | c_steak
-- out ----+------------+---------
-- out 4 | 30.03 | 120.13
-- out 7 | 30.06 | 210.28
-- out 10 | 30.09 | 300.52
-- out 14 | 30.13 | 420.98
-- out 17 | 30.16 | 511.43
-- out (5 rows)
-- out
-- out Time: First fetch (5 rows): 53.018 ms. All rows formatted: 53.066 ms
Upvotes: 0
Reputation: 14389
It almost certain you need LAG
method. You can try like:
SELECT *
FROM (
SELECT c_steak
,lag(c_steak, 1, 0) OVER (ORDER BY id) lg
FROM myTable
) sub
WHERE cast(sub.c_steak as int) %100 - cast(sub.lg as int)% 100 < 0
The logic is that when you reach a sum of 100, 200 etc, the difference in modulus with the previous value should be negative. e.g:
80%100 = 80 where as 101%100 = 1
195%100 = 95 where as 205%100 = 5
293%100 = 93 where as 320%100 = 20
etc
Upvotes: 2
Reputation: 71
This works:
SELECT m2.id,m2.steak,m2.c_steak FROM t1 as m1 inner join t1 as m2 on m2.id = m1.id + 1 WHERE cast(m2.c_steak as int) % 100 < cast(m1.c_steak as int) % 100;
Look here:
===========
EDIT (in case id column skips at all):
SELECT distinct m2.id,m2.steak,m2.c_steak FROM t1 as m1 inner join t1 as m2 on m2.id > m1.id WHERE cast(m2.c_steak as int) % 100 < cast(m1.c_steak as int) % 100;
===========
Upvotes: 1
Reputation: 1087
You can use the MOD() function. Docs: https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_mod
SELECT * FROM Table WHERE MOD(c_steak, 100) = 0;
EDIT: In response to OPs edit, you can use FLOOR() on c_steak to get an int. Docs: https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_floor
SELECT * FROM Table WHERE MOD(FLOOR(c_steak), 100) = 0;
Upvotes: 0