Get Top 3 Records By Date By Day SQL Server 2012 - sql

I have table with rows that look like this:
DateTime, Field1, Field2, Field3
I want to get the TOP 3 records by date, by day. For one record I would execute
SELECT TOP(3) *
FROM tum
I need that for each day. I am assuming I would use partition or cross apply, but the actual syntax for this is not clear to me.

You would use row_number():
select t.*
from (select t.*,
row_number() over (partition convert(date, datetime) order by ?) as seqnum
from t
) t
where seqnum <= 3;

Related

MSSQL How Can I Get the latest Amount

How can I get the Latest amount, I already had some queries but instead it shows two records ,Im expecting to show only the the '7370' current amount
you can use correlated subquery
select * from tablename a where lasttime in (select max(lasttime) from tablename b where a.id=b.id)
OR you can use row_number()
select * from
(
select *,row_number() over(partition by id order by lasttime desc) as rn from tablename
)A where rn=1
Just add Top 1 before your fields.
Select TOP 1 fields from table
SELECT TOP 1 currentBalance FROM DBO.tbl_billing ORDER BY [date]

Select Max() is too slow

I am trying to get the latest date from a column in SQL Server 2016 but it takes near 10 seconds to retrieve this data. The table has over 146 million records.
Combined with other queries that I have to run the code takes over 1 minute to complete.
How can I make this query faster?
DECLARE #MaxDate DATE
SELECT #MaxDate = MAX(MyDate)
SELECT COUNT(*) FROM MyTable
I have even tried
SELECT c.*
FROM (SELECT MyDate, COUNT(*) as TheDate,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM MyTable
GROUP BY MyDate
) c
WHERE seqnum = 1;
and it is the same speed
If you want the max date quickly, then create an index on that column, (mydate).
You should be able to do:
select max(mydate)
from t;
Or if you want all the rows:
select top (1) with ties t.*
from t
order by mydate desc;

SQL Earliest hour for every day

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

SQL query to get maximum value for each day

So I have a table that looks something like this:
Now, I want the max totalcst for both days, something like this:
I tried using different variations of max and the Row_number funtion but still can't seem to get the result I want. My query:
select date,pid,max(quan*cst), totalcst
from dbo.test1
group by date, pid
But this returns all the records. So if somebody can point me towards the right direction, that would be very helpful.
Thanks in advance!
ROW_NUMBER should work just fine:
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY [date] ORDER BY totalcst)
FROM dbo.YourTable
)
SELECT [date],
pid,
totalcst
FROM CTE
WHERE RN = 1
;
Here is one simple way:
select t.*
from test1 t
where t.totalcst = (select max(t2.totalcst) from test1 t2 where t2.date = t.date);
This often has the best performance if you have an index on (date, totalcst). Of course, row_number()/rank() is also a very acceptable solution:
select t.*
from (select t.*, row_number() over (partition by date order by totalcst desc) as seqnum
from test1
) t
where seqnum = 1;

Get rows from the table using row no in sql server

I want to get rows from 100-150 from my table in sql server 2008, how i can do that? Is there any way to do so? as much i search Limit keyword is available in mysql but for sql server use common table technique but i don't want to do like that is there any other way available as it is available in Mysql?
select * from
(select row_number() over (order by #column) as row,* from Table) as t
where row between 100 and 150
#column to be replaced by a colomn from your table witch well be used to order the result
use sql limit
http://php.about.com/od/mysqlcommands/g/Limit_sql.htm
In SQL 2005 and above there is a ROW_NUMBER() function. If you need something that works for both MySQL and SQL Server though then I don't know if this is available in MySQL as I've never used it.
http://msdn.microsoft.com/en-us/library/ms186734.aspx
The example given in the linked page that seems most relevant is the following, where the results of a query are ordered by date, and then rows 50 to 60 from that result set are returned.
USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
FROM Sales.SalesOrderHeader
)
SELECT SalesOrderID, OrderDate, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;
Actuall, the least expensive way to do this is using top, and then row_number()
select *
from (select *, row_number() over (order by (select NULL)) as rownum
from (select top 150 t.*
from t
) t
) t
where rownum >= 100
However, I do give you one caution. There is no such thing as rows 100-150 in a relational table, because these are inherently unordered. You need to specify the ordering. For this, you need order by:
select *
from (select *, row_number() over (order by <field>) as rownum
from (select top 150 t.*
from t
order by <field>
) t
) t
where rownum >= 100