MySQL substract first row from last row of a group - mysql

I'm working on creating Google Charts from MySQL datasource. This works fine so far. Now I want to count how many blocks of a Blockchain processed per hour.
How can I simple substract the first row from last row of a group?
SELECT
date_format(time,'%Y-%m-%d %H-%i'),blocks,
count(1)
FROM blockchain
GROUP BY 1
ORDER BY `date_format(time,'%Y-%m-%d %H-%i')` ASC
And if this done, how to repeat this for the last 24 hours?
Sample data:
id time blocks
3 2020-12-30 11:21:53 112149
4 2020-12-30 11:21:55 112150
5 2020-12-30 11:21:56 112150
6 2020-12-30 11:21:57 112150
7 2020-12-30 11:24:01 112169
8 2020-12-30 11:25:01 112178
9 2020-12-30 11:26:01 112188
10 2020-12-30 11:27:01 112197
-10 2020-12-30 11:27:01 112197
3 2020-12-30 11:21:53 112149
-----------------------------------------------
48
I hope its not a stupid question. I'm kinda new to this.

You can use this query to get blocks per hour.
select hour(time) as hr, max(blocks)-min(blocks) as blocks_per_hour
from test
group by hour(time)
Result:
hr
blocks_per_hour
11
48
Example:
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=96ee323e8f15af0a946ff1220af01588

Related

MySQL - How to DISREGARD the records less than the CURRENT_DATE with the same FOREIGN KEY?

This is might be a simple problem for some but I badly need help.
Here is my table namely contribution:
id
entityno
oreceipt
oramount
ordate
datestarted
validity
5
8
1
60
2021-01-04
2021-01-04
2021-02-04
6
9
2
60
2021-01-04
2021-01-04
2021-02-04
7
8
3
60
2020-12-04
2020-12-04
2021-01-04
11
8
4
60
2021-02-22
2021-03-04
2021-03-04
enter image description here
What query can I use to select the records less than the current_date using validity as the basis?
The expected output is the record on the red marker corresponds to entityno = 9 only. Since entityno = 9 was expired last 04 February 2021 and entityno = 8 will expire on 04 March 2021.
Expected output:
id
entityno
oreceipt
oramount
ordate
datestarted
validity
6
9
2
60
2021-01-04
2021-01-04
2021-02-04
Fiddle
Any help is highly appreciated. Thanks!
You probably can do something like this:
SELECT A.* FROM contribution A
JOIN
(SELECT entityno, MAX(validity) mxv
FROM contribution
GROUP BY entityno) B
ON A.entityno=B.entityno AND A.validity=B.mxv
WHERE validity < CURDATE();
Idea is to:
Get the entityno with their maximum validity date, hence MAX(validity).
Then make it as a sub-query and JOIN with contribution table by matching entityno and validity=MAX(validity). This suppose to return each entityno with their maximum validity.
Then with that do a WHERE condition to get any entityno that have validity date smaller than CURDATE().
Demo fiddle

Exclude the combination of 2 columns only from my query

Sounds simple but I couldn't find the solution for it.
I have a table with 3 columns. Account, Amount, Date.
I want to get all entries except the ones of one specific account with negative amount. But I still want to get the entries of this account if amount value is positive.
So with this query I'm also not getting the entries from account1 with a positive amount.
select * from table where (account!='account1' AND amount<='0') AND date='2020-05-01'
You can do this using WHERE NOT in your statement.
Example schema:
Account Amount Date
=====================================
1 Ben 200 2020-10-10
2 Frank 200 2020-10-10
3 Ben -300 2020-10-12
4 Ben 10 2020-10-16
5 Mary 2000 2020-10-16
6 Frank -200 2020-10-18
7 Ben -10 2020-10-18
8 Ben 0 2020-10-20
Now if you build your query like this
SELECT * FROM t1 WHERE NOT (account='Ben' AND amount<0);
you should get what you want (all records except the 3rd and 7th).
Edit: if you really only want to exclude records with negative amounts, you need to do < rather than <= as you did in your example above. Depends on whether you want row 8 to be included in the result or not.

Missing values on count in mysql

