i want to return the second item from this subquery:
set GrowerNumber =(select top 1 tea_no
from ktda_file
where ktda_file.fosa_acno=customer.fosa_acno)
GrowerNumber = (
select top 1
tea_no
from
(
select top 2
tea_no
from
ktda_file
where ktda_file.fosa_acno=customer.fosa_acno
) as a
order by
tea_no desc
)
Try this
WITH CTE AS
(
SELECT top 2 tea_no from ktda_file
WHERE ktda_file.fosa_acno=customer.fosa_acno
ORDER BY tea_no ASC
)
SELECT TOP 1 tea_no FROM CTE ORDER BY tea_no DESC
SELECT *
FROM customer
OUTER APPLY (
SELECT
Item1 = MAX(CASE WHEN t.RowNum = 1 THEN t.tea_no END),
Item2 = MAX(CASE WHEN t.RowNum = 2 THEN t.tea_no END)
FROM (
SELECT tea_no, RowNum = ROW_NUMBER() OVER (ORDER BY tea_no)
FROM ktda_file
WHERE ktda_file.fosa_acno = customer.fosa_acno
) t
WHERE RowNum < 3
) t2
Maybe this will help you:
(select tea_no from (select row_number() over ( order by tea_no asc) as rowID, tea_no from ktda_file where ktda_file.fosa_acno=customer.fosa_acno)x where rowID = 2)
Hi you need to do something like this (as Ivan said, you dont have an order by in your query, so what is the 2nd one?) Nevertheless assuming it is tea_no...
GrowerNumber = (Select tea_no from (select row_number() over (order by tea_no) as row
from ktda_file where ktda_file.fosa_acno=customer.fosa_acno) as orderedlist
where row = 2)
Related
Can someone please help me to find the average time between first and second purchase on a product level.
This is what I have written -
Select A.CustomerId,A.ProductId , A.OrderSequence, (Case WHEN OrderSequence = 1 THEN OrderDate END) AS First_Order_Date,
MAX(Case WHEN OrderSequence = 2 THEN OrderDate END) AS Second_Order_Date
From
(
Select t.CustomerId, t.ProductId, t.OrderDate,
Dense_RANK() OVER (PARTITION BY t.CustomerId, t.ProductId ORDER BY OrderDate Asc) as OrderSequence
From Transactions t (NOLOCK)
Where t.SiteKey = 01
Group by t.CustomerId, t.ProductId, t.OrderDate)
A
Where A.OrderSequence IN (1,2)
Group By A.Customer_Id, A.ProductId, A.OrderSequence, A.OrderDate
Sample Data:
It looks like row-numbering and LEAD should do the trick for you here.
Don't use NOLOCK unless you really know what you're doing
It's unclear if you want the results to be partitioned by CustomerId also. If not, you can remove it everywhere in the query
SELECT
A.CustomerId,
A.ProductId,
AVG(DATEDIFF(day, OrderDate, NextOrderDate))
FROM
(
SELECT
t.CustomerId,
t.ProductId,
t.OrderDate,
ROW_NUMBER() OVER (PARTITION BY t.CustomerId, t.ProductId ORDER BY OrderDate) AS rn,
LEAD(OrderDate) OVER (PARTITION BY t.CustomerId, t.ProductId ORDER BY OrderDate) AS NextOrderDate
FROM Transactions t
WHERE t.SiteKey = '01'
) t
WHERE t.rn = 1
GROUP BY
t.Customer_Id,
t.ProductId;
I have a CTE with the last 3 rows of the table sorted by VersionNumber DESC. How I can sort them backwards in order to have the smallest VersionNumber from those 3 always to have display order 1?
There is no LIMIT in Microsoft SQL Server...
;WITH cte AS
(
SELECT
BSId, RevisedBSId, VersionNumber,
RANK() OVER (ORDER BY VersionNumber DESC) AS [DisplayOrder]
FROM
cte
),
sortedctethree AS
(
SELECT TOP 3
BSId, RevisedBSId, VersionNumber, DisplayOrder
FROM
sortedcte
)
SELECT *
FROM sortedctethree
Here DisplayOrder is wrong. If I use another CTE where I am trying to reorder, it is still wrong.
I need only 3 rows. But in the TOP 3 can be also one, or two rows in the result. I need in that case always have the DisplayOrder 1 for the smallest VersionNumber.
VersionNumber | DisplayOrder
--------------+--------------
2 | 2
1 | 1
How it is possible to achieve? Thanks a lot in advance.
try like below you dont need another cte
WITH cte AS
(
SELECT
BSId, RevisedBSId, VersionNumber,
rank() OVER (ORDER BY VersionNumber DESC) AS [DisplayOrder] from
table_name
)
SELECT BSId, RevisedBSId, VersionNumber , DisplayOrder FROM cte
where DisplayOrder<=3
order by DisplayOrder
You may try with the next approach. Number your data using DENSE_RANK() ordered by VersionNumber descending and then select first three rows and order them ascending:
;WITH cte AS (
SELECT
BSId,
RevisedBSId,
VersionNumber,
DENSE_RANK() OVER (ORDER BY VersionNumber DESC) AS [DisplayOrder]
FROM YourTable
)
SELECT
BSId,
RevisedBSId,
VersionNumber
FROM cte
WHERE [DisplayOrder] <= 3
ORDER BY VersionNumber ASC
If I understood correctly:
If you use ROW_NUMBER() with data ordered asc then the smallest value will have DisplayOrder = 1
;WITH cte AS
(
SELECT
BSId, RevisedBSId, VersionNumber,
ROW_NUMBER() OVER (ORDER BY VersionNumber ASC) AS [DisplayOrder]
FROM
cte
)
SELECT TOP 3
BSId, RevisedBSId, VersionNumber, DisplayOrder
FROM
sortedcte where [DisplayOrder] =1
If there are no partitions this is the simplest way, you dont need rank or row_number in your subquery or CTE
SELECT ROW_NUMBER() OVER (ORDER BY VersionNumber) as DisplayOrder, VesionNumber FROM (
SELECT TOP 3 VesionNumber from mytable
ORDER BY VesionNumber DESC
) A
ORDER BY VesionNumber ASC
Or using your approach
;WITH cte AS
(
SELECT
BSId, RevisedBSId, VersionNumber,
RANK() OVER (ORDER BY VersionNumber DESC) AS [SelectOrder],
RANK() OVER (ORDER BY VersionNumber ASC) AS [DisplayOrder],
FROM
cte
),
sortedctethree AS
(
SELECT TOP 3
BSId, RevisedBSId, VersionNumber, DisplayOrder, SelectOrder
FROM
sortedcte
ORDER BY SelectOrder
)
SELECT *
FROM sortedctethree
ORDER BY DisplayOrder
I have this table. With case#, Linenumber and code#.
case# Linenumber Code#
99L1HV 1 1510
99L1HV 2 4320
99PX58 1 1510
99PX58 2 4320
99PX58 3 4500
99PX59 1 1510
99PX59 2 918
99PX59 3 4320
How can I get the records with the last LineNumber per case# where code = 4320
The output should be like this
case# Linenumber Code
99L1HV 2 4320
99PX59 3 4320
Using ROW_NUMBER to get a number that's in the opposite order of the linenumber per case#.
Then the last lines will have RN = 1
SELECT [case#], Linenumber, [Code#]
FROM
(
SELECT [case#], Linenumber, [Code#],
ROW_NUMBER() OVER (PARTITION BY [case#] ORDER BY Linenumber DESC) AS RN
FROM yourtable
) q
WHERE RN = 1
AND [Code#] = 4320
ORDER BY [case#];
Or the more concise version.
Using a TOP 1 WITH TIES in combination with an ORDER BY ROW_NUMBER.
SELECT *
FROM
(
SELECT TOP 1 WITH TIES [case#], Linenumber, [Code#]
FROM yourtable
ORDER BY ROW_NUMBER() OVER (PARTITION BY [case#] ORDER BY Linenumber DESC)
) q
WHERE [Code#] = 4320
ORDER BY [case#];
cte is to generate a running number by case#. rn = 1 will be the last row for each case#
; with cte as
(
select *, rn = row_number() over (partition by [case#] order by linenumber desc)
from yourtable
)
select *
from cte
where rn = 1
and [code#] = 4320
declare #t table (
CaseNumber varchar(10),
LineNumber int,
CodeNumber int
);
-- Filling the table with data, skipped
select t.*
from #t t
where t.CodeNumber = 4320
and not exists (
select 0 from #t x
where x.CaseNumber = t.CaseNumber
and x.LineNumber > t.LineNumber
);
with cte as
(select case#, max(linenumber)
from source_table
group by case#)
select t1.*
from source_table t1 inner join cte t2
on t1.case# = t2.case# and t1.linenumber = t2.linenumber
where t1.Code# = 4320
I have the below query -
select System_Id, TeamProjectSK, System_State, System_Rev
from
(
select w1.System_Id, w1.TeamProjectSK, w1.System_State, w1.System_Rev,
row_number() over(partition by w1.System_Id, w1.TeamProjectSK, w1.System_State order by w1.System_Rev desc) rn
from dbo.DimWorkItem w1
where w1.System_Id = 1691
) d
where rn = 1
order by System_Id, TeamProjectSK,System_Rev desc;
The output looks like -
System_Id TeamProjectSK System_State System_Rev
1691 126 Closed 17
1691 126 Resolved 14
1691 126 Active 13
1691 126 Proposed 2
But I want my output to select the row with the highest "System_Rev" value & it should look like -
System_Id TeamProjectSK System_State System_Rev
1691 126 Closed 17
Now, I tried to re-use the "max" concept using the below query. But it would not work for my help. Please let me know your comments or if there is a better way to get the same result.
select System_Id, TeamProjectSK, System_State, max(System_Rev)
from
(select System_Id, TeamProjectSK, System_State, System_Rev
from
(
select w1.System_Id, w1.TeamProjectSK, w1.System_State, w1.System_Rev,
row_number() over(partition by w1.System_Id, w1.TeamProjectSK, w1.System_State order by w1.System_Rev desc) rn
from dbo.DimWorkItem w1
where w1.System_Id = 1691
) d
where rn = 1
) e
group by System_Id, TeamProjectSK, System_State
having max(System_Rev)>1
If you just want to return the row with the max System_Rev, then you need to alter the row_number() to partition by the System_id and the TeamProjectSK only. Remove the partition by System_State as well.
select System_Id, TeamProjectSK, System_State, System_Rev
from
(
select w1.System_Id, w1.TeamProjectSK, w1.System_State, w1.System_Rev,
row_number() over(partition by w1.System_Id, w1.TeamProjectSK order by w1.System_Rev desc) rn
from dbo.DimWorkItem w1
where w1.System_Id = 1691
) d
where rn = 1;
See SQL Fiddle with Demo
select System_Id, TeamProjectSK, System_State, System_Rev
from
(
select w1.System_Id, w1.TeamProjectSK, w1.System_State, w1.System_Rev,
row_number() over(partition by w1.System_Id, w1.TeamProjectSK, w1.System_State order by w1.System_Rev desc) rn
from dbo.DimWorkItem w1
where w1.System_Id = 1691
) d
where rn = 1
and d.System_Rev = (select max(w2.System_Rev) from dbo.DimWorkItem w2 where w2.System_Id = d.System_Id)
order by System_Id, TeamProjectSK,System_Rev desc;
I have a CTE as follows
WITH details
AS ( SELECT FldId
,Rev
,Words
,row_number() OVER ( PARTITION BY FldId ORDER BY Rev DESC ) AS rn
FROM WorkItemLongTexts
WHERE ID = 2855
)
SELECT f.ReferenceName
,d.FldId
,Rev
,Words
FROM details AS d
INNER JOIN Fields AS f ON f.FldId = d.FldId
WHERE d.rn = 1 ;
The above returns the following output
ReferenceName | FldId | Rev | Words
Description 52 2 Description here
Objectives 10257 2 Objectives here
Specification 10258 6 Specification here
Requirements 10259 6 Requirements here
I want to apply PIVOT (or whatever is the best option) so that i can get output as follows
Description | Objectives | Specification | Requirements
Description here Objectives here Specification here Requirements here
Pls. suggest.
Thanks
You do this:
SELECT
FldId,
[Description],
[Objectives],
[Specification],
[Requirements]
FROM (
SELECT
ReferenceName,
FldId,
REV,
Words
FROM CTE
WHERE RowNumber = 1
) t
PIVOT (
MIN(Words)
FOR ReferenceName IN ([Description], [Objectives], [Specification], [Requirements])
) PIV
Or you can add it to your CTE, like this:
;WITH CTE2 AS (
SELECT
FldId,
REV,
[Description],
[Objectives],
[Specification],
[Requirements],
ROW_NUMBER() OVER (PARTITION BY FldId ORDER BY REV DESC) AS RowNumber
FROM TBL
PIVOT (
MIN(Words)
FOR ReferenceName IN ([Description], [Objectives], [Specification], [Requirements])
) PIV
)
SELECT
FldId,
REV,
[Description],
[Objectives],
[Specification],
[Requirements]
FROM CTE2
WHERE RowNumber = 1
WITH details
AS ( SELECT FldId
,Rev
,Words
,row_number() OVER ( PARTITION BY FldId ORDER BY Rev DESC ) AS rn
FROM WorkItemLongTexts
WHERE ID = 2855
),
cte_1
AS ( SELECT f.ReferenceName
,d.FldId
,Rev
,Words
FROM details AS d
INNER JOIN Fields AS f ON f.FldId = d.FldId
WHERE d.rn = 1
)
SELECT max(case [ReferenceName] WHEN 'Descripton' THEN [Words] ELSE NULL END) AS [Descripton]
,max(case [ReferenceName] WHEN 'Objectives' THEN [Words] ELSE NULL END) AS [Objectives]
,max(case [ReferenceName] WHEN 'Specification' THEN [Words] ELSE NULL END) AS [Specification]
,max(case [ReferenceName] WHEN 'Requirements' THEN [Words] ELSE NULL END) AS [Requirements]
FROM cte_1 ;
OR:
-- cte here as above
SELECT Description
,Objectives
,Specification
,Requirements
FROM cte_1 PIVOT ( max(Words) FOR ReferenceName IN ( Description,
Objectives,
Specification,
Requirements ) ) AS PivotTable
Do something like:
with details as (...)
, unpivotted as (select f.ReferenceName, Words
from details as d
inner join Fields as f
on f.FldId=d.FldId
where d.rn =1)
Select *
from unpivotted
pivot
(max(Words) for Description in ([Objectives],[Specification],[Requirements]) p
;