Need last 30 days of data in library database - sql

I need the magazines that were added to this database for the last 30 days. I have tried the following:
SELECT A.TITLE, A.EDITION, B.DONATEDBY, B.DATE_ADDED
FROM LIBRARY A
JOIN LIB_COPIES B ON A.IDNO=B.IDNO
WHERE A.TYPE LIKE '%Magazine%'
AND B.DONATEDBY LIKE '%State%'
AND B.DATE_ADDED>CURRENT_DATE-31
ORDER BY B.DATE_ADDED
It doesn't get any entries from today's date.
I have tried
DATEDIFF(dateColumn, CURRENT_TIMESTAMP) BETWEEN 0 AND 30
AND >= DATEADD(day, -30, GETDATE())
I am new to this forgive me if in wrong format. I put B.Date_added for that is my column, where I felt it should be.
Please help me!

Assuming you're using MySQL, CURRENT_DATE-31 does not subtract 31 days from the current date. Instead it converts CURRENT_DATE to an integer and subtracts 31.
select CURRENT_DATE, CURRENT_DATE - 31;
CURRENT_DATE CURRENT_DATE - 31
2020-01-10 20200079
Instead, use date_sub(current_date, interval 31 day).
select CURRENT_DATE, date_sub(CURRENT_DATE, interval 31 day);
CURRENT_DATE date_sub(CURRENT_DATE, interval 31 day)
2020-01-10 2019-12-10
Or if you mean 1 month, use interval 1 month.
DATEDIFF(dateColumn,CURRENT_TIMESTAMP) BETWEEN 0 AND 30 does not work because when dateColumn is in the past the diff will be negative.
select DATEDIFF("2020-01-01",current_date);
DATEDIFF("2020-01-01",current_date)
-9
Instead, reverse the order of the dates.
select DATEDIFF(current_date, "2020-01-01")
DATEDIFF(current_date, "2020-01-01")
9

Related

Search Last 7 days excluding today Oracle SQL

I have the below code to which I want to return the last 7 days excluding today (for example from 5th May - 11th May as opposed to 5th May - 12th May)
What else would I be able to include to acheive this?
SELECT *
FROM TABLE_1
WHERE DATE_TIME >= SYSDATE -7
You want to have a range that starts from 7 days before midnight today and ends before midnight today:
SELECT *
FROM table_name
WHERE date_time >= TRUNC(sysdate) - 7
AND date_time < TRUNC(sysdate);
This should work:
SELECT *
FROM TABLE_1
WHERE DATE_TIME >= SYSDATE -7
AND TRUNC(DATE_TIME) != TRUNC(SYSDATE)
The TRUNC is needed to strip the time portion of the date column and sysdate.
Note that DATE_TIME >= SYSDATE -7 will include the time portion of SYSDATE and substract 7 days. If you run the query at 10AM, do you want to include rows that have date_time = sysdate - 7 at 9AM too ? If so it is better to add a TRUNC there too DATE_TIME >= TRUNC(SYSDATE) -7.

Can I search between two dates in SQL using DATE_TRUNC and INTERVAL?

Here is what I have working:
select date_trunc('hour', 123.created_at) AS trunc_created_at
FROM 123abc 123
WHERE 123.expires_at > date_trunc('day', GETDATE()) + INTERVAL '2 days'
Is it possible, from here, to then do an 'and' or 'between' to do something like
and 123.expires_at < date_trunc('day', GETDATE()) + INTERVAL '28 days'
Obviously, that doesn't work, but is there a way to do this using number of days instead of a specific date? I'm pretty new to SQL and have been playing with this for 30 minutes, including a dozen google queries, and can't seem to find a way to make something like this work. Only using between and a specific date range.
If you are just trying to look back 28 days you can just subtract that from GETDATE
SELECT CAST(GETDATE() - 28 AS DATE)
So if you wanted to look back 28 days it would be something like this
SELECT
*
FROM TABLE
WHERE 1=1
AND DATE BETWEEN GETDATE() AND GETDATE() - 28
I figured out how to do what I wanted
WHERE 123.expires_at > (date_trunc('day', GETDATE()) + INTERVAL '2 days') AND 123.expires_at < (date_trunc('day', GETDATE()) + INTERVAL '21 days')

