How can I generate last three transactions from the below table?
Date Tran dr cr total
-------------------------------------
2017-04-13
2017-07-15
2017-07-15
2017-10-17
2017-10-17 abc 10 10
2017-11-12 def 10 20
2017-11-12 ghi 5 15
I'm using SQL Server 2012
Like this you should your expected result:
SELECT * FROM
(
SELECT TOP 3 *
FROM TransactionTable
ORDER BY [Date] DESC
) AS t
ORDER by t.[Date]
if your requirement is to get the 3 transactions with the latest date. you can use either of the following.
Simple Order by :
select
top 3
* from YourTable
where isnull(Tran,'')<>''
order by [Date] desc
using Row Number
;with cte
as
(
select
seqno = row_number() over(order by [date] desc),
*
from YourTable
where isnull(Tran,'')<>''
)
select
* from cte
where SeqNo <=3
order by SeqNo desc
Related
I have a table like below
ID Code Age
----------------
1 4758 21
1 7842 14
1 9821 23
1 6842 9
2 8472 24
2 7558 31
2 7841 28
3 7881 38
3 8794 42
3 4871 43
For each ID, I want to select one of the rows at random like so
ID Code Age
----------------
1 7842 14
2 7841 28
3 4871 43
Is this possible in SQL Server?
select top 1 with ties id,code,age
from
table
order by row_number() over (partition by id order by rand())
Update: as per this Return rows in random order, you have to use NEWId,since RAND() is fixed for the duration of the SELECT on MS SQL Server.
select top 1 with ties id,code,age
from
table
order by row_number() over (partition by id order by NEWID())
Use Newid() in order by clause of Row_number()
SELECT [ID], [Code], [Age]
FROM (SELECT *,
Row_number()
OVER(
PARTITION BY ID
ORDER BY Newid()) RNO
FROM #Table1)A
WHERE RNO = 1
with cte as
(
select *,rank() over ( partition by id order by Newid()) as rn from #c
)
select id,code,age from cte where rn=1
To select different sets each time, use checksum(newid()) in the order by clause.
Query
;with cte as(
select *, rn = row_number() over(
partition by ID
order by abs(checksum(newid())) % 15
)
from [your_table_name]
)
select * from cte
where rn = 1;
I have table like this:
id_Seq_No emp_name Current_Property_value
-----------------------------------------------
1 John 100
2 Peter 200
3 Pollard 50
4 John 500
I want the max record value of particular employee.
For example, John has 2 records seq_no 1, 4. I want 4th seq_no Current_Property_Value in single query.
Select
max(id_Seq_No)
from
t1
where
emp_name = 'John'
To get the Current_Property_value, just order the results by id_Seq_No and get the first one:
SELECT
TOP 1 Current_Property_value
FROM
table
WHERE
emp_name = 'John'
ORDER BY
id_Seq_No DESC
this will give highest for all tied employees
select top 1 with ties
id_Seq_No,emp_name,Current_Property_value
from
table
order by
row_number() over (partition by emp_name order by Current_Property_value desc)
You can use ROW_NUMBER with CTE.
Query
;WITH CTE AS(
SELECT rn = ROW_NUMBER() OVER(
PARTITION BY emp_name
ORDER BY id_Seq_No DESC
), *
FROM your_table_name
WHERE emp_name = 'John'
)
SELECT * FROM CTE
WHERE rn = 1;
I know how to use MAX() function and GROUP BY clause in sql query but, in my case the records i want to group is bit different.
for example I have a following table
HostName ModifyDate Sr No
-------------------------------------------
PC-1 2015-12-04 08:45:52.847 1
PC-1 2015-12-04 08:48:51.025 2
PC-2 2015-12-04 08:50:01.125 3
PC-2 2015-12-04 08:50:45.545 4
PC-2 2015-12-04 08:53:44.897 5
PC-1 2015-12-04 09:02:17.524 6
PC-2 2015-12-04 09:18:36.788 7
PC-2 2015-12-04 09:22:01.041 8
PC-1 2015-12-04 09:31:41.744 9
And the result should be like this
HostName ModifyDate Sr No
------------------------------------------
PC-1 2015-12-04 08:48:51.025 2
PC-2 2015-12-04 08:53:44.897 5
PC-1 2015-12-04 09:02:17.524 6
PC-2 2015-12-04 09:22:01.041 8
PC-1 2015-12-04 09:31:41.744 9
Sql Fiddle
The above result shows the record of max date of consecutive HostName records. You can see there are 3 entries (SrNo 3,4,5) but I have taken only 5th which is latest from all of three. the same scenario also used in first two records (SrNo 1,2) I have taken only 2nd record which is latest from those two.
The problem is that I cannot take the Max Date Record. if I use MAX(ModifyDate) with group by HostName then it will return only two records (Sr No 8 and 9) which is latest. I want to take max record of each consecutive HostName entry.
NOTE: I cannot create stored procedure for it. I want to get that record by single sql statement. And there is no Sr No field in the table. I have taken it just to understand the case.
This is a Grouping Islands of Contiguous Dates problem which can be solved using ROW_NUMBER:
SQL Fiddle
WITH Cte AS(
SELECT *,
grp = ROW_NUMBER() OVER(ORDER BY ModifyDate) -
ROW_NUMBER() OVER(PARTITION BY HostName ORDER BY ModifyDate),
SrNo = ROW_NUMBER() OVER(ORDER BY ModifyDate)
FROM LOG
),
CteFinal AS(
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY HostName, grp ORDER BY SrNo DESC)
FROM Cte
)
SELECT
HostName, ModifyDate, SrNo
FROM CteFinal
WHERE rn = 1
ORDER BY SrNo
You can try this approach..
SQL Fiddle
WITH CTE1 AS
(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT ModifyDate)) RN,* FROM DATES9
),
CTE2 AS
(
SELECT CAST(1 AS INT) AS NRN, * FROM CTE1 WHERE RN=1
UNION ALL
SELECT CAST((CASE WHEN C1.HOSTNAME = C2.HOSTNAME THEN NRN ELSE NRN+1 END) AS INT) AS NRN,C1.*
FROM CTE1 C1 INNER JOIN CTE2 C2 ON C2.RN = C1.RN-1
)
select MAX(MODIFYDATE),HOSTNAME
from CTE2
GROUP BY NRN,HOSTNAME
ORDER BY NRN
I got a situation to display first top 6 records. first 3 records in FirstCol and next 3 in SecondCol. My query is like this:
select top 6 [EmpName]
from [Emp ]
order by [Salary] Desc
Result:
[EmpName]
----------------------
Sam
Pam
Oliver
Jam
Kim
Nixon
But I want the result to look like this:
FirstCol SecondCol
Sam Jam
Pam Kim
Oliver Nixon
; WITH TOP_3 AS
(
select TOP 3 [EmpName]
,ROW_NUMBER() OVER (ORDER BY [Salary] Desc) rn
from [Emp ]
order by [Salary] Desc
),
Other3 AS
(
SELECT [EmpName]
,ROW_NUMBER() OVER (ORDER BY [Salary] Desc) rn
FROM Employees
ORDER BY [Salary] DESC OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY
)
SELECT T3.[EmpName] , O3.[EmpName]
FROM TOP_3 T3 INNER JOIN Other3 O3
ON T3.RN = O3.RN
ORDER BY T3.RN ASC
You can do this using several windowing functions, this is kind of ugly but it will get you the result that you want:
;with data as
(
-- get your Top 6
select top 6 empname, salary
from emp
order by salary desc
),
buckets as
(
-- use NTILE to split the six rows into 2 buckets
select empname,
nt = ntile(2) over(order by salary desc),
salary
from data
)
select
FirstCol = max(case when nt = 1 then empname end),
SecondCol = max(case when nt = 2 then empname end)
from
(
-- create a row number for each item in the buckets to return multiple rows
select empname,
nt,
rn = row_number() over(partition by nt order by salary desc)
from buckets
) d
group by rn;
See SQL Fiddle with Demo. This uses the function NTILE, this takes your dataset of six rows and splits it into two buckets - 3 rows in bucket 1 and 3 rows in bucket 2. The (2) inside the NTILE is used to determine the number of buckets.
Next I used row_number() to create a unique value for each row within each bucket, this allows you to return multiple rows for each column.
I am still learning about SQL Server, and recently I encountered with issue with ranking (not sure if i should use rank).
I am trying to get the ranking to sort out as below, but i could not achieve by using row_number(over) or any ranking function in SQL server.
[Add in ]
the content in table1 has Cust_Code, Week and T_Mode, the one i display below is CustA. basically i want to know CustA, he is first using Air, then Water then switch to Air again in listed weeks.
**** Required Output ******
Week T_Mode Rank
201301 Air 1
201303 Water 2
201305 Water 2
201306 Water 2
201311 Air 3
i used Row_Number but it does not give what I want.
select *
, row_number()over(partition by T_Mode order by week) as Rank
from table1
the output returned
Week T_Mode Rank
201301 Air 1
201303 Water 1
201305 Water 2
201306 Water 3
201311 Air 2
any advice would be most welcome. Thank you!
Declare #t table(Week1 int,T_Mode varchar(20))
insert into #t values(201301,'Air'),(201303,'Water'),(201305,'Water'),(201306,'Water'),(201311,'Air')
;with cte as
(
select top 1 week1,t_mode,1 [Rank] from #t order by week1
union all
select b.week1,b.t_mode,case when a.T_Mode=b.T_Mode then a.Rank else a.Rank+1 end [Rank] from #t b
outer apply cte a
where b.Week1>a.week1 and b.T_Mode<>a.T_Mode
)
select distinct * from cte
Here's a solution that works in SQL Server 2012:
select
week, t_mode,
sum(change) over (order by week rows unbounded preceding) [rank]
from (
select *,
case when
(select top 1 t_mode
from table1
where week < t1.week
order by week desc) <> t1.t_mode then 1 else 0 end [change]
from table1 t1
) x
See this SQL Fiddle
Here is a less efficient version for SQL 2008:
;with cte as (
select *,
case when
(select top 1 t_mode
from table1
where week < t1.week
order by week desc) <> t1.t_mode then 1 else 0 end [change]
from table1 t1
)
select
week, t_mode,
(select sum(change) from cte where week <= x.week) [rank]
from cte x
And here's the fiddle.