Why is a CTE needed to execute the following - sql

The following query errors with an invalid column name 'rowid'
SELECT row_number() over (partition by sales_rep order by timestamp desc) as rowid, *
FROM dbo.you_gettheidea
where rowid = 1
However, the following version works perfectly. I'm not sure why.
with t1 as (SELECT row_number() over (partition by sales_rep order by timestamp desc) as rowid, *
FROM dbo.you_gettheidea)
Select * from t1
Where rowid = 1
SQL Server 12.0.2000
Edit: It appears that this question is in line with the following answered question

You can't use column alias in where clause of same statement. It doesn't obey the execution order that's why CTE is needed. Please check Execution order
FROM and JOIN s. The FROM clause, and subsequent JOIN s are first executed to determine the total working set of data that is being
queried.
WHERE.
GROUP BY.
HAVING.
SELECT.
DISTINCT.
ORDER BY.
LIMIT / OFFSET / TOP

Late answer, but there is another option without a CTE or subquery ... WITH TIES
Select top 1 with ties *
From dbo.you_gettheidea
Order By row_number() over (partition by sales_rep order by timestamp desc)

Related

SQL - Only need the record with Max Date

My table looks something like this:
I want to get the record for the MAX Date. So after querying, my output should only contain this:
A correlated subquery is a simple method:
select t.*
from t
where t.update_date = (select max(t2.update_date) from t t2 where t2.number = t.num);
Use row_number() with top (1) with ties available for SQL Server (which was initially tagged) :
select top (1) with ties t.*
from table t
order by row_number() over (partition by no order by date desc);
You can also use subquery :
select t.*
from (select t.*, row_number() over (partition by no order by date desc) as seq
from table t
) t
where seq = 1;

Multiple records not repeated

I have a table called TABLE_SCREW where I want to get the latest records for each code.
For example, in the table below you should obtain the records with ids 3 and 7.
I am a newbie in sql and I hope you can help me.
You could use:
SELECT TOP 1 WITH TIES *
FROM TABLE_SCREW
ORDER BY ROW_NUMBER() OVER(PARTITION BY CODE ORDER BY Date DESC);
Another approach(may have better performance):
SELECT * -- here * should be replaced with actual column names
FROM (SELECT *,ROW_NUMBER() OVER(PARTITION BY CODE ORDER BY Date DESC) AS rn
FROM TABLE_SCREW) sub
WHERE sub.rn = 1;

MS SQL add max()-1 to qyery

how to add to the query max(o.Acct)-1 rows. I need to visualize the last two o.Acct rows. My query is currently showing only the max(o.Acct)
SELECT Max(o.Acct) AS [MaxAcct],o.ObjectID,o.Opertype
FROM Operations o
GROUP By o.ObjectID,o.Opertype
If you want to see the last two rows (per group), you're better off using ROW_NUMBER() rather than GROUP BY.
SELECT
*
FROM
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY ObjectID,
Opertype
ORDER BY Acct DESC
)
AS sequence_id
FROM
Operations
)
sortedOperations
WHERE
sequence_id <= 2
ORDER BY
ObjectID,
Opertype,
Acct
If you want the last two of something, I'm thinking order by and top. Something like this:
select top (2) o.*
from Operations o
order by o.acct desc;

How to select a row based on its row number?

I'm working on a small project in which I'll need to select a record from a temporary table based on the actual row number of the record.
How can I select a record based on its row number?
A couple of the other answers touched on the problem, but this might explain. There really isn't an order implied in SQL (set theory). So to refer to the "fifth row" requires you to introduce the concept
Select *
From
(
Select
Row_Number() Over (Order By SomeField) As RowNum
, *
From TheTable
) t2
Where RowNum = 5
In the subquery, a row number is "created" by defining the order you expect. Now the outer query is able to pull the fifth entry out of that ordered set.
Technically SQL Rows do not have "RowNumbers" in their tables. Some implementations (Oracle, I think) provide one of their own, but that's not standard and SQL Server/T-SQL does not. You can add one to the table (sort of) with an IDENTITY column.
Or you can add one (for real) in a query with the ROW_NUMBER() function, but unless you specify your own unique ORDER for the rows, the ROW_NUMBERS will be assigned non-deterministically.
What you're looking for is the row_number() function, as Kaf mentioned in the comments.
Here is an example:
WITH MyCte AS
(
SELECT employee_id,
RowNum = row_number() OVER ( order by employee_id )
FROM V_EMPLOYEE
ORDER BY Employee_ID
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
There are 3 ways of doing this.
Suppose u have an employee table with the columns as emp_id, emp_name, salary. You need the top 10 employees who has highest salary.
Using row_number() analytic function
Select * from
( select emp_id,emp_name,row_number() over (order by salary desc) rank
from employee)
where rank<=10
Using rank() analytic function
Select * from
( select emp_id,emp_name,rank() over (order by salary desc) rank
from employee)
where rank<=10
Using rownum
select * from
(select * from employee order by salary desc)
where rownum<=10;
This will give you the rows of the table without being re-ordered by some set of values:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT '1')) AS RowID, * FROM #table
If using SQL Server 2012 you can now use offset/fetch:
declare #rowIndexToFetch int
set #rowIndexToFetch = 0
select
*
from
dbo.EntityA ea
order by
ea.Id
offset #rowIndexToFetch rows
fetch next 1 rows only

Query uses rank() needs optimization

select * from
(
Select DISTINCT
DocManREPORT_View.DOCINPUTDATE,
DocManREPORT_View.REACTIVATEDATE,
DocManREPORT_View.TRACENO,
DocManREPORT_View.CLIENTNAME,
DocManREPORT_View.DOCUMENTID,DocManREPORT_View.BARCODEID,
DocManREPORT_View.INPUTMODE,
DocManREPORT_View.INPUTSOURCE,PI.start_time,
RANK() OVER (PARTITION BY process_instance_id
ORDER BY last_modified_date desc) rank,
PI.STATUS AS PROCESSSTATUS
FROM DocManREPORT_View
INNER JOIN PROCESS_INSTANCE PI ON
(pi.instance_id = DocManREPORT_View.process_instance_id)
)
where rank = 1;
I presume DISTINCT clause could screw up the performance. I would recommend you to get rid of it by including into partition by clause and have a look what have you got.
If you can, try to use the
RANK() OVER (PARTITION BY process_instance_id
ORDER BY last_modified_date desc) rank,
Inside the VIEW, since I tihnk the View has already every data to make this step inside.