SQL query how to get the local variable - sql

I have this query and I want to get "page" variable which is created:
SELECT *, (rowNum / 5) + 1 as page
FROM (
SELECT *, Row_Number() OVER (ORDER BY items.id_item ASC) as rowNum
FROM items INNER JOIN utilizadores ON items.autor = utilizadores.id_user
) x
WHERE (rowNum / 1000) + 1 = 1
How can I get it in the query to make a procedure to search.
CREATE PROCEDURE get_items_by_page
#page int
AS
SELECT *, (rowNum / 5) + 1 as page
FROM (
SELECT *, Row_Number() OVER (ORDER BY items.id_item ASC) as rowNum
FROM items INNER JOIN utilizadores ON items.autor = utilizadores.id_user
) x
WHERE (rowNum / 1000) + 1 = 1 //the required condition to query is in bottom
GO
and page = #page;

CREATE PROCEDURE get_items_by_page
#page int
AS
SELECT x.*, (rowNum / 5) + 1 as page
FROM (
SELECT *, Row_Number() OVER (ORDER BY items.id_item ASC) as rowNum
FROM items INNER JOIN utilizadores ON items.autor = utilizadores.id_user
) x
WHERE (rowNum / 5) + 1 = #page
GO

Related

Merge two SELECT queries with different ORDER BY

