MySql query to select rows with the next lower or higher date - mysql-5.1

Let' say I selected those data from a table which have the biggest date value like this:
SELECT * FROM table_name WHERE column_name IN (SELECT MIN(column_name) FROM table_name
It works fine, it selects those data with the "newest" date value.
What I want to know if is there a query in MySQL to list out those data which have the next descending date.
For example, in my first select, I've selected those rows which have the MIN date value like this: 2012-08-27 10:15:00
What I want with another query to select those data wich date value is the closest next value like this: 2012-08-28 11:45:00
So there are other rows with bigger or lower date value, but I don't want to select them. Only the closest next, from what I'm currently on.

If you have a value for the datetime whose closest next element you want to find (let's name it comparison_date), you could try something like this:
SELECT * FROM table_name WHERE column_name IN (SELECT MIN(column_name) FROM table_name WHERE column_name > comparison_date ORDER BY column_name)
This will return all the datetime values later than that date. If you want to limit it to a single result, you should use:
SELECT * FROM table_name WHERE column_name IN (SELECT MIN(column_name) FROM table_name WHERE column_name > comparison_date ORDER BY column_name) LIMIT 1
Alternatively, if you want the next closest datetime from current time, you can replace comparison_date with NOW() which is a MySQL function. Then, you can try something like this:
SELECT * FROM table_name WHERE column_name IN (SELECT MIN(column_name) FROM table_name WHERE column_name > NOW() ORDER BY column_name)
In order to find the next lower datetime (or previous datetime, however we call it), you should use:
SELECT * FROM table_name WHERE column_name IN (SELECT MIN(column_name) FROM table_name WHERE column_name < comparison_date ORDER BY column_name DESC) LIMIT 1

Related

How to Query in google sheets, sort by a column and not include that column in the output

I would like to query in google sheets and sort the query by a specific column in accending order, and have a secondary sort that is also in ascending order. I already know how to do this by
=QUERY(A:C,"select * where month(A)+1 = 1 order by A,B ",0)
Here i queried 3 columns month, unique ID, and name. I selected the data with the necessary month, and sorted it by month, followed by a secondary sort of unique ID. But this query outputs 3 columns. How would i change the formula so the output does not include the month column anymore.
Your question is:
How would i change the formula so the output does not include the month column anymore.
Try wrapping your QUERY formula within another QUERY. Like:
=QUERY(QUERY(your_query_here),"select Col2, Col3")
For your given example it would be:
=QUERY(QUERY(A1:C22,"select * where month(A)+1 = 1 order by A,B ",0),
"select Col1, Col3")

How to extract top 5 sum values with their top 3 sum reasons?

I need to review this query:
=QUERY('BD3'!A:Q, "SELECT D,Q, SUM(M) WHERE I='W34' AND M>0 AND L='Huacho' GROUP BY D,Q ORDER BY SUM(M) DESC LIMIT 5",-1)
I obtain this:
But I need something like this:
For the result you want, the correct SQL function should be:
RANK() OVER (PARTITION BY D, Q ORDER BY SUM(M) DESC
You can check this answer for detail explanations:
Array Formula to Rank Column A Partition by Column B And C

Clean cumulative sum alongside grouped sum

I am working in PostgreSQL 9.6.6
For the sake of reproducibility, I'll use create tempory table to create a "constant" table to play with:
create temporary table test_table as
select * from
(values
('2018-01-01', 2),
('2018-01-01', 3),
('2018-02-01', 1),
('2018-02-01', 2))
as t (month, count)
A select * from test_table returns the following:
month | count
------------+-------
2018-01-01 | 2
2018-01-01 | 3
2018-02-01 | 1
2018-02-01 | 2
The desired output is the following:
month | sum | cumulative_sum
------------+-----+----------------
2018-01-01 | 5 | 5
2018-02-01 | 3 | 8
In other words, the values have been summed, grouping by month, and then the cumulative sum is displayed in another column.
The issue is that the only way I know to achieve this is somewhat convoluted. The grouped sum must be computed first, (as with a sub select or with statement), and then the running tally is computed with a select statement against that table, as so:
with sums as
(select month,
sum(count) as sum
from test_table
group by 1)
select month,
sum,
sum(sum) over (order by month) as cumulative_sum
from sums
What I wish could work would be something more like...
select month,
sum(count) as sum,
sum(count) over (order by month) as cumulative_sum
from test_table
group by 1
But this returns
ERROR: column "test_table.count" must appear in the GROUP BY clause or be used in an aggregate function
LINE 3: sum(count) over (order by month) as cumulative_sum
No amount of fussing with the group by clause seems to satisfy PSQL.
TL,DR: is there a way in PSQL to compute both a sum over groups and the cumulative sum over groups using just a single select statement? More generally, is there a "preferred" way to accomplish this, beyond the method I use in this question?
Your hunch to use SUM as an analytic function was on the right track, but you need to analytic sum the aggregate sum:
SELECT month,
SUM(count) as sum,
SUM(SUM(count)) OVER (ORDER BY month) AS cumulative_sum
FROM test_table
GROUP BY 1;
Demo
As to why this works, the analytic functions are applied after the GROUP BY clause has happened. So the aggregate sum in fact is available when we go take the rolling sum.

InfluxDB: Select latest values in ascending order

To select the latest 100 data points from a measurement I use the following query:
select field1, field2 from measurement
where time < now()
order by time desc limit 100
However I need the values in ascending order. Currently I'm inverting the result in my application, which is costly.
I also tried a subquery, but without success:
select field1, field2 from
(select * from measurement
where time <= now()
order by time desc limit 100) order by asc
You can use this query as a work out
select * from measurement where time <= now() and time >= now() - "some time you defined" limit 100
Though You have to cautious about your defining time.

Replacing a sql column value based on a column another table

I have table1 (col1,col2) and table2(col1,col2) as given below/
Now i need to replace values of col2 of table1 with corresponding value of col1 and col2 from table2. So that the final table should look like this. how can we do this in query??
I assume table1.col2 and table2.col2 have the same text type(?)
update table1 set table1.col2=table2.col2
from table1
join table2 on (table1.col2=table2.col1)

Resources