Get the nearest/lowest Date SQL - sql

I have four dates with a different prices for each date:
10/01/2011 $25
10/08/2011 $50
11/17/2011 $100
12/23/2011 $150
SQL:
SELECT price FROM MyTable WHERE MyDate <= '10/12/2011'
PROBLEM: This query returns $25 and $50. I need it to give me the nearest date only...
How can i have it return only the $50?

SELECT top 1 price FROM MyTable WHERE MyDate <= '10/12/2011' order by MyDate desc

Try this (in SQL Server)
SELECT TOP 1 price
FROM MyTable
WHERE myDate <= getDate()
ORDER BY myDate DESC
Try this (in mySQL)
SELECT price
FROM MyTable
WHERE myDate <= now()
ORDER BY myDate DESC
LIMIT 1

Related

Return ID if sum of value is between two possible date ranges, and output which date range it came from?

I have a table that has a similar structure as this:
UserID
Amount
Date
123
50
01/01/2021
234
105
02/01/2021
123
60
01/15/2021
345
70
01/15/2021
456
110
12/31/2020
345
50
02/15/2020
I have two date ranges, 01/01/2021 - 01/31/2021 and 02/01/2021 - 02/28/2021. I want to get a list of UserIDs if they had total amount >= 100 within these date ranges, and to specify which date range it came from.
So in this example, I'd like an output like this:
UserID
Total Amount
Date Range
123
110
January
234
105
February
User ID 345 and 456 would not be included since their total amounts only reached >= 100 outside of the date ranges.
In my code, I'm not sure how to exclude UserID 345 since technically they have an amount >= 100 coming from dates in both ranges and not just one single range.
I'm having troubles with only summing if it's within the date range and I'm not sure how to specify from which date range it's coming from:
SELECT
UserID
,SUM(amount)
FROM table
WHERE
date BETWEEN '01-01-2021' AND '01-31-2021' OR
date BETWEEN '02-01-2021' AND '02-28-2021'
GROUP BY
UserID
HAVING SUM(amount) >= 100
You could use CROSS APPLY to calculate the date range, and then group by it.
But in this instance, it appears you are just using whole months, so we can just use DATENAME.
Side notes:
You should not use mm-dd-yyyy format for date literals
You can combine your two periods together in this instance, I have not done so to leave you the option of disjoint periods.
SELECT t.UserID,
SUM(t.amount),
Month = DATENAME(month, t.date)
FROM table t
WHERE t.Date BETWEEN '2021-01-01' AND '2021-01-31' OR
t.date BETWEEN '2021-02-01' AND '2021-02-28'
GROUP BY UserId, DATENAME(month, t.date);
NOTE: if your dates are actually datetime values then your filter is wrong. Instead you must use a half open interval:
WHERE t.Date >= '2021-01-01' AND t.Date < '2021-02-01' OR
t.date >= '2021-02-01' AND t.Date < '2021-03-01'
If your date ranges are months, you can join to the ranges and then aggregate by user:
select min(range_name), user_name, sum(amount)
from t join
(values ('2021-01-01', '2021-01-31', 'January'),
('2021-02-01', '2021-02-28', 'February')
) v(range_start, range_end, range_name)
on t.date >= v.range_start and t.date <= v.range_end
group by userid
having count(distinct range_name) = 1 and
sum(amount) > 100;
The having clause limits the results both by the number of ranges and by the amount.
If you just wants months between particular dates, I would simplify this to:
select datepart(month, min(date)), userid, sum(amount)
from t
where date >= '2021-01-01' and date < '2021-03-01'
group by userid
having count(distinct month(date)) = 1 and
sum(amount) > 100;

Counting an already counted column in SQL (db2)

