SQL Earliest hour for every day - sql

I have table like this
And I want to have only earliest time from column time for each day from column date. Rest of table has to be unaffected.
So result would be that for example that I have only time 9:25 for 2018-07-13 and rest of rows with later times for 2018-07-13 are deleted

To delete you can use a CTE with ROW_NUMBER window function
;WITH cteDups
AS(
SELECT *, RN=ROW_NUMBER()OVER (PARTITION BY M.Date ORDER BY M.Time ASC)
FROM dbo.yourtable M
)
--SELECT *
DELETE
FROM cteDups D WHERE D.RN > 1

You can use a window function to return all rows
select
*,
min([time]) over (partition by [date] order by [time])
from YourTable
Or just the aggregate to remove them
select *
from YourTable
inner join
(select whatever, min(FullDate) dt
from yourtable
group by whatever) x on x.whatever = YourTable.whatever and x.dt = YourTable.FullDate
If the whatever column doesn't matter, and you only want the date and time:
Select
[date],
min([time])
from YourTable
group by [Date]

The simplest way to keep certain records and remove the rest would be by using a CTE with a windowing function to rank (or add rownumbers). Check this out:
;WITH EarliestHourEveryDay AS (
SELECT
whatever
,FullDate
,[date]
,[time]
,rn = ROW_NUMBER() OVER (PARTITION BY [date] ORDER BY [time])
FROM TableName
)
SELECT *
FROM EarliestHourEveryDay
WHERE rn = 1
/*
DELETE FROM EarliestHourEveryDay
WHERE rn > 1
*/
I have commented out the delete statement so that you can test this first. Run the CTE as-is, and if the result set contains the exact rows which you want, remove the SELECT statement from the CTE and uncomment the DELETE statement and you'll be good to go.

Group by day and select the MIN time.

Use the MIN function and a GROUP BY clause.
Something like:
SELECT date, MIN(time) AS EarliestTime
FROM MyTable
GROUP BY date
ORDER BY date ASC
Here is an example of this working: SQL Fiddle

Related

Finding 2nd to last date with SQL

I'm trying to find the 2nd to last date using the below query to get all unique dates.
SELECT DISTINCT CAST(Entrydatetime AS DATE)
FROM [table_name]
This returns
2017-11-15
2017-11-16
2017-11-17
2017-11-20
The [table_name] contains many rows, many that are all on the same dates listed above. (200 records with '2017-11-20' and 180 with '2017-11-17' etc..)
So is there a way to just grab the 2nd to last item given from the above query?
If this were an array I could do something like '$array[-2]'
So in this instance it would pull 2017-11-17.
Any help would be appreciated
You can use ROW_NUMBER to rank your dates:
select dt
from
(
select distinct
cast(entrydatetime as date) as dt,
row_number() over (order by cast(entrydatetime as date) desc) as rn
from table_name
) ranked
where rn = 2;
If using SQL Server, you can use the following query:
with cte as
(
select DISTINCT Convert(Date,Entrydatetime) ,
ROW_NUMBER() over (order by Convert(Date,Entrydatetime) DESC) as rn
from [table name]
)
select * from cte where rn=2
Or you can do it another way
SELECT MAX(Convert(Date,Entrydatetime))
FROM [table name]
WHERE Convert(Date,Entrydatetime) < (SELECT MAX(Convert(Date,Entrydatetime) ) FROM [table name])
Here's an example using a CTE. I think the DISTINCT EntryDate has to be taken- cast to date to remove time- then the rownumber applied. Notice I am using two different times for 2017-11-20, 12:00:00 and 13:00:00. The ORDER BY cannot do this correctly if you have DISTINCT in the select... this requires a subquery.
DECLARE #tablename TABLE (Entrydatetime datetime)
INSERT INTO #tablename VALUES ('2017-11-15 12:00:00')
,('2017-11-16 12:00:00')
,('2017-11-17 12:00:00')
,('2017-11-20 12:00:00')
,('2017-11-20 13:00:00')
;
WITH cte AS
(
SELECT ROW_NUMBER() OVER(ORDER BY EntryDate DESC) [theOrder]
,dT.EntryDate
FROM (
SELECT DISTINCT CAST(Entrydatetime as date) AS EntryDate
FROM #tablename
) AS dT
)
SELECT cte.EntryDate FROM cte WHERE theOrder = 2
Gives output:
EntryDate
2017-11-17

Filter the table with latest date having duplicate OrderId

I have following table:
I need to filter out the rows for which start date is latest corresponding to its order id .With reference to given table row no 2 and 3 should be the output.
As row 1 and row 2 has same order id and order date but start date is later than first row. And same goes with row number 3 and 4 hence I need to take out row no 3 . I am trying to write the query in SQL server. Any help is appreciated.Please let me know if you need more details.Apologies for poor English
You can do this easily with a ROW_NUMBER() windowed function:
;With Cte As
(
Select *,
Row_Number() Over (Partition By OrderId Order By StartDate Desc) RN
From YourTable
)
Select *
From Cte
Where RN = 1
But I question the StartDate datatype. It looks like these are being stored as VARCHAR. If that is the case, you need to CONVERT the value to a DATETIME:
;With Cte As
(
Select *,
Row_Number() Over (Partition By OrderId
Order By Convert(DateTime, StartDate) Desc) RN
From YourTable
)
Select *
From Cte
Where RN = 1
Another way using a derived table.
select
t.*
from
YourTable t
inner join
(select OrderId, max(StartDate) dt
from YourTable
group by OrderId) t2 on t2.dt = t.StartDate and t2.OrderId = t.OrderId