I'm just stuck with this issue atm and I'm not 100% sure how to deal with it.
I have a table where I'm aggregating data on week
select week(create_date),count(*)
from user
where create_date > '2015-02-01'
and id_customer between 9 and 17
group by week(create_date);
the results that I'm getting have missing values in the count, as shown below
5 334
6 376
7 394
8 405
9 504
10 569
11 709
12 679
13 802
14 936
15 1081
16 559
21 1
24 9
25 22
26 1
32 3
34 1
35 1
For example here from 16 to 21 there a obviously 4 values missing I would like these values to be included and count to be 0. I want this because I want the weeks to be matching with other metrics as we are outputting them in an excel file for internal analysis.
Any help would be greatly appreciated.
The problem is that an sql query cannot really produce data that is not there at all.
You have 3 options:
If you have data for each week in your entire table for the period you are querying, then you can use a self join to get the missing weeks:
select week(t1.create_date), count(t2.id_customer)
from customer t1
left join customer t2 on t1.id_customer=t2.id_customer and t1.create_date=t2.create_date and t2.id_customer between 9 and 17
where t1.create_date > '2015-02-01'
group by week(t1.create_date)
If you have missing weeks from the customer table as whole, then create a helper table that contain week numbers from 1 or 0 (depending on mysql config) to 53 and do a left join to this helper table.
Use a stored procedure that loops through the results of your original query and inserts the missing data in the resultset using a temporary table and then returns the extended dataset as result.
The problem is that there is no data matching your criteria for the missing weeks. A solution will be to join from a table that has all week numbers. For example if you create a table weeknumbers with one field weeknumber containing all the numbers from 0 to 53 you can use something like this
select weeknumber,count(user.*)
from weeknumbers left join user on (weeknumbers.weeknumber=week(user.create_date)
and user.create_date > '2015-02-01'
and user.id_customer between 9 and 17)
group by weeknumber;
Additionaly you might want to limit the week numbers you do not want to see.
The other way is to do it in the application.

Aggregate values based on a date interval

I have a database containing monthly precipitation values at some measurements locations. The structure of my table is:
describe pp_lunare;
Field Type Null
ID int(11) NO
DATA_OBS date NO
PLUTON float NO
LEGHIN float NO
DUMBRAVA float NO
A sample of my data:
ID DATA_OBS PLUTON LEGHIN DUMBRAVA
1 1977-01-01 14.4 33.3 25.1
2 1977-02-01 18.7 12.9 13.2
3 1977-03-01 32.8 26.7 18.3
4 1977-04-01 109.6 123.8 140.6
5 1977-05-01 98.5 104.7 59.9
6 1977-06-01 192.9 172.8 66.6
7 1977-07-01 101.4 85.8 79.4
8 1977-08-01 116.4 103.3 105.7
9 1977-09-01 54.5 47.4 51.8
10 1977-10-01 23.6 15.6 11
11 1977-11-01 59.7 44.3 29.7
12 1977-12-01 28.7 13.1 10
In my case I need to get the sum of the precipitation for every column at every 3 months something like this:
ID DATA_OBS PLUTON LEGHIN DUMBRAVA
1 1977-03-01 65.9 72.9 56.6
2 1977-06-01 401 401.3 267.1
3 1977-09-01 272.3 236.5 247.9
and so on...
Thanks.
You can get the month from your date with month(data_obs) which returns a month from 1 to 12. Convert this to a value for the quarter by doing something like floor((month(data_obs) - 1)/3) as quarter to get quarters from 0 to 3.
For example, select data_obs, concat(year(data_obs), floor((month(data_obs) - 1)/3)) as quarter from pp_lunare; should show you both the original date and the derived quarter side by side.
Then group by this new value and sum the rest:
select concat(year(data_obs), floor((month(data_obs) - 1)/3)) as quarter, sum(pluton), sum(leghin), sum(dumbrava)
from pp_lunare
group by quarter
order by quarter;
If you want the exact date format you had in the question, you'll have to do a little bit of string manipulation (add 1 to the quarter above, multiply that by 3, pad with 0s, then tack on a "-01" for the date).
You can get the month data at first, and convert it into [quarter], which is from 0 to 2.
Then you can create three temporary tables given [quarter]=0,1,2,
and the easy and final part will be to add up the i_th row in these tables, the result will be just like below. And you can also have the data_obs data as well.
ID DATA_OBS PLUTON LEGHIN DUMBRAVA
1 1977-03-01 65.9 72.9 56.6
2 1977-06-01 401 401.3 267.1
3 1977-09-01 272.3 236.5 247.9

Add together grouped rows into one value

I've got an issue where I've been presented data in this format from SQL, and have directly imported that into SSRS 2008.
I do have access to the stored procedure for this report, however I don't want to change it as a few other reports rely on it.
Project HoursSpent Cost
1 5 45
1 8 10
1 7 25
1 5 25
2 1 15
2 3 10
2 5 15
2 6 10
3 6 10
3 4 5
3 4 10
3 2 5
I've been struggling all morning to understand how/when I should be implementing the SUM() function with this.
I have tried already to SUM() the rows, but it still outputs the above result.
Should I be adding any extra groups?
Ideally, I need to have the following output:
Project HoursSpent Cost
1 25 105
2 15 40
3 16 30
EDIT: Here is my current structure:
"LineName" is a group for each project
You have to add a row group on "Project" since you want to sum up the data per each project.