Select stmt with ROW_NUMBER() OVER(PARTITION BY...) in Where clause - sql-server

I must be doing something wrong. I'm trying to use the row_number function to only select the values that have a rownum of 1, so that I always get the latest index. However rownum is not recognized in the where-clause.
SELECT fs.docu_id as docID
, fs.field_3 AS ProductNo
, fs.field_4 AS [Status]
, fs.field_5 AS [Index]
,pd.[doku_nr] AS docIDshort
, ROW_NUMBER() OVER(PARTITION BY fs.field_3 ORDER BY fs.field_5 Desc) AS rownum
FROM [table1] fs
JOIN [table2] pd
ON fs.docu_id=pd.docu_id
AND fs.field_4 = 'valid'
What am I missing? Do I need to create a different select stmt?
Thank you.

You cannot use window functions in the Where clause(only in SELECT or ORDER BY).
But you could use a CTE instead:
WITH CTE
AS (SELECT fs.docu_id AS docID,
fs.field_3 AS ProductNo,
fs.field_4 AS [Status],
fs.field_5 AS [Index],
pd.[doku_nr] AS docIDshort,
Row_number() OVER(
Partition BY fs.field_3
ORDER BY fs.field_5 DESC) AS rownum
FROM [table1] fs
JOIN [table2] pd
ON fs.docu_id = pd.docu_id
AND fs.field_4 = 'valid')
SELECT docid, productno, status, [index], docIDshort
FROM CTE
WHERE rownum = 1

Related

How to get desired result by combining two CTE's with different tables?

I have two CTE's,firstly
;WITH CTE AS (SELECT A.*
, Row_NUMBER() Over (Partition by ID order by Date asc) RN
FROM TABLE A)
SELECT Sum(Weight) as IN_WT
FROM CTE
WHERE RN = 1 and name='dev1'
and then
;WITH CTE AS (SELECT B.*
, Row_NUMBER() Over (Partition by ID order by Date desc) RN1
FROM TABLE B)
SELECT Sum(Weight) AS out_wt
FROM CTE
WHERE RN1 = 1 and name='dev1'
Here we had two tablesTableA,TableB.We are getting In_wt from TableA and Out_wt from TableB.Now I had a requiremnt that the output should be combined and get in_wt,out_wt in single row from different tables and same name.I tried combining both the CTE's but didn't get the desired result.How can we do that?
Try this:
;WITH CTE1 AS (
SELECT name,
Row_NUMBER() Over (Partition by ID order by Date asc) RN
FROM TABLEA
), CTE2 AS (
SELECT name,
Row_NUMBER() Over (Partition by ID order by Date desc) RN
FROM TABLEB
)
SELECT (SELECT Sum(Weight) FROM CTE1 WHERE RN = 1 and name='dev1') AS IN_WT,
(SELECT Sum(Weight) FROM CTE2 WHERE RN = 1 and name='dev1') AS OUT_WT

Applying window function in one query without CTE

I have been searched in the net and trying to create a query that contains a window function without a CTE but I couldn't get the result and I need some help
this my query that I create with a CTE what I need is doing that in one query
;with cte(Gid, id, prod, orderdate, shipdate, ranking) as
(
select
p1.Gid Gid,
p1.id id,
p1.prod prod,
p1.orderdate orderdate,
p2.shipdate shipdate,
rank() over (partition by p1.prod order by p1.id desc) ranking
from
shpro p1
inner join
shpro p2 on p1.id = p2.id
where
cast(p1.orderdate as DATE) > GETDATE()
and cast(p1.shipdate as DATE) < GETDATE() - 1
)
select *
from cte
where ranking = 1
Demo with some test data on how this works
select top (1) with ties
p1.Gid Gid,
p1.id id,
p1.prod prod,
p1.orderdate orderdate,
p2.shipdate shipdate
from shpro p1 inner join shpro p2
on p1.id=p2.id
where cast(p1.orderdate as DATE)>GETDATE() and cast(p1.shipdate as DATE)<GETDATE()-1
order by
Rank() over (partition by p1.prod order by p1.id desc)
This works like below..
1.order by arranges all the rows based on their rank
2.Top 1 with ties options fetches all the rows which are tied
References:
T-SQL Querying (Developer Reference)
Below is some sample data to play with:
CREATE TABLE #TEST
(
Id INT,
Name VARCHAR(10)
)
Insert Into #Test
select 1,'A'
Union All
Select 1,'B'
union all
Select 1,'C'
union all
Select 2,'D'
select top 1 with ties id,name
from #test
order by row_number() over (partition by id order by id)
CTE can be translated directly into subquery. Yours query should look similar to following:
SELECT * FROM
(
select
p1.Gid Gid,
p1.id id,
p1.prod prod,
p1.orderdate orderdate,
p2.shipdate shipdate,
rank() over (partition by p1.prod order by p1.id desc) ranking
from
shpro p1
inner join
shpro p2 on p1.id = p2.id
where
cast(p1.orderdate as DATE) > GETDATE()
and cast(p1.shipdate as DATE) < GETDATE() - 1
) CteAsSubquery
WHERE ranking = 1
Note alias CteAsSubquery is there (most common error).

