SQL to output line number in results of a query - sql

I would like to generate a line number for each line in the results of a sql query. How is it possible to do that?
Example: In the request
select distinct client_name from deliveries
I would like to add a column showing the line number
I am working on sql server 2005.

It depends on the database you are using. One option that works for SQL Server, Oracle and MySQL:
SELECT ROW_NUMBER() OVER (ORDER BY SomeField) AS Row, *
FROM SomeTable
Change SomeField and SomeTable is according to your specific table and relevant field to order by. It is preferred that SomeField is unique in the context of the query, naturally.
In your case the query would be as follows (Faiz crafted such a query first):
SELECT ROW_NUMBER() OVER (ORDER BY client_name) AS row_number, client_name
FROM (SELECT DISTINCT client_name FROM deliveries) TempTable
I think it won't work for SQLite (if someone can correct me here I would be grateful), I'm not sure what's the alternative there.

You can use the ROW_NUMBER function for this. Check the syntax for this here http://msdn.microsoft.com/en-us/library/ms186734.aspx
SELECT FirstName, LastName, ROW_NUMBER() OVER(ORDER BY FirstName) AS 'Row#'
FROM Sales.vSalesPerson;
For your query,
SELECT client_name, ROW_NUMBER() Over (Order By client_name) AS row_number
FROM (select distinct client_name from deliveries) SQ
will work.

In Oracle
SQL> select row_number() over (order by deptno) as rn
2 , deptno
3 from
4 ( select distinct deptno
5 from emp
6 )
7 /
RN DEPTNO
---------- ----------
1 10
2 20
3 30
SQL>

OR you could also do
SELECT DISTINCT client_name, #num := #num + 1 AS lineNum(this is your new col)
FROM deliveries
JOIN (SELECT #num :=0) AS n ON 1=1;
hope this helps too :)

In SQL we are also using this query:
select row_number() over (order by table_kid) as S_No ,table_columnname,table_columnname2 from tablename where table_fieldcondition='condtionnal falg or data ';
Here table_kid or may be other table_columnname

Related

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

Sql query to fetch 3rd lowest value

I have a table called employee_salary, having two columns(emp_id, emp_salary) in it.
I have a requirement to fetch 3rd lowest emp_salary from this table. In this case, what should be my query so that i can get the exact value.
I have tested this in Postgres Database. I hope this query work in all type of database. please try this.
SELECT
[emp_salary]
FROM [employee_salary]
GROUP BY [emp_salary]
ORDER BY [emp_salary] LIMIT 1 OFFSET 2;
This may be one solution
select top 1 * from
(
select top 3 * from
(
select distinct emp_sal from employee order by asc emp_sal
) d orderby desc emp_sal
)
SELECT TOP 1 * FROM employee_salary WHERE emp_salary in (SELECT TOP 3 emp_salary FROM employee_salary ORDER BY emp_salary) ORDER BY emp_salary DESC
However, this does not work in all DBs. You need to find out alternative. For eg. in Informix, the statement will be SELECT FIRST 1 *
Using windowing functions... this construct is for SQL Server:
;WITH CTE AS
(
SELECT ..., ROW_NUMBER() OVER (ORDER BY emp_salary) AS rn
FROM myTable
)
SELECT ...
FROM CTE
WHERE rn = 3
for identical salaries you can get using RANK () function in SQL Server
;WITH CTE AS
(
SELECT ..., RANK() OVER (ORDER BY emp_salary) AS rn
FROM myTable
)
SELECT ...
FROM CTE
WHERE rn = 3
I got the answer by executing the following query in sql server 2008
Select MIN(emp_salary) from MyTable Where emp_salary in
(Select DISTINCT TOP 3 emp_salary from MyTable order by 1 DESC)
I got the 3rd minimum value.
DISTINCT is used to when one or more salary are same.
select * from table_name where col_name = (select (min(col_name) from table_name where col_name > (select min(col_name) from table_name where col_name > (select min(col_name) from table_name)));
You need 3rd lowest Salary. Let dive deep in the question.
1st requirement is Need Salary , 2nd requirement is need lowest salary and 3rd requirement is 3rd Lowest Salary
SELECT * FROM employee_salary // "It will give us Salary"
ORDER BY emp_salary DESC //"It will show lowest salary on top"
LIMIT 2,1 // As wee need 3rd salary , i am saying LIMIT 2,1 skip first 2 and show 3rd one

SQL query query about selecting particular number of rows

For example -
SELECT * FROM user_names returns about 100 rows.
How would you query to get only row no.30 to row no.40?
Well with MySQL you would do it as follows:
SELECT * FROM user_names LIMIT 30,10
you can use row_number
with CTE_Table
as (SELECT id, ROW_NUMBER() OVER(ORDER BY id DESC) AS Row_Number
FROM dbo.a)
select * from CTE_Table
WHERE Row_Number BETWEEN 30 AND 40
Assuming SQL Server
SELECT * FROM
(SELECT ROW_NUMBER() OVER (ORDER BY user_names.id) as RowNumber, *
from user_names) un
where un.RowNumber between 30 and 40
replace the ORDER BY clause with whatever you want to order by.

Retrieving the second most highest value from a table

How do I retrieve the second highest value from a table?
select max(val) from table where val < (select max(val) form table)
In MySQL you could for instance use LIMIT 1, 1:
SELECT col FROM tbl ORDER BY col DESC LIMIT 1, 1
See the MySQL reference manual: SELECT Syntax).
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).
With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return. The offset of the initial row is 0 (not 1):
SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15
select top 2 field_name from table_name order by field_name desc limit 1
SELECT E.lastname, E.salary FROM employees E
WHERE 2 = (SELECT COUNT(*) FROM employess E2
WHERE E2.salary > E.salary)
Taken from here
This works in almost all Dbs
Select Top 1 sq.ColumnToSelect
From
(Select Top 2 ColumnToSelect
From MyTable
Order by ColumnToSelect Desc
)sq
Order by sq.ColumnToSelect asc
Cool, this is almost like Code Golf.
Microsoft SQL Server 2005 and higher:
SELECT *
FROM (
SELECT
*,
row_number() OVER (ORDER BY var DESC) AS ranking
FROM table
) AS q
WHERE ranking = 2
Try this
SELECT * FROM
(SELECT empno, deptno, sal,
DENSE_RANK() OVER (PARTITION BY deptno ORDER BY sal DESC NULLS LAST) DENSE_RANK
FROM emp)
WHERE DENSE_RANK = 2;
This works in both Oracle and SQL Server.
Try this
SELECT TOP 1 Column FROM Table WHERE Column < (SELECT MAX(Column) FROM Table)
ORDER BY Column DESC
SELECT TOP 1 Column FROM (SELECT TOP <n> Column FROM Table ORDER BY Column DESC)
ORDER BY ASC
change the n to get the value of any position
Maybe:
SELECT * FROM table ORDER BY value DESC LIMIT 1, 1
one solution would be like this:
SELECT var FROM table ORDER BY var DESC LIMIT 1,1

