I have a database with colums I am working on. What I am looking for is the date associated with the row where the SUM(#) reaches 6 in a query. The query I have now will give the date when the number in the colum is six but not the sum of the previous rows. example below
Date number
---- ------
6mar16 1
8mar16 4
10mar16 6
12mar16 2
I would like to get a query to get the 10mar16 date because on that date the number is now greater than 6. Earlier dates wont total up to six.
Here is an example of a query i have been working on:
SELECT max(date) FROM `numbers` WHERE `number` > 60
You could use this query, which tracks the accumulated sum and then returns the first one that meets the condition:
select date
from (select * from mytable order by date) as base,
(select #sum := 0) init
where (#sum := #sum + number) >= 6
limit 1
SQL Fiddle
Most databases support ANSI standard window functions. In this case, cumulative sum is your friend:
select t.*
from (select t.*, sum(number) over (order by date) as sumnumber
from t
) t
where sumnumber >= 10
order by sumnumber
fetch first 1 row only;
In MySQL, you need variables:
select t.*
from (select t.*, (#sumn := #sumn + number) as sumnumber
from t cross join (select #sumn) params
order by date
) t
where sumnumber >= 10
order by sumnumber
fetch first 1 row only;
Awesome!!!! It seems to be working great. Here is the code that I used.
SELECT date, id, crewname
FROM (select * FROM flightrecord WHERE `crewname` = 'brayn'
ORDER BY dutyTimeArrive DESC) as base,
(select #sum := 0) init
WHERE (#sum := #sum + tankDropCount) >= 6
limit 1
Related
I have a Store Database with the following tables :
1 - Provider(ProviderID,Name,Country)
2 - Product(ProductID,ProviderID,ProductPrice)
3 - Command(CommandID,ProductID,ProductQuantity,CommandDate)
I made a query that counts the gain by year
SELECT EXTRACT(YEAR FROM COMMAND_DATE) AS year,
SUM(PRODUCT_PRICE*PRODUCT_QUANTITY) AS gain
FROM PRODUCT JOIN COMMAND ON PRODUCT.PRODUCT_ID=COMMAND.PRODUCT_ID
GROUP BY year
ORDER BY year
This is the output :
Now I want to display the row number just like Oracle, so I used this query :
SET #currentRow = 0;
SELECT #currentRow := #currentRow + 1 AS counter,
EXTRACT(YEAR FROM COMMAND_DATE) AS year,
SUM(PRODUCT_PRICE*PRODUCT_QUANTITY) AS gain
FROM PRODUCT JOIN COMMAND ON PRODUCT.PRODUCT_ID=COMMAND.PRODUCT_ID
GROUP BY year
ORDER BY year
But I don't get what I want
It seems that order is affecting the row number. I want it to start from 1. Ordering by counter is not an option because I need to order by years.
This is how I want it to be :
1 2014 1863
2 2015 889
3 2016 2626
...
With group by, you need a subquery:
SELECT (#currentRow := #currentRow + 1) AS counter, y.*
FROM (SELECT EXTRACT(YEAR FROM COMMAND_DATE) AS year,
SUM(PRODUCT_PRICE*PRODUCT_QUANTITY) AS gain
FROM PRODUCT JOIN
COMMAND
ON PRODUCT.PRODUCT_ID = COMMAND.PRODUCT_ID
GROUP BY year
ORDER BY year
) y CROSS JOIN
(SELECT #currentRow := 0) params;
Or, you can use ROW_NUMBER() OVER (ORDER BY YEAR), if you are using MySQL 8+.
The following code was taken from another question on SO. Original Q&A
I would like to count the number of consecutive days (Streak) with records since today AND also how many records were made today. I'm using this to send notifications. If a user submits a new record the same day, they should not get a second notification telling them that they are on a streak (they were made aware the first time they submitted a record for the current day).
I tried adding a COUNT() function before #streak, after the first SELECT and pretty much everywhere that seemed reasonable but this query is too complex for me to figure it out.
SELECT streak + 1 as realStreak
FROM (
SELECT dt,
#streak := #streak+1 streak,
datediff(curdate(),dt) diff
FROM (
SELECT distinct date(dt) dt
FROM glucose where uid = 1
) t1
CROSS JOIN (SELECT #streak := -1) t2
ORDER BY dt desc
)
t1 where streak = diff
ORDER BY streak DESC LIMIT 1
http://sqlfiddle.com/#!9/45d386/1/0
The result of the above should be:
realStreak | RecordsToday
3 | 3
Just add a subquery for the today check
SELECT streak + 1 as realStreak,cdt
FROM (
SELECT dt,
#streak := #streak+1 streak,
datediff(curdate(),dt) diff
FROM (
SELECT distinct date(dt) dt
FROM gl where uid = 1
) t1
CROSS JOIN (SELECT #streak := -1) t2
ORDER BY dt desc
)t1
JOIN
(SELECT COUNT(CASE WHEN DATE(dt)=CURDATE() THEN 1 END) cdt FROM gl)x
where streak = diff
ORDER BY streak DESC LIMIT 1
I'm using MySQL database. I'm looking to generate the rank of customers month by month for the last 6 months.
I just got the following query to work to determine the rank of a customer in a monthly poll. This reports the rank correctly only if the date range in one month.
select
t1.*,
#rownum := #rownum + 1 AS RANK
from
(
select
date_format(EVE_DATE,'%Y-%m') as MON_DATE,
CUST,
SUM(POLL) as SCORE
from
TABLE
where
EVE_DATE >= '2016-01-01' and EVE_DATE <= '2016-01-31'
group by
MON_DATE,
CUST
order by
SCORE desc
)t1,
(SELECT #rownum := 0) r
order by
RANK DESC
The problem I have is, if I were to change the date range to span over multiple months, then the rank shown isn't right. I've dug a bit deeper & realize that, the problem is due to the fact that when the number of days span across months, every customer gets listed as many times as the number of months in question. Thereby, number of rows in the output is number_of_customers * number of months which means the rank per month is no longer a meaningful value.
For example, if there are 100 customers & if I were to calculate the rank for one month, the maximum rank I can have is 100 which is correct. However, if I considered 2 months, the rank can range from 1 to 200 which is incorrect. This is because there are only 100 customers, but, are appearing twice due to 2 months being the consideration.
How could I correct the below query to show me rank per month correctly?
select
t2.*
from
(
select
t1.*,
#rownum := #rownum + 1 AS RANK
from
(
select
date_format(EVE_DATE,'%Y-%m') as MON_DATE,
CUST,
SUM(POLL) as SCORE
from
TABLE
where
EVE_DATE >= (curdate() - INTERVAL 3 MONTH)
group by
MON_DATE,
CUST
order by
SCORE desc
)t1,
(SELECT #rownum := 0) r
order by
RANK DESC
)t2
where
t2.CUST= 'customerA'
order by
t2.MON_DATE desc
I'd appreciate any help here to get me going please.
I think you want the inner subquery to aggregate only by customer, not by customer and date:
select t1.*,
#rownum := #rownum + 1 AS RANK
from (select CUST, SUM(POLL) as SCORE
from TABLE
where EVE_DATE >= '2016-01-01' and EVE_DATE <= '2016-01-31'
group by CUST
order by SCORE desc
) t1 cross join
(SELECT #rownum := 0) r
order by RANK DESC;
I have a table where each row contains a value and a datetime. It has hundreds of thousands of rows. I would like to select the highest (max) value every n rows.
I had previously used a query to get the highest value every hour, but this isn't quite what I am looking for:
SELECT datetime, MAX(value)
FROM `table`
GROUP BY date_format(datetime, '%Y-%m-%d &h')
Any advice would be greatly appreciated!
You can enumerate the rows and then aggregate to your heart's desire:
select min(rn), max(rn), min(datetime), max(datetime), max(value)
from (select t.*, (#rn := #rn + 1) rn
from `table` t cross join
(select #rn := 0) params
order by datetime
) t
group by floor((rn - 1) / #n)
order by min(rn);
I have a single table with a list of hits/downloads, every row has of course a date.
I was able to sum all the rows grouped by day.
Do you think it's possible to also calculate the change in percentage of every daily sum compared to the previous day using a single query, starting from the entire list of hits?
I tried to do this
select *, temp1.a-temp2.b/temp1.a*100 as percentage from
(select DATE(date), count(id_update) as a from vas_updates group by DATE(date)) as table1
UNION
(select DATE_ADD(date, INTERVAL 1 DAY), count(id_update) as b from vas_updates group by DATE(date)) as table2, vas_updates
but it won't work (100% CPU + crash).
Of course I can't JOIN them because those two temp tables share nothing in common being with 1 day offset.
The table looks like this, nothing fancy.
id_updates | date
1 2014-07-06 12:45:21
2 2014-07-06 12:46:10
3 2014-07-07 10:16:10
and I want
date | sum a | sum b | percentage
2014-07-07 2 1 -50%
It can be either be positive or negative obviously
select DATE(v.date), count(v.id_update) a, q2.b, count(v.id_update) - q2.b/count(v.id_update)*100 as Percentage
from vas_updates v
Left Join (select DATE_ADD(date, INTERVAL 1 DAY) d2, count(id_update) as b
from vas_updates group by d2) as q2
ON v.date = q2.d2
group by DATE(v.date)
The sum by day is:
select DATE(date), count(id_update) as a
from vas_update
group by DATE(date);
In MySQL, the easiest way to get the previous value is by using variables, which looks something like this:
select DATE(u.date), count(u.id_update) as cnt,
#prevcnt as prevcnt, count(u.id_update) / #prevcnt * 100,
#prevcnt := count(u.id_update)
from vas_update u cross join
(select #prevcnt := 0) vars
group by DATE(u.date)
order by date(u.date);
This will generally work in practice, but MySQL doesn't guarantee the ordering of variables. A more guaranteed approach looks like:
select dt, cnt, prevcnt, (case when prevcnt > 0 then 100 * cnt / prevcnt end)
from (select DATE(u.date) as dt, count(u.id_update) as cnt,
(case when (#tmp := #prevcnt) is null then null
when (#prevcnt := count(u.id_update)) is null then null
else #tmp
end) as prevcnt
from vas_update u cross join
(select #prevcnt := 0, #tmp := 0) vars
group by DATE(u.date)
order by date(u.date)
) t;