How to select the bigger date between 2 columns? - mysql

I have a table 'processes' with the following columns :
id
date_creation
date_lastrun
For example I have the following entries:
id;date_creation;date_lastrun
1;2022-01-01 00:00:00;2022-02-01 00:00:00
2;2022-03-01 00:00:00;NULL
I want to select the element with the bigger date in MySQL
I can do
SELECT id, MAX(IFNULL(date_lastrun, date_creation)) as lastdate
FROM processes
It's OK it works but now I want to get the element with the bigger date compared to a specific date time.
I tried :
SELECT id, MAX(IFNULL(date_lastrun, date_creation)) as lastdate
FROM processes
WHERE DATE(lastdate) > "2022-03-01"
but it returns *#1054 - Unknown column 'lastdate' in 'where clause'
SELECT id, MAX(IFNULL(date_lastrun, date_creation)) as lastdate
FROM processes
WHERE DATE(MAX(IFNULL(date_lastrun, date_creation))) > "2022-03-01"
but it returns #1111 - Invalid use of group function
Do you have any idea how to accomplish that?
I hope to return the element with the bigger date compared to a specific date.

Do not use the MAX in the WHERE clause but limit the result to dates bigger than "2022-03-01" and then get the biggest one.
SELECT id, MAX(IFNULL(date_lastrun, date_creation)) as lastdate FROM
processes WHERE DATE(IFNULL(date_lastrun, date_creation)) >
"2022-03-01";

I would prefer GREATEST with COALESCE here:
SELECT id, GREATEST(COALESCE(date_creation,0), COALESCE(date_lastrun,0)) AS lastdate
FROM processes
WHERE GREATEST(COALESCE(date_creation,0), COALESCE(date_lastrun,0)) > "2022-03-01";
MAX is unhandy in this situation due to its limitation to one argument, see also this article: difference max <-> greatest
COALESCE is required in this case because GREATEST is not able to deal with NULL values in MYSQL.
Try out: db<>fiddle

Related

Getting and splitting result from one column of MYSQL database to multiple Columns

I have a table named as energymeter which have 3 columns named as Date, Name, Value.
I want a result of highest value of day- minimum value of day of each day in specified time period of individual parameter (Name) into 3 separate columns.
Here is my table structure
And i am getting result for single parameter as i wish using query
select Date(Date) as Date,
Max(Value) - Min(Value) as Value ,
Name
from energy_meter.energy_meter
WHERE Name ='Energy_Meters\[1\].Total_active_energy_kWh'
And DATE(Date) between '2022-10-01' and '2022-10-13'
group by DATE(Date)
and getting result as below
and i want result should look like below for all 3 parameters
Community help is needed.
Thanks

MYSQL - Max(Date) gives me right Date but wrong Value

So I am querying a specific measurement based of the last date inserted using MAX
The last occurency is this one:
Measurement Date_insert
9.039999961 2021-03-30 11:57:2
When I try to query it like this:
SELECT m.measurement, MAX(m.date_insert) FROM measurements m
I get:
Measurement Date_insert
0.000000000 2021-03-30 11:57:2
The date keeps the same which shows me that I queried the right date
but how is it possible that the measurement changes value?
Any help would be grateful!
You should do that
SELECT m.measurement, m.date_insert
FROM measurements m
order by m.date_insert desc
limit 1
Your query does not return the correct results because you mix "normal" column selects with aggregation. MySQL supports that sadly. It returns strange results. Other DB engines throw an error for your query.
It's returning 0.000000000 as measurement from the first (any) row and MAX(m.date_insert) is returning max value from date_insert column.
It's possible that 0.000000000 and 2021-03-30 11:57:2 even do not exist in same row.
Please avoid this query if your intention is to get the max date_insert along with the value of measurement column from same row. Instead use just order by clause with Limit 1 as suggested by #juergen d.
But if there are multiple measurement value for a single date_insert then you can use group by clause to find the max(measurement) for the highest date_inert value. Here goes the example:
Schema:
create table measurements( Measurement float, Date_insert datetime);
insert into measurements values(0.000001000 ,'2021-03-30 11:57:5');
insert into measurements values(9.039999961 ,'2021-03-30 11:57:5');
insert into measurements values(0.000000000 ,'2021-03-30 11:57:2');
Set sql_mode:
set sql_mode=only_full_group_by;
Query:
SELECT m.date_insert, max(m.measurement)measurement
FROM measurements m
group by m.date_insert
order by m.date_insert desc
limit 1
date_insert
measurement
2021-03-30 11:57:05
9.04
db<>fiddle here

how can I calculate the SUM in 4days buckets over all dates