Tricky SQL SELECT Statement

I have a performance issue when selecting data in my project.
There is a table with 3 columns: "id","time" and "group"
The ids are just unique ids as usual.
The time is the creation date of the entry.
The group is there to cummulate certain entries together.
So the table data may look like this:
ID | TIME | GROUP
------------------------
1 | 20090805 | A
2 | 20090804 | A
3 | 20090804 | B
4 | 20090805 | B
5 | 20090803 | A
6 | 20090802 | B
...and so on.
The task is now to select the "current" entries (their ids) in each group for a given date. That is, for each group find the most recent entry for a given date.
Following preconditions apply:
I do not know the different groups in advance - there may be many different ones changing over time
The selection date may lie "in between" the dates of the entries in the table. Then I have to find the closest one in each group. That is, TIME is less than the selection date but the maximum of those to which this rule applies in a group.
What I currently do is a multi-step process which I would like to change into single SELECT statement:
SELECT DISTINCT group FROM table to find the available groups
For each group found in 1), SELECT * FROM table WHERE time<selectionDate AND group=loop ORDER BY time DESC
Take the first row of each result found in 2)
Obviously this is not optimal.
So I would be very happy if some more experienced SQL expert could help me to find a solution to put these steps in a single statement.
Thank you!
The following will work on SQL Server 2005+ and Oracle 9i+:
WITH groups AS (
SELECT t.group,
MAX(t.time) 'maxtime'
FROM TABLE t
GROUP BY t.group)
SELECT t.id,
t.time,
t.group
FROM TABLE t
JOIN groups g ON g.group = t.group AND g.maxtime = t.time
Any database should support:
SELECT t.id,
t.time,
t.group
FROM TABLE t
JOIN (SELECT t.group,
MAX(t.time) 'maxtime'
FROM TABLE t
GROUP BY t.group) g ON g.group = t.group AND g.maxtime = t.time
Here's how I would do it in SQL Server:
SELECT * FROM table WHERE id in
(SELECT top 1 id FROM table WHERE time<selectionDate GROUP BY [group] ORDER BY [time])
The solution will vary by database server, since the syntax for TOP queries varies. Basically you are looking for a "top n per group" query, so you can Google that if you want.
Here is a solution in SQL Server. The following will return the top 10 players who hit the most home runs per year since 1990. The key is to calculate the "Home Run Rank" of each player for each year.
select
HRRanks.*
from
(
Select
b.yearID, b.PlayerID, sum(b.Hr) as TotalHR,
rank() over (partition by b.yearID order by sum(b.hr) desc) as HR_Rank
from
Batting b
where
b.yearID > 1990
group by
b.yearID, b.playerID
)
HRRanks
where
HRRanks.HR_Rank <= 10
Here is a solution in Oracle (Top Salespeople per Department)
SELECT deptno, avg_sal
FROM(
SELECT deptno, AVG(sal) avg_sal
GROUP BY deptno
ORDER BY AVG(sal) DESC
)
WHERE ROWNUM <= 10;
Or using analytic functions:
SELECT deptno, avg_sal
FROM (
SELECT deptno, avg_sal, RANK() OVER (ORDER BY sal DESC) rank
FROM
(
SELECT deptno, AVG(sal) avg_sal
FROM emp
GROUP BY deptno
)
)
WHERE rank <= 10;
Or same again, but using DENSE_RANK() instead of RANK()
select * from TABLE where (GROUP, TIME) in (
select GROUP, max(TIME) from things
where TIME >= 20090804
group by GROUP
)
Tested with MySQL (but I had to change the table and column names because they are keywords).
SELECT *
FROM TABB T1
QUALIFY ROW_NUMBER() OVER ( PARTITION BY GROUPP,TIMEE order by id desc )=1