Get the number of remaining days after excluding date ranges in a table

create table test (start date ,"end" date);
insert into test values
('2019-05-05','2019-05-10')
,('2019-05-25','2019-06-10')
,('2019-07-05','2019-07-10')
;
I am looking for the following output, where for every date between the start and end the person is available only between start and end. considering for the month of may he is present for 11 days(05/05 to 05/10 and 05/25 to 05/31) and the total number of days in the month of may is 31. The output column should have 31-11 (the number of days he worked)
MonthDate------Days-
2019-05-01 20(31-11)
2019-06-01 20(30-10)
2019-07-01 26(31-5)
I get slightly different results.
But the idea is to generate every date. Then filter out the ones that are used and aggregate:
select date_trunc('month', dte) as yyyymm,
count(*) filter (where t.startd is null) as available_days
from (select generate_series(date_trunc('month', min(startd)), date_trunc('month', max(endd)) + interval '1 month - 1 day', interval '1 day') dte
from test
) d left join
test t
on d.dte between t.startd and t.endd
group by date_trunc('month', dte)
order by date_trunc('month', dte);
Here is a db<>fiddle.
The free days in May are:
1
2
3
4
11
12
13
14
15
16
17
18
19
20
21
22
23
24
I am counting 18 of these. So, I believe the results from this query.
If you do not want to include the end date (which is contrary to your description using "between", then the on logic would be:
on d.dte >= t.startd and
d.dte < t.endd
But that would only get you up to 19 in May.
Your results are inconsistent. I decided to go with inclusive bounds for the simplest solution:
SELECT date_trunc('month', d)::date, count(*)
FROM (
SELECT generate_series(timestamp '2019-05-01', timestamp '2019-07-31', interval '1 day') d
EXCEPT ALL
SELECT generate_series(start_date::timestamp, end_date::timestamp, interval '1 day') x
FROM test
) sub
GROUP BY date_trunc('month', d);
date_trunc | count
-----------+------
2019-05-01 | 18
2019-06-01 | 20
2019-07-01 | 25
db<>fiddle here
This generates all days of a given time frame (May to July of the year in your case) and excludes the days generated from all your date ranges.
Assuming at least Postgres 10.
What is the expected behaviour for multiple set-returning functions in SELECT clause?
Assuming data type date in your table. I cast to timestamp for best results. See:
Generating time series between two dates in PostgreSQL
Aside: don't use the reserved words start and end as identifiers.
Related:
Select rows which are not present in other table

MSSQL query for all records between two date range of current day

I might not be asking this right, but basically I need a query that when ran, returns all records entered from the 1st till the 15th of the current month. And when the 15 passes only return the records from the 16th till the end of the current month.
I've tried to build something like this but its for bigquery and not sql, and I can't seem to find something similar for mssql 2016.
select sample_id
from dbo.table
WHERE date_entered BETWEEN DATE_ADD(CURRENT_DATE(), -15, 'DAY') AND CURRENT_DATE()
or
WHERE date_entered BETWEEN CAST(eomonth(GETDATE()) AS datetime) AND CURRENT_DATE()
Regardless of the today's date, I need the 1st till today, until the 15th. Then the 16th till today, until the end of the month. Sorry I'm new to SQL.
UPDATE: I was able to solve this issue with the example provided by #GordonLinoff . Thank you Gordon!
SELECT rowguid, ModifiedDate
FROM [AdventureWorks2017].[Person].[Person]
WHERE Year(ModifiedDate) =Year(getdate()) and month(ModifiedDate) =month(getdate()) and
((day(getdate()) <= 15 and day(ModifiedDate) <=15))
Or
((day(getdate()) >= 16 and day(ModifiedDate) >=16))
The description of your logic is a bit hard to follow, but you seem to want something like this:
where date_entered >= datefromparts(year(getdate(), month(getdate(), 1)) and -- this month
(day(getdate()) <= 15 or
day(getdate()) > 15 and day(date_entered) > 15
)
This was MySQL:
SELECT *
FROM dbo.table
WHERE date BETWEEN CASE WHEN DAY(CURRENT_DATE) <= 15
THEN DATE_FORMAT(CURRENT_DATE, '%Y-%m-01')
ELSE DATE_FORMAT(CURRENT_DATE, '%Y-%m-16')
END
AND CASE WHEN DAY(CURRENT_DATE) <= 15
THEN DATE_FORMAT(CURRENT_DATE, '%Y-%m-15')
ELSE LAST_DAY(CURRENT_DATE)
END
Big Query:
SELECT *
FROM table
WHERE date BETWEEN CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) <= 15
THEN DATE_TRUNC(CURRENT_DATE, MONTH)
ELSE DATE_ADD(DATE_TRUNC(CURRENT_DATE, MONTH), INTERVAL 15 DAY)
END
AND CASE WHEN EXTRACT(DAY FROM CURRENT_DATE) <= 15
THEN DATE_ADD(DATE_TRUNC(CURRENT_DATE, MONTH), INTERVAL 14 DAY)
ELSE DATE_ADD(CURRENT_DATE, INTERVAL 31 DAY)
END
This should give
date between 1 and 15
or date between 16 and last_of_the_month
I've tried to build something like this but its for bigquery
Whatever example you use - it is not working in BigQuery either!
Below is working example for BigQuery Standard SQL and uses some "tricks" to avoid using redundant code fragments
#standardSQL
SELECT sample_id
FROM `project.dataset.table`,
UNNEST([STRUCT(
EXTRACT(DAY FROM date_entered) AS day,
DATE_TRUNC(date_entered, MONTH) AS month
)])
WHERE DATE_TRUNC(CURRENT_DATE(), MONTH) = month
AND IF(
EXTRACT(DAY FROM CURRENT_DATE()) < 16,
day BETWEEN 1 AND 15,
day BETWEEN 16 AND 99
)

SQL abstract out date and find the next one this week

I have a set of records which store weekly events by using a datetime... start_at from the first week they began.
It's not the REAL DATE, it's storing the DAY (DOW) and TIME, but is not the date I'm actually looking for.
I'm trying to figure out how I can convert/abstract the start_at date in a way so using that I can find all of the next events that fall within the next 24 hours.
START_AT -> 2010-09-12 16:00:00 -> CONVERT into 2013-09-08 16:00:00
but I'm not sure how to abstract the start_at for the upcoming day of the week.
I figured out how to order them but I'm not sure how to do what I want:
SELECT * FROM events ORDER BY (EXTRACT(dow FROM start_at)::int + 7 - EXTRACT(dow FROM now())::int) % 7,start_at::time
Any help would be greatly appreciated!
If you mean the next 24 hours:
SELECT *
FROM events
WHERE start_at BETWEEN now() AND now() + INTERVAL '1 day'
If you mean the next 24 hour period starting at midnight (i.e. all day tomorrow):
SELECT *
FROM events
WHERE start_at BETWEEN now()::date + INTERVAL '1 day' AND
now()::date + INTERVAL '2 days'
If I understand you correctly you may be over thinking it. If all you're looking for is a recurring datetime 24 hour before you could do something like:
SELECT * FROM events EXTRACT(dow FROM start_at) = 1
Where 1 is the DOW (for Monday)... you abstract the DOW from the date
The day of the week as Sunday(0) to Saturday(6)
and unless you very fussed about the Time, you could just search for the DOW before the day you want (~24 hours).
If I've understood you correctly, you store the date a recurring event starts on, and you need to know which recurring events happen in the next 24 hours.
This is probably easiest to handle with a join on a calendar table. The CTE "events" below takes the place of whatever your table is called. It stores events we expect to recur weekly, starting on Jan 3, Jan 4, and Jan 5. As I write this, it's Thursday.
with events as (
select date '2013-01-03' start_at
union all
select date '2013-01-04'
union all
select date '2013-01-05'
), event_days as (
select events.start_at, c.day_of_week
from events
inner join calendar c on c.cal_date = events.start_at
)
select *
from event_days
inner join calendar on event_days.day_of_week = calendar.day_of_week
where cal_date between current_date and current_date + interval '1 days';
start_at day_of_week cal_date year_of_date month_of_year day_of_month day_of_week
2013-01-03 Thu 2013-09-12 2013 9 12 Thu
2013-01-04 Fri 2013-09-13 2013 9 13 Fri
Code for a calendar table in PostgreSQL.
"The next 24 hours" is a little fuzzy if you're storing just the date.