I have a Story table, and I need the following query:
- first 6 rows sorted by distance (I calculate it)
- next rows are sorted by TIME property descending
declare #profileID int
set #profileID = 6
declare #longitude float
set #longitude = 17.6009169090776
declare #latitude float
set #latitude = 46.9548404806283
SELECT
first.*
FROM
(
SELECT top 6
[dbo].[Story].*,
SQRT( POWER(#Longitude - [dbo].[Story].[Longitude], 2) + POWER(#Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = #ProfileID and
[dbo].[Story].IsDraft = 0
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
[dbo].[Story].*,
SQRT( POWER(#Longitude - [dbo].[Story].[Longitude], 2) + POWER(#Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = #ProfileID and
[dbo].[Story].IsDraft = 0
**ORDER BY
Time desc**
) last
My problem is the second query. It not sorts the records after the 6'th row descending by the TIME property, it sorts as ascending.
thnx
Try This
SELECT
first.*
FROM
(
SELECT top 6
[dbo].[Story].*,
SQRT( POWER(#Longitude - [dbo].[Story].[Longitude], 2) + POWER(#Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
,1 as ord
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = #ProfileID and
[dbo].[Story].IsDraft = 0
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
[dbo].[Story].*,
SQRT( POWER(#Longitude - [dbo].[Story].[Longitude], 2) + POWER(#Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
,row_number() over(order by Time desc) as ord
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON
[dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE
[dbo].[Follow].[Follower] = #ProfileID and
[dbo].[Story].IsDraft = 0
**ORDER BY
Time desc**
) last
My try (example)
declare #ta as table
(
id int
,na varchar(100)
,sal numeric(18,2)
)
insert into #ta( id,na,sal) values (1,'aa',10)
insert into #ta( id,na,sal) values (3,'bb',100)
insert into #ta( id,na,sal) values (2,'c',5)
insert into #ta( id,na,sal) values (4,'dd',50)
select * from
(select top 2 * , 1 as ord from #ta order by id) as f
union all
select * from (select top 100 percent * , row_number() over(order by sal desc) ord from #ta order by sal desc
) as tt
If you want the result set ordered in a particular way, then the outermost SELECT needs an ORDER BY.
You can control the ordering by including multiple keys in the outer ORDER BY. If I'm reading the query correctly, the only difference is the order by, so put the logic for the queries in a CTE:
WITH sf as (
SELECT s.*,
SQRT( POWER(#Longitude - s.[Longitude], 2) + POWER(#Latitude - s.[Latitude], 2)) as [DistanceFromUser]
FROM [dbo].[Follow] f LEFT JOIN
[dbo].[Story] s
ON f.[Followed] = s.[ProfileID]
WHERE f.[Follower] = #ProfileID and
s.IsDraft = 0
)
SELECT sf.*
FROM ((SELECT TOP (6) sf.*, 1 as ord
FROM sf
ORDER BY [DistanceFromUser] ASC
) UNION ALL
(SELECT TOP (6) sf.*, 2 as ord
FROM sf
ORDER BY Time DESC
)
) sf
ORDER BY ord,
(CASE WHEN ord = 1 THEN DistanceFromUser END) ASC,
(CASE WHEN ord = 2 THEN Time END) DESC;
You can also do this with window functions:
WITH sf as (
SELECT s.*,
SQRT( POWER(#Longitude - s.[Longitude], 2) + POWER(#Latitude - s.[Latitude], 2)) as [DistanceFromUser]
FROM [dbo].[Follow] f LEFT JOIN
[dbo].[Story] s
ON f.[Followed] = s.[ProfileID]
WHERE f.[Follower] = #ProfileID and
s.IsDraft = 0
)
SELECT sf.*
FROM (SELECT sf.*,
ROW_NUMBER() OVER (ORDER BY DistanceFromUser) as seqnum_d,
ROW_NUMBER() OVER (ORDER BY Time DESC) as seqnum_t
FROM sf
)
) sf
WHERE seqnum_d <= 6 OR seqnum_t <= 6
ORDER BY ord,
(CASE WHEN seqnum_d <= 6 THEN DistanceFromUser END) ASC,
(CASE WHEN seqnum_t <= 6 THEN Time END) DESC;
Your version could include the same row twice. This version will not duplicate rows that are in the top 6 for both conditions.
So I ended with next solution thnx to everyone
WITH TempTable as
(
SELECT [dbo].[Story].*,
SQRT( POWER(#Longitude - [dbo].[Story].[Longitude], 2) + POWER(#Latitude - [dbo].[Story].[Latitude], 2)) as [DistanceFromUser]
FROM
[dbo].[Follow]
LEFT JOIN
[dbo].[Story]
ON [dbo].[Follow].[Followed] = [dbo].[Story].[ProfileID]
WHERE [dbo].[Follow].[Follower] = #ProfileID and
[dbo].[Story].IsDraft = 0
)
SELECT
first.*
FROM
(
SELECT top 6
*,
1 as ord
FROM
TempTable
ORDER BY
[DistanceFromUser] asc
) first
UNION ALL
SELECT
last.*
FROM
(
SELECT TOP 100 PERCENT
*,
row_number() over(order by Time desc) as ord
FROM
TempTable
ORDER BY
Time desc
) last

Oracle: Need to fetch the rows exponentially

I got below query from another post which selects 100 rows from every 2000 rows.
Like this: 1-100,2001-2100,4001-4100,6001-6100,8001-8100 and so on.
SELECT * FROM (SELECT t.*,ROWNUM AS rn FROM(SELECT * FROM your_table ORDER BY your_condition) t)WHERE MOD( rn - 1, 2000 ) < 100;
Now I want to select my data exponentially.Such that it will select 100 rows from first 1000 rows, then from next 2000 rows, then from next 4000 rows.
Like this: 1-100,2000-2100,4000-4100,8000-8100,16000-16100 and so on.
The idea is to scan rows with a specific pattern.
You asked this in a comment on your previous question and I answered there...
SELECT *
FROM (
SELECT t.*,
ROWNUM AS rn -- Secondly, assign a row number to the ordered rows
FROM (
SELECT *
FROM your_table
ORDER BY your_condition -- First, order the data
) t
)
WHERE rn - POWER( -- Finally, filter the top 100.
2,
TRUNC( CAST( LOG( 2, CEIL( rn / 1000 ) ) AS NUMBER(20,4) ) )
) * 1000 + 1000 <= 100
This will take the first 100 rows from the groups 1-1000, 1001-3000, 3001-7000, 7001-15000, etc.
Or, to get the rows:
1-100,2000-2100,4000-4100,8000-8100,16000-16100, 32000-32100 and so on.
Then:
WHERE CASE -- Finally, filter the top 100.
WHEN rn <= 2000 THEN rn
ELSE rn - POWER(
2,
TRUNC( CAST( LOG( 2, CEIL( rn / 1000 - 1 ) ) AS NUMBER(20,4) ) )
) * 1000
END <= 100
You could use power function and simple hierarchical query, then join it with your table. Here is example with all_objects view:
with rng as (select 0 num from dual union all
select 1000 * power(2, level) from dual connect by level < 10 )
select *
from (select row_number() over (order by object_name) rn, object_name from all_objects)
join rng on rn between num + 1 and num + 100
From what you describe, you can use logs to define the groups. This is probably close enough to what you want:
select t.*
from (select t.*,
row_number() over (floor(log(2, floor(1 + (seqnum - 1) / 1000) ))
order by col
) as seqnum_2
from (select t.*, row_number() over (order by col) as seqnum
from t
) t
where seqnum_2 <= 100;
The difference from your description is that the first group is 1-999, 1000-1999, and so on.

How to get the middle most record(s) from a group of data in sql

create table #middle
(
A INT,
B INT,
C INT
)
INSERT INTO #middle (A,B,C) VALUES (7,6,2),(1,0,8),(9,12,16),(7, 16, 2),(1,12,8), (9,12,16),(9,12,16),(7, 16, 2),(1,12,8), (9,12,16)
;WITH MIDS
AS (SELECT *,
Row_number()
OVER (
ORDER BY a, b, c DESC )AS rn
FROM #middle)
SELECT *
FROM MIDS
WHERE rn <= (SELECT CASE ( Count(*)%2 )
WHEN 0 THEN ( Count(*) / 2 ) + 1
ELSE ( Count(*) / 2 )
END
FROM MIDS) except (SELECT *
FROM MIDS
WHERE rn < (SELECT ( Count(*) / 2 )
FROM MIDS))
The query i have tried works >4 records but not for '3'.Now my question is how should i modify my query so that for 3 records i should get the 2nd record which is the middle most record among them,try to insert only 3 records from above records and help. Thanks in advance.
You can use OFFSET and FETCH
select *
from #middle
order by a, b, c desc
offset (select count(*) / 2 - (case when count(*) % 2 = 0 then 1 else 0 end) from #middle) rows
fetch next (select 2 - (count(*) % 2) from #middle) rows only
There are many ways to get the median in SQL. Here is a simple way:
select h.*
from (select h.*, row_number() over (order by a, b, c desc) as seqnum,
count(*) over () as cnt
from #highest h
) h
where 2 * rn in (cnt, cnt - 1, cnt + 1);
For an even number of records, you will get two rows. You need to decide what you actually want in this case.
How about this:
**EDITED
;WITH MIDS
AS (SELECT *,
Row_number()
OVER (
ORDER BY a, b, c DESC )AS rn
FROM #middle),
Cnt
AS
(SELECT COUNT(*) c, COUNT(*)%2 as rem, COUNT(*)/2 as mid FROM Mids)
SELECT *
FROM MIDS
CROSS APPLY cnt
where (rn >= cnt.mid and rn <= cnt.mid + 1 AND cnt.rem = 0) OR
(cnt.rem <> 0 AND rn = cnt.mid+1)

Paging in SQL, how to use row number in where clause?

I am trying to use the row numbers from MSSQL in the where clause of my SELECT query (in a stored procedure) however it won't let me reference that column in the where clause. How would you usually go about such a thing?
I'm trying the following (which doesn't work):
SELECT ROW_NUMBER() OVER(ORDER BY [dtd]) AS row_num, [data]
FROM dbo.Reports INNER JOIN dbo.Types
WITH (NOLOCK)
ON dbo.Reports.type = dbo.Types.id
WHERE [dbo].[Reports].[Id] = #Id AND (row_num < (#page - 1) * 30) AND (row_num > #page * 30)
ORDER BY [dtd] DESC
You can use a CTE:
WITH CTE AS
(
SELECT ROW_NUMBER() OVER(ORDER BY [dtd]) AS row_num, [data]
FROM dbo.Reports INNER JOIN dbo.Types
WITH (NOLOCK)
ON dbo.Reports.type = dbo.Types.id
WHERE [dbo].[Reports].[Id] = #Id
)
SELECT * FROM CTE
WHERE (row_num < (#page - 1) * 30) AND (row_num > #page * 30)
ORDER BY [dtd] DESC

SQL WITH Statement, Unknown Column in where clause

I ve got the following query which is throwing the following error
Unkown Column 'RowNum'
WITH Employees AS
(
SELECT
(keyTblSp.RANK * 3) AS [Rank],
sp.*,
addr.Street,
addr.PostOfficeBox,
addr.StreetNumber
FROM Employee sp
INNER JOIN
FREETEXTTABLE(Employee, *, 'something', 1000) AS keyTblSp
ON sp.EmployeeId = keyTblSp.[KEY]
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId
UNION ALL
SELECT
(keyTblAddr.RANK * 2) AS [Rank],
sp.*,
addr.Street,
addr.PostOfficeBox,
addr.StreetNumber
FROM Employee sp
LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = sp.EmployeeId
INNER JOIN
FREETEXTTABLE([Address], *, 'something', 1000) AS keyTblAddr
ON addr.AddressId = keyTblAddr.[KEY]
)
SELECT ROW_NUMBER() OVER (ORDER BY [Rank] DESC) AS RowNum, *
FROM Employees
WHERE RowNum BETWEEN (1 - 1) * 10 + 1 AND 1 * 10
ORDER BY Rank DESC
This is because aliases are not recognized in WHERE clauses. Instead, use the full query like this:
WHERE ROW_NUMBER() OVER (ORDER BY [Rank] DESC) BETWEEN (1 - 1) * 10 + 1 AND 1 * 10
Try wrpping up your query to get the name usable in the where clause
SELECT
*
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY [Rank] DESC) AS RowNum
, *
FROM
Employees) AS Results
WHERE
RowNum BETWEEN (1 - 1) * 10 + 1 AND 1 * 10
ORDER BY
Rank
Your WHERE clause cannot refer to a window or aggregate function like ROW_NUMBER(). If you want to filter on the result of ROW_NUMBER(), you need to do so in the HAVING clause:
...
SELECT ROW_NUMBER() OVER (ORDER BY [Rank] DESC) AS RowNum, *
FROM Employees
HAVING RowNum BETWEEN (1 - 1) * 10 + 1 AND 1 * 10
ORDER BY Rank DESC
How about:
select top 10 *
from Employees
order by Rank Desc
Alternatively, does it work without the where rownum clause. (why is your between so tricky?).