SQL: Use a calculated fields from the SELECT in the WHERE clause - sql

I have a SQL query that does some ranking, like this:
SELECT RANK() OVER(PARTITION BY XXX ORDER BY yyy,zzz,oooo) as ranking, *
FROM SomeTable
WHERE ranking = 1 --> this is not possible
I want to use that ranking in a WHERE condition at the end.
Now I nest this query in another query and do filtering on the ranking there, but is there no easier or faster way to filter on such values from the SELECT statement?

Use a CTE (Common Table Expression) - sort of an "inline" view just for the next statement:
;WITH MyCTE AS
(
SELECT
RANK() OVER(PARTITION BY XXX ORDER BY yyy,zzz,oooo) as ranking,
*
FROM SomeTable
)
SELECT *
FROM MyCTE
WHERE ranking = 1 --> this is now possible!

Sorry for the former posting, i forgot : windowing functions can only be used in select or order by clauses.
You'll have to use a sub query:
SELECT * FROM
(
SELECT RANK() OVER(PARTITION BY XXX ORDER BY yyy,zzz,oooo) as ranking, *
FROM SomeTable
) t
WHERE ranking = 1
OR A CTE.

select * from (
select RANK() OVER(PARTITION BY name ORDER BY id) as ranking, *
from PostTypes
) A
where A.ranking = 1
https://data.stackexchange.com/stackoverflow/query/edit/59515

Related

how can i write the sql query to get the result set, get the result set from the max time

Name Longititue latutute Time
tharindu 79.94148 6.9748404 00:15:47
shane 79.8630765 6.8910388 13:23:24
shane 79.862815 6.8909349 14:41:29
shane 79.8628665 6.8911084 09:39:33
shane 79.8626956 6.890992 11:00:07
shane 79.8628831 6.89099 11:43:00
i want get the result set as below
shane 79.862815 6.8909349 14:41:29
tharindu 79.94148 6.9748404 00:15:47
how can i write the sql query to get the result set, get the result set from the max time
You can try to use ROW_NUMBER window function.
SELECT Name,Longititue,latutute,[Time]
FROM (
SELECT *,ROW_NUMBER() OVER(PARTITION BY Name ORDER BY [Time] DESC) rn
FROM T
)t1
WHERE rn = 1
you can also try using correlated subquery
select * from tablename a
where Time in (select max(Time) from tablename b where a.name=b.name)
you can use corelated subquery
select t.* from table_name t
where t.[Time]=( select max([Time]) from table_name t1 where t1.Name=t.Name)
Here is a way to use ROW_NUMBER without a formal subquery:
SELECT TOP 1 WITH TIES
Name,
Longititue,
latutute,
Time
FROM yourTable
ORDER BY
ROW_NUMBER() OVER (PARTITION BY Name ORDER BY [Time] DESC);
Demo
You can achive this use CTE(Common Table Expression) and Ranking Function.
SQL Query:
WITH CTE AS
(
SELECT Name,Longititue,latutute,Time,DENSE_RANK() OVER(PARTITION BY Name ORDER BY time desc) as RN
FROM MaxTime
)
SELECT * FROM CTE
WHERE RN = 1

Opposite of TOP in SQL Server

I need to retrieve the last few entries from a table. I can retrieve them using:
SELECT TOP n *
FROM table
ORDER BY id DESC
That I looked everywhere and that's the only answer I could find, But that way I get them in reverse order. I need them in the same order as they are in the table because it's for a messaging interface.
Use a derived table:
select id, ...
from
(
select top n id, ...
from t
order by id desc
) dt
order by id
I suggest you to use a ROW_NUMBER() like this:
SELECT *
FROM (
SELECT
*, ROW_NUMBER() OVER (ORDER BY id DESC) AS RowNo
FROM
yourTable
) AS t
WHERE
(RowNO < #n)
ORDER BY
id

Select Top 100 Groups

I have thousands of groups in a table, something like :
1..
1..
2..
2..
2..
2..
3..
3..
.
.
.
10000..
10000..
How can i make a select that give me the Top 3 groups each time.
I Want something like select Top 3 from rows , but it have to return the first three groups not the first three rows.
You can try this :
;with cte as (
select distinct groupId from mytable order by groupid
)
select * from mytable where TheGroupId in (select top 3 groupdid from cte)
You can use DENSE_RANK to assign a number to each group. All members of the same group will have the same number. Then in an outer query, select top 3 groups:
SELECT *
FROM (SELECT *, DENSE_RANK() OVER (ORDER BY id) AS rnk
FROM mytable ) t
WHERE t.rnk <= 3
The above query assumes that id is the column used to group records together.
SQL Fiddle Demo
Use Ranking function Row_Number() :
SELECT *
FROM (SELECT *,
Row_number()
OVER(
partition BY GroupId
ORDER BY GroupId) AS [rn]
FROM YourTable) t
WHERE rn <= 3
Check this MSDN doc for details of all ranking functions.
There is a sql TOP statement that does this
SELECT TOP number|percent column_name(s) FROM table_name;
a description of what it does and how it is used in alternative sql statements for example for mysql and ms access can be found here: http://www.w3schools.com/sql/sql_top.asp
My bad i misread your question, this will return the top rows not groups, could you explain what you are trying to do in more detail?
SELECT *
FROM
(SELECT *
,ROW_NUMBER() OVER (PARTITION BY [Group] ORDER BY [Group] ASC)rn
FROM TableName
)A
WHERE rn <= 3

How to use distinct when you select multiple column in SQL

I have use simple inner join statement and getting result into CTE table. I want to select distinct 'ServiceId' from CTE. I have following query
SELECT DISTINCT(ServicesId), ServiceNo, ServiceDate, DealerCode FROM CTE_Temp
Suppose there are duplicate entries of ServiceId in CTE then I want to select first entry only and ignore rest of them.
You can use ROW_NUMBER() OVER() for this. Just replace the column in the ORDER BY to define what's first.
;WITH AnotherCTE AS(
SELECT
ServicesId, ServiceNo, ServiceDate, DealerCode,
RN = ROW_NUMBER() OVER(PARTITION BY ServicesID ORDER BY ServiceDate DESC)
FROM CTE_Temp
)
SELECT
ServicesId, ServiceNo, ServiceDate, DealerCode
FROM AnotherCTE
WHERE RN = 1

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.