Select first largest value using TOP 1 in MySQL? - mysql

I'll try to explain by example what I want to achieve in MySQL.
I have a table looking like this:
pricelist_id valid_from
1 1610665200000 //15 Jan 2021
2 1610751600000 //16 Jan 2021
3 1610838000000 //17 Jan 2021
Values in column, valid_from, are essentially String values which were generated at some point in time by following Java code:
String.valueOf(System.currentTimeMillis())
My assignment is to pass any String value (in the format of a number, in this case long), generated in the same way as explained above and I need to extract single pricelist_id which belongs to the first lesser or equal value of valid_from in the table, in comparison with passed value of valid_from. It is hard to explain by words (and my English is just terrible), so I'll demonstrate.
If I pass a value which will represent Jan 18th, 1610924400000, I would need to get single pricelist_id value, in this case 3.
If I pass a value which will represent Jan 16th 17:15:00, 1610813700000, I would need to get single pricelist_id value, in this case 2.
If I pass a value which will represent Jan 25th, 1611529200000, I would need to get single pricelist_id value, in this case 3.
What I have so far, is this:
select max(p.pricelist_id)
from pricelist p
where (p.valid_from + 0) <= some_passed_value
order by p.valid_from, p.pricelist_id desc

If you can rely on pricelist_id being in the exact same sort order as valid_from, then your solution using max() works.
Otherwise you can use LIMIT:
select p.pricelist_id
from pricelist p
where (p.valid_from + 0) <= some_passed_value
order by p.valid_from, p.pricelist_id desc
limit 1

Convert the string to number for ordering and for comparing
Also use limit to get the higher value
select p.pricelist_id
from pricelist p
where CONVERT(p.valid_from, SIGNED) <= some_passed_value
order by CONVERT(p.valid_from, SIGNED), p.pricelist_id desc
LIMIT 0, 1

Related

How to use not greater than operator in mysql

Does mysql support !<= or !>= operator!!!
I am trying to fetch the data from the Person table where the age of a person is not greater than 30 (the age field may have null value).
You may phrase not greater than 30 as being aged 30 or younger:
SELECT *
FROM Person
WHERE age <= 30;
By default, those records with a null age would not be included in the above inequality.
If you really wanted to use NOT, then we could try:
SELECT *
FROM Person
WHERE NOT age > 30;
But typically you will just see the appropriate inequality being used, without an explicit NOT.
Not greater than can be written as <=
!<= is not an operator
Why not doing something like this :
SELECT * FROM table WHERE id <= 100
That mean the query will selecting the ID which not GREATER THAN 100. Or if you want to search something with specific value, you can try this :
SELECT * FROM table WHERE id >= 50 AND id <= 100
That mean the query will search data from table which ID is MORE THAN 50 AND NOT GREATER THAN 100.
Hope this will help.

Average since beginning of the year

I have a MySQL table shown in a picture. The result I want to get is in the "average" column:
I would like create query to calculate the average value since the beginning of the year (1 January). Each row contains the average between the beginning of the year and current row. Each 1 January the average should be reset to zero.
One method uses a correlated subquery:
select date, value,
(select avg(value) from t t2 where t2.date <= t.date) as running_avg
from t
order by date;
This makes some assumptions:
"a", "b" and so on are numbers, not strings.
a+b/2 really means (a + b) / 2 and so on.
If you need from only this year, then the condition needs to include the year.

SQL - Performing a query on a result from another query?

I have a column(varchar) with date values, I need to find those dates which are expiring in next 30 days.
ExpiringDate
===================
20171208,
20171215,samples
20171130,tested
N/A
No
(empty row)
So, First I need to get values before comma. On the resultset, I need to filter out rows that has only numbers(no 'N/A' or 'No' or empty rows) & then I need to filter those dates which are expiring in next 30 days.
Edited
I have tried the following & resultset seems to be inappropriate
SELECT
DocName,
CategoryName,
AttributeName,
CAST(SUBSTRING_INDEX(AttributeValue, ',', 1) AS DATE) AS ExpiredDate
FROM myDB
WHERE (AttributeName = 'Date of last vessel OVID' OR AttributeName = 'Next Statutory docking' OR
AttributeName = 'Last statutory docking') AND AttributeValue LIKE '%[^0-9]%' AND
DATEDIFF(now(), AttributeValue) <= 30;
Because you are not only storing dates as text, but mixing those dates with entirely non date information, this complicates things. In this case, we can do two checks, one to ensure that the record starts with an actual expected date, and the second to make sure that the date diff is within 30 days from now.
SELECT ExpiringDate
FROM
(
SELECT ExpiringDate
FROM yourTable
WHERE ExpiringDate REGEXP '^[0-9]{8}'
) t
WHERE
DATEDIFF(LEFT(ExpiringDate, 8), NOW()) BETWEEN 0 AND 30;
Note that I use a subquery to first remove rows that do not even have a parseable date. The reason for this is that DATEDIFF will error out if not passed valid dates for both parameters.
Demo

Is formatting required to compare dates in mysql

SELECT * FROM table WHERE '2016-03-31' > (SELECT MAX(year) from table where bill_id = 'somevalue')
I am using above query to check if 2016-03-31 is greater than all years present in table against bill_id. It is working fine. but is it correct approach to compare dates. dates will always in above format. Is there any need to convert date format for comparison. value 2016-03-31 will change dynamically but it will be always in Y-m-d format
Note : year is column name which contains full date in Y-m-d format like 2016-05-20
You are not comparing dates. You are comparing a string '2016-03-31' with a number, e.g. 2015.
In order to compare, MySQL silently converts the string to number. One would expect this to crash, as '2016-03-31' certainly isn't a number. MySQL, however, reads from left to right and takes from there all that can be considered a number, i.e. '2016'. Well, one could argue that some people put a minus sign at the end of a number, so this should be '2016-', i.e. -2016. Anyway, MySQL stops before the minus sign, gets 2016 and uses this for the comparision.
I don't know if all this is guaranteed to work in the future. I would not rely on this.
What result would you expect anyway? Is the 31st of March 2016 greater than the year 2016? That's a queer question, don't you think?
Try this. But do you really have a column year that stores only year?
SELECT * FROM table WHERE year(STR_TO_DATE('2016-03-31'))
> (SELECT MAX(year) from table where bill_id = 'somevalue')
SELECT * FROM table WHERE YEAR('2016-03-31') > (SELECT MAX(year) from table where bill_id = 'somevalue')
MySQL YEAR() returns the year for a given date or timestamp. The return value is in the range of 1000 to 9999 or 0 for 'zero' date.

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.