I have a MySQL DB where one column is the DATE and the other column is the SIGNAL. Now I would like to calculate the SUM over Signal for 4 days each.
f.e.
SUM(signal over DATE1,DATE2,DATE3,DATE4)
SUM(signal over DATE5,DATE6,DATE7,DATE8)
...
whereas Date_N = successor of DATE_N-1 but need not to be the day before
Moreless the algo should be variable in the days group. 4 ist just an example.
Can anyone here give me an advice how to perform this in MySQL?
I have found this here group by with count, maybe this could be helpful for my issue?
Thanks
Edit: One important note: My date ranges have gaps in it. you see this in the picture below, in the column count(DISTINCT(TradeDate)). It should be always 4 when I have no gaps. But I DO have gaps. But when I sort the date descending, I would like to group the dates together always 4 days, f.e. Group1: 2017-08-22 + 2017-08-21 + 2017-08-20 + 2017-08-19, Group2: 2017-08-18 + 2017-08-17+2017-08-15+2017-08-14, ...
maybe I could map the decending dateranges into a decending integer autoincrement number, then I would have a number without gaps. number1="2017-08-17" number2="2017-08-15" and so on ..
Edit2:
As I see the result from my table with this Query: I might I have double entries for one and the same date. How Can I distinct this date-doubles into only one reprensentative?
SELECT SUM(CondN1),count(id),count(DISTINCT(TradeDate)),min(TradeDate),max(TradeDate) ,min(TO_DAYS(DATE(TradeDate))),id FROM marketstat where Stockplace like '%' GROUP BY TO_DAYS(DATE(TradeDate)) DIV 4 order by TO_DAYS(DATE(TradeDate))
SUM() is a grouping function, so you need to GROUP BY something. That something should change only every four days. Let's start by grouping by one day:
SELECT SUM(signal)
FROM tableName
GROUP BY date
date should really be of type DATE, like you mentioned, not DATETIME or anything else. You could use DATE(date) to convert other date types to dates. Now we need to group by four dates:
SELECT SUM(signal)
FROM tableName
GROUP BY TO_DAYS(date) DIV 4
Note that this will create an arbitary group of four days, if you want control over that you can add a term like this:
SELECT SUM(signal)
FROM tableName
GROUP BY (TO_DAYS(date)+2) DIV 4
In the meantime and with help of KIKO I have found the solution:
I make a temp table with
CREATE TEMPORARY TABLE if not EXISTS tradedatemaptmp (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY) SELECT Tradedate AS Tradedate, CondN1, CondN2 FROM marketstat WHERE marketstat.Stockplace like 'US' GROUP BY TradeDate ORDER BY TradeDate asc;
and use instead the originate tradedate the now created id in the temp table. So I could manage that - even when I have gaps in the tradedate range, the id in the tmp table has no gaps. And with this I can DIV 4 and get the always the corresponding 4 dates together.

SQL query to select values grouped by hour(col) and weekday(row) based on the timestamp

I have searched SO for this question and found slightly similar posts but was unable to adapt to my needs.
I have a database with server requests since forever, each one with a timestamp and i'm trying to come up with a query that allows me to create a heatmatrix chart (CCC HeatGrid).
The sql query result must represent the server load grouped by each hour of each weekday.
Like this: Example table
I just need the SQL query, i know how to create the chart.
Thank you,
Those looks like "counts" of rows.
One of the issues is "sparse" data, we can address that later.
To get the day of the week ('Sunday','Monday',etc.) returned, you can use the DATE_FORMAT function. To get those ordered, we need to include an integer value 0 through 6, or 1 through 7. We can use an ORDER BY clause on that expression to get the rows returned in the order we want.
To get the "hour" across the top, we can use expressions in the SELECT list that conditionally increments the count.
Assuming your timestamp column is named ts, and assuming you want to pull all rows from the year 2014, we start with something like this:
SELECT DAYOFWEEK(t.ts)
, DATE_FORMAT(t.ts,'%W')
FROM mytable t
WHERE t.ts >= '2014-01-01'
AND t.ts < '2015-01-01'
GROUP BY DAYOFWEEK(t.ts)
ORDER BY DAYOFWEEK(t.ts)
(I need to check the MySQL documentation, WEEKDAY and DAYOFWEEK are real similar, but we want the one that returns lowest value for Sunday, and highest value for Saturday... i think we want DAYOFWEEK, easy enough to fix later)
The "trick" now is the columns across the top.
We can extract the "hour" from timestamp using the DATE_FORMAT() function, the HOUR() function, or an EXTRACT() function... take your pick.
The expressions we want are going to return a 1 if the timestamp is in the specified hour, and a zero otherwise. Then, we can use a SUM() aggregate to count up the 1. A boolean expression returns a value of 1 for TRUE and 0 for FALSE.
, SUM( HOUR(t.ts)=0 ) AS `h0`
, SUM( HOUR(t.ts)=1 ) AS `h1`
, SUM( HOUR(t.ts)=2 ) AS `h2`
, '...'
, SUM( HOUR(t.ts)=22 ) AS `h22`
, SUM( HOUR(t.ts)=23 ) AS `h23`
A boolean expression can also evaluate to NULL, but since we have a predicate (i.e. condition in the WHERE clause) that ensures us that ts can't be NULL, that won't be an issue.
The other issue we can encounter (as I mentioned earlier) is "sparse" data. To illustrate that, consider what happens (with our query) if there are no rows that have a ts value for a Monday. What happens is that we don't get a row in the resultset for Monday. If it does happen that a row is "missing" for Monday (or any day of the week), we do know that all of the hourly counts across the "missing" Monday row would all be zero.

select all the rows until date diff is 4 from bottom

I want to select all the rows from table where date different between two row is 4 or less and stop as soon as condition don't match ie diff > 4 in descending order i.e.(from bottom)
caution: once condition is > 4 it will not match further it simply
stops
i.e it will have to select 5,6,7,8,9
I tried using "HAVING", but its slow on big data
Thank you all in advance to helping figure it out.
You can use user-defined variables to track the previous updated_at value (in my example below, in #t) then calculate from that whether the record is desired based on whether the previous record was desired (#b) and, if so, the difference between that last date and the current one:
SELECT id, amount, updated_at
FROM (
SELECT my_table.*,
#b:=IF(#b, DATEDIFF(#t,updated_at)<=4, FALSE) okay,
#t:=updated_at
FROM my_table, (SELECT #b:=TRUE, #t:=MAX(updated_at) FROM my_table) init
ORDER BY updated_at DESC
) t
WHERE okay
ORDER BY updated_at, id
See it on sqlfiddle.