Select Record with Maximum Creation Date

Let us say that I have a database table with the following two records:
CACHE_ID BUSINESS_DATE CREATED_DATE
1183 13-09-06 13-09-19 16:38:59.336000000
1169 13-09-06 13-09-24 17:19:05.762000000
1152 13-09-06 13-09-17 14:18:59.336000000
1173 13-09-05 13-09-19 15:48:59.136000000
1139 13-09-05 13-09-24 12:59:05.263000000
1152 13-09-05 13-09-27 13:28:59.332000000
I need to write a query that will return the CACHE_ID for the record which has the most recent CREATED_DATE.
I am having trouble crafting such a query. I can do a GROUP BY based on BUSINESS_DATE and get the MAX(CREATED_DATE)...of course, I won't have the CACHE_ID of the record.
Could someone help with this?
Not positive on oracle syntax, but use the ROW_NUMBER() function:
SELECT BUSINESS_DATE, CACHE_ID
FROM (SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY BUSINESS_DATE ORDER BY CREATED_DATE DESC) RN
FROM YourTable t
)sub
WHERE RN = 1
The ROW_NUMBER() function assigns a number to each row. PARTITION BY is optional, but used to start the numbering over for each value in that group,  ie: if you PARTITION BY BUSINESS_DATE  then for each unique BUSINESS_DATE value the numbering would start over at 1.  ORDER BY of course is used to define how the counting should go, and is required in the ROW_NUMBER() function.
You want to group on business date, and get the CACHE_ID with the most current created date? Use something like this:
select yt.CACHE_ID, yt.BUSINESS_DATE, yt.CREATED_DATE
from YourTable yt
where yt.CREATED_DATE = (select max(yt1.CREATED_DATE)
from YourTable yt1
where yt1.BUSINESS_DATE = yt.BUSINESS_DATE)
Not sure of the exact syntax, but conceptually, can't you just sort by CREATED_DATE descending and take the first one?
Across all records -
select top 1 CACHE_ID from YourTable order by CREATED_DATE desc
For each BUSINESS_DATE -
select distinct
a.BUSINESS_DATE,
(
select top 1 b.CACHE_ID
from YourTable b where a.BUSINESS_DATE = b.BUSINESS_DATE
order by b.CREATED_DATE desc
) as Last_CREATED_DATE
from YourTable a

Sort result when using ROW_NUMBER()

This is a follow-up to this question I asked yesterday.
I did not know if I should expand my original question, I decided to start a new one (bear with me...)
My SELECT is like this at the moment:
SELECT *
FROM
(
SELECT
a.guid_column1, b.guidID_column1, c.date_column1, d.guid_column1
ROW_NUMBER() OVER (PARTITION BY a.guid_column1, b.guid_column1 ORDER BY c.date_column1 DESC) as rn
...
-- JOINS AND WHERE STUFF HERE
....
) t
WHERE t.rn = 1
I get the (expected) result like this:
a.guid_column1 b.guid_column1 c.date_column1 d.guid_column1
-------------------------------------------------------------------
a1 b1 07/08/2013 someUniqueID
a2 b2 05/06/2012 someUniqueID
The tricky part is that I would like to sort that result by a dateadd, something like this ORDER BY dateadd(month, a.float_column, c.date_column1) asca.float_column is of course not always the same (and is in fact entered by the user later on).
Is there a way to accomplish this in SQL (I'm using SQL Server 2005)
Below query will calculate the new date in the SELECT-CLAUSE.
If a.float_column is NULL nothing will be added to the original date.
SELECT dateadd(month, ISNULL(t.float_column,0), t.date_column1) as newDate
, *
FROM
(
SELECT
a.guid_column1, b.guidID_column1, c.date_column1, d.guid_column1, a.float_column
ROW_NUMBER() OVER (PARTITION BY a.guid_column1, b.guid_column1 ORDER BY c.date_column1 DESC) as rn
...
-- JOINS AND WHERE STUFF HERE
....
) t
WHERE t.rn = 1
ORDER BY newDate ASC
why don't you just add column into your subquery?
select *
from
(
select
a.guid_column1, b.guidID_column1, c.date_column1, d.guid_column1,
dateadd(month, a.float_column, c.date_column1) as sort_order,
row_number() over (partition by a.guid_column1, b.guid_column1 order by c.date_column1 desc) as rn
--
-- JOINS AND WHERE STUFF HERE
--
) t
where t.rn = 1
order by t.sort_order asc

Get Dates on multiple calls

I have a log table that records dates.
I want to find out the date of the Second and Third call.
I get the first call by using MIN(DateCreated)
I get the last date using MAX(DateCreated). This could also be the second call.
What is the best way to find out the date of the second and third call?
I would just get all 3 rows together in one query
SELECT TOP 3 *
FROM LogTable
ORDER BY LogDate ASC -- DESC if you need the last 3
If you do need them one by one, you can use:
WITH LogByDate AS
(
SELECT LogDate,
ROW_NUMBER() OVER (ORDER BY LogDate) AS 'RowNumber'
FROM LogTable
)
SELECT *
FROM LogByDate
WHERE RowNumber = 2; -- RowNumber=3 for the third line
Try using analytical functions:
;WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY CallId ORDER BY DateCreated) Corr
FROM dbo.YourTable
)
SELECT *
FROM CTE
WHERE Corr IN (2,3)