How do I select the top 1 results of the if the same identifier exist? SQL Server

I have a data table in sql server 2008 that I would like to select the top 1 out of each identifier:
The results shld looks like this during before and after:
Thus it should only select the 1st results if the same identifier do exist. Thanks a lot.
select distinct [Primary Identifier] from tbl
If you have entire records (other columns) instead of that single column, you can row number them and choose one.
select {list of columns}
from
(
select *, rn = row_number over (partition by [Primary Identifier]
order by 1/0)
from tbl
) X
where rn = 1;
order by 1/0 is arbitrary. If you need to choose a specific one from the "duplicates", for example the highest cost, you order by cost descending, i.e.
(partition by [Primary Identifier]
order by [cost] descending)
Just distinct them:
select distinct [primary identifier] from tablename
Or by grouping:
select [primary identifier] from tablename group by [primary identifier]
If more columns exist you can rank rows with window function:
;with cte as(select *, row_number() over(partition by [primary identifier] order by (select null)) rn from tablename)
select * from cte where rn = 1
Change order by (select null) to appropriate ordering column.
i think this will be an appropriate solution to your need-
;WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY [Primary Identifier] ORDER BY [sort columns]) AS rowid
FROM [table]
)
SELECT *
FROM cte
WHERE rowid = 1

Can cross join work with window function like - row_number() function

Window function can not be used in where clause. In the below query rn column can be used in where clause only in the outer query like -
select * from (
select *, row_number() over (partition by col1 order by col1) as rn
from tab1) as abc
where rn = 1
can we use rn column with cross join some thing like -
select *, row_number() over (partition by col1 order by col1) as rn
from tab1 as a
cross join(select rn from a)
Just curious to know as i am trying to learn SQL server
You cannot do it in this way. You either have to repeat ROW_NUMBER() inside the subquery:
SELECT *, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1) AS rn
FROM tab1 AS a
CROSS JOIN (SELECT ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1) AS rn FROM tab1) t
or, alternatively, use a common table expression:
;WITH a AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY col1 ORDER BY col1) AS rn
FROM tab1
)
SELECT *
FROM a
CROSS JOIN (SELECT rn FROM a) t

How to optimize the query, adding rowNumber in where clause

In a table I have more than 700,000 records. When I run this query it takes more than 3 minutes to fetch the rows, and returns 390 records based on rowNum. Is there way to optimize this query?
SELECT ID, Lat, Long, SDateTime,
row_number() OVER (partition BY [ID] ORDER BY [SDateTime] DESC) AS rowNum
into #temp
FROM
dbo.myTable WITH (NOLOCK)
select * from #temp where rowNum = 1 -- returns 390 records
drop table #temp
Can I select data in one query without putting it in temp table? like this:
SELECT ID, Lat, Long, SDateTime,
row_number() OVER (partition BY [ID] ORDER BY [SDateTime] DESC) AS rowNum
FROM
dbo.myTable WITH (NOLOCK)
where (row_number() OVER (partition BY [ID] ORDER BY [SDateTime] DESC)) = 1
try doing this !
select * from
(
SELECT ID, Lat, Long, SDateTime,
row_number() OVER (partition BY [ID] ORDER BY [SDateTime] DESC) AS rowNum
FROM
dbo.myTable WITH (NOLOCK)
)x
where x.rowNum=1
This should do the job, but it will work very well with an index on (id,SDateTime)
;with d as (
select distinct id
from myTable
)
select
mt.*
from d
cross apply (
select top 1 *
from myTable m
on m.id = d.id
order by [SDateTime] DESC
) mt

Resources