I'm pretty new to SQL and have this problem:
I have a filled table with a date column and other not interesting columns.
date | name | name2
2015-03-20 | peter | pan
2015-03-20 | john | wick
2015-03-18 | harry | potter
What im doing right now is counting everything for a date
select date, count(*)
from testtable
where date >= current date - 10 days
group by date
what i want to do now is counting the resulting lines and only returning them if there are less then 10 resulting lines.
What i tried so far is surrounding the whole query with a temp table and the counting everything which gives me the number of resulting lines (yeah)
with temp_count (date, counter) as
(
select date, count(*)
from testtable
where date >= current date - 10 days
group by date
)
select count(*)
from temp_count
What is still missing the check if the number is smaller then 10.
I was searching in this Forum and came across some "having" structs to use, but that forced me to use a "group by", which i can't.
I was thinking about something like this :
with temp_count (date, counter) as
(
select date, count(*)
from testtable
where date >= current date - 10 days
group by date
)
select *
from temp_count
having count(*) < 10
maybe im too tired to think of an easy solution, but i can't solve this so far
Edit: A picture for clarification since my english is horrible
http://imgur.com/1O6zwoh
I want to see the 2 columned results ONLY IF there are less then 10 rows overall
I think you just need to move your having clause to the inner query so that it is paired with the GROUP BY:
with temp_count (date, counter) as
(
select date, count(*)
from testtable
where date >= current date - 10 days
group by date
having count(*) < 10
)
select *
from temp_count
If what you want is to know whether the total # of records (after grouping), are returned, then you could do this:
with temp_count (date, counter) as
(
select date, counter=count(*)
from testtable
where date >= current date - 10 days
group by date
)
select date, counter
from (
select date, counter, rseq=row_number() over (order by date)
from temp_count
) x
group by date, counter
having max(rseq) >= 10
This will return 0 rows if there are less than 10 total, and will deliver ALL the results if there are 10 or more (you can just get the first 10 rows if needed with this also).
In your temp_count table, you can filter results with the WHERE clause:
with temp_count (date, counter) as
(
select date, count(distinct date)
from testtable
where date >= current date - 10 days
group by date
)
select *
from temp_count
where counter < 10
Something like:
with t(dt, rn, cnt) as (
select dt, row_number() over (order by dt) as rn
, count(1) as cnt
from testtable
where dt >= current date - 10 days
group by dt
)
select dt, cnt
from t where 10 >= (select max(rn) from t);
will do what you want (I think)

Decrease Date for Average on this SQL

I want to query price average from my top 25 price sort by last date (and select some symbols).
I use this code, It's Work !!
SELECT AVG(PRICE)
FROM (SELECT PRICE FROM ms_data where SYMBOL='$symbol'
ORDER BY DATE DESC LIMIT 25) var;
If I don't want top date or 2 top date.
Example.
top date (lastest date) = 2014-04-16
2nd of top date = 2014-04-15
3rd of top date = 2014-04-4
...
I should not query first result,right?
I use this code but It doesn't work.
SELECT AVG(PRICE)
FROM (SELECT PRICE FROM ms_data where SYMBOL='$symbol' AND
NOT EXISTS (SELECT PRICE FROM ms_data where SYMBOL='$symbol'
ORDER BY DATE DESC LIMIT 1) ORDER BY DATE DESC LIMIT 26) var;
If use variable instead of limit.
SELECT AVG(PRICE)
FROM (SELECT PRICE FROM ms_data where SYMBOL='$symbol' AND
NOT EXISTS (SELECT PRICE FROM ms_data where SYMBOL='$symbol'
ORDER BY DATE DESC LIMIT $i) ORDER BY DATE DESC LIMIT 25+$i) var;
Any suggestion?
Thank you in advance.

SQL return a value at a specific date in time

I'm trying the find a value at a certain date.
My data looks like
Date Value
2013-11-02 5
2013-10-10 8
2013-09-14 6
2013-08-15 4
How can I determine what the value was on 2013-09-30?
Obviously the answer is 6 but I can't figure out the SQL code.
Thanks
You can do it with order by and limiting the number of rows. In SQL Server syntax (and Sybase and Access):
select top 1 t.*
from table t
where date <= '2013-09-30'
order by date desc;
In MySQL (and Postgres):
select t.*
from table t
where date <= '2013-09-30'
order by date desc
limit 1;
In Oracle:
select t.*
from (select t.*
from table t
where date <= '2013-09-30'
order by date desc
) t
where rownum = 1
EDIT:
And, a SQL standard way to it (should work in any database):
select t.*
from table t
where date = (select max(date)
from table t2
where date <= '2013-09-30'
);

Valid price at given date

got a table with dates and prices.
Date Price
2012-01-01 25
2012-01-05 12
2012-01-10 10
Is there some kind of function that lets me find what the current price where at '2012-01-07'? Without me knowing of the other dates.
Pseudoquery: select price where currentprice('2012-01-07')
Thanks!
MySQL:
select price from your_table
where date <= '2012-01-07'
order by date desc
limit 1
SQL Server:
select top 1 price from your_table
where date <= '2012-01-07'
order by date desc
If you don't have use of ROW_NUMBER(), and want a generic solution, you need to join on a sub-query.
Get the date you want, then get the data for that date.
SELECT
*
FROM
yourTable
INNER JOIN
(
SELECT MAX(yourDate) AS maxDate FROM yourTable WHERE yourDate <= #dateParameter
)
AS lookup
ON yourTable.yourDate = lookup.maxDate
select price
from table1 t
where t.date = ( select max(t2.date)
from table1 t2
where t2.date <= '2012-01-07' )
Note this is not the copy&paste answer, as we're not not knowing what is the datatype for your date column.