How to get the date for two saturdays ago - sql

I have the following query which displays a table with date:
SELECT *
FROM [Db].[dbo].[btotals]
ORDER BY [Date] DESC
Which displays:
Date
06/07/2014
05/31/2014
05/24/2014
05/17/2014
05/10/2014
05/03/2014
If I pick SELECT TOP 1 will give me the first row. How can I modify my query so I get the week prior to last week? In this case the 5/31/14 row?

If your dates are always a week apart, and you just want the second row you can use ROW_NUMBER():
SELECT Date
FROM ( SELECT Date,
RowNumber = ROW_NUMBER() OVER(ORDER BY Date DESC)
FROM [Db].[dbo].[btotals]
) AS d
WHERE d.RowNumber = 2;
Otherwise you can use the following to get the saturday of 2 weeks ago:
SELECT DATEADD(DAY, -((DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7) - 7, CAST(GETDATE() AS DATE));
Then select your first date that is on or after that:
SELECT TOP 1 Date
FROM [Db].[dbo].[btotals]
WHERE Date >= DATEADD(DAY, -((DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7) - 7, CAST(GETDATE() AS DATE))
ORDER BY Date;

This should also work, if you are trying to select the second date, Though Gareth's approach of using ROW_NUNMBER is a better one.
SELECT TOP 1 *
FROM (
SELECT TOP 2 *
FROM [Db].[dbo].[btotals]
ORDER BY [Date] DESC
) as X
ORDER BY Date ASC

Another approach:
SELECT TOP 1 *
FROM [Db].[dbo].[btotals]
WHERE [Date] < (SELECT MAX([Date]) FROM [Db].[dbo].[btotals])
ORDER BY [Date] DESC

Related

Select Table of Days For One Year SQLITE

I am trying to select a table of every date for the last year.
In SQL Server, I can run something like this:
SELECT TOP (DATEDIFF(DAY, DATEADD(YEAR, - 1, GETDATE()), GETDATE()) + 1)
Date = CAST(DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY a.object_id) - 1, DATEADD(YEAR, - 1, GETDATE())) AS DATE)
FROM sys.all_objects a
It returns 1 column with 366 rows containing the dates from 1 year ago until now.
I am looking for something equivalent in SQLITE.
You can do it with a recursive CTE:
WITH cte AS (
SELECT DATE(CURRENT_DATE, '-1 year') date
UNION ALL
SELECT DATE(date, '+1 day')
FROM cte
WHERE date < CURRENT_DATE
)
SELECT * FROM cte;
See the demo.
You can also do this using an inline tally table
WITH L1(n) AS (
VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
),
L2(n) AS (
SELECT 1 FROM L1 a CROSS JOIN L1 b
)
SELECT DATE(CURRENT_DATE, (-ROW_NUMBER() OVER (ORDER BY 1) + 1) || ' days') AS date
FROM L2
LIMIT julianday(CURRENT_DATE) - julianday(DATE(CURRENT_DATE, '-1 year')) + 1;
db<>fiddle
For newer versions of SQLite you may want to add NOT MATERIALIZED to the CTEs.

How to subtract an offset to dates generated through a recursive CTE?

The query below uses a recursive CTE to generate days if there is no data for that specific day. I want to group the daily downtime total starting at 7:15 the previous day until 7:15 the next day and do it over a month. This query works fine but I need to subtract DATEADD(minute, -(7 * 60 + 15) from each day.
WITH dates as (
SELECT CONVERT(date, 'Anydate') as dte
UNION ALL
SELECT DATEADD(day, 1, dte)
FROM dates
WHERE dte < 'Anydate + 1 month later'
)
SELECT CONVERT(datetime,d.dte), ISNULL(SUM(long_stop_minutes), 0) AS downtime
FROM dates d LEFT JOIN
long_stops_table b
ON CAST(t_stamp as DATE) = d.dte AND Type = 'downtime'
GROUP BY CONVERT(datetime, d.dte)
ORDER BY CONVERT(datetime, d.dte) ASC;
Just subtract the appropriate time units. Here is one way:
SELECT d.dte,
COALESCE(SUM(lst.long_stop_minutes), 0) AS downtime
FROM dates d LEFT JOIN
long_stops_table lst
ON CONVERT(date, DATEADD(minute, -(7 * 60 + 15), lst.t_stamp) = d.dte AND
lst.Type = 'downtime'
GROUP BY d.dte
ORDER BY d.dte ASC;
I see no reason to convert dates.dte to a datetime, so I just removed the conversion.

How can I select one row of data per hour?

I'm new at sql.
There is something that makes me confused, i got data per minute, but i only need a row of it per hour or per 2 hours. For example when i select data from the previous day, it shows me 1440 rows and i need to reduce them to less rows to make some charts.
Thanks in advance.
when i use this query:
select [Value],[Time] from [AbsoluteData] where [Sensor] = '5100' and [Time] >= dateadd(day,datediff(day,1,GETDATE()),0) AND[Time] < dateadd(day, datediff(day, 0, GETDATE()), 0)
i got:
You can select on row per hour by using row_number() like this:
select t.*
from (select t.*,
row_number() over (partition by cast(datetimecol as date), datepart(hour, datetimecol)
order by datetimecol
) as seqnum
from t
) t
where seqnum = 1;
I cannot read your image and you don't have a sample query or sample data, so this uses generic names.
If the data drops in every minute and you want just one within a given range (last hour or last day), just restrict the rows to the range and pick 1:
select top 1
[Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
(last one yesterday)
or:
set rowcount 1;
select [Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
set rowcount 0;

How can I select the 1st of every month for the last 5 years in sql?

I am trying to get a list of the 1st of the Month for the last 5 years. How can i do that ?? I have a select statement:
select convert(varchar(10), dateadd(mm,Datediff(mm,0,getdate()),0),111) as StartDate
but i am not sure how to get a list for every month.
with dates
as (
select dateadd(month, datediff(month, 0, getdate()), 0) as date
union all
select dateadd(month, - 1, date)
from dates
)
select top 60 *
from dates
with cte as (
select DATEFROMPARTS ( datepart(yyyy,getdate()), datepart(mm,getdate()), 1 ) as startdate
union all
select dateadd(month,-1,startdate) from dates
where datediff(year,startdate,getdate()) <> 5 )
select CONVERT ( varchar(12), startdate , 107 ) from cte;

Get a table of dates of last 14 days (2 weeks) starting from previous day

I want to write a query which gives a coloumn of DATES of last 14 days
starting from yesterday.
Example:
Dates
2012-06-21
2012-06-20
2012-06-19
--
-
;WITH n(n) AS
(
SELECT TOP (14) ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.objects ORDER BY [object_id]
)
SELECT Dates = DATEADD(DAY, -n, DATEDIFF(DAY, 0, GETDATE())) FROM n
ORDER BY n;
Another way;
;with days(day) as
(
select getdate() - 1 as day
union all
select day - 1
from days
where day > dateadd(day, -14, getdate())
)
select cast(day as date) from days