Sqlite get ROW NUMBER and COUNT of records found on every SELECT request - sql

I´m using Sqlite3 on a grid application pretty much like that post here..
The grid needs the rows that is being show and the total number of rows found, used for paging.
On Oracle I use the following statement to get rows from 100 to 500 - fields Id, Name, Phone where Deleted=false:
SELECT * FROM (SELECT ROW_NUMBER()
OVER (ORDER BY ID) AS RN,
COUNT(*) OVER (ORDER BY (SELECT NULL) AS CNT)
Id, Name, Phone FROM MyTable WHERE Deleted='F')
T WHERE RN > 100 AND RN < 500;
On MySQl, I normally use the excellet SELECT SQL_CALC_FOUND_ROWS followed by a SELECT FOUND_ROWS() call.
So my questions are:
a) Is there any equivalent of this Sqlite3 for either Oracle or MySQL option above ?
b) How can I accomplish that on Sqlite3 without issuing 2 selects (one for querying and another one for counting) ?
The question posted here does not solve my problem because it does not return the number of records, just pages through the table.
Thanks a lot for helping...

In recent versions of SQLite (3.25.0 and later) there is support for window functions. So you can rewrite your query as follows:
SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID) AS RN,
COUNT() OVER () AS CNT,
Id, Name, Phone FROM MyTable WHERE Deleted='F')
T WHERE RN > 100 AND RN < 500;

Related

Get Row Number according to a specific condition by sqlite

I have 3 Tables:
So I need an SQLite query that shows me the Row Number of the s_id=7 ( it must be here 3 )
I search too much on the Internet to find tips but I didn't find! it will be perfect if someone can help me with that.
You can use window functions like this:
select *
from (
select s_id, row_number() over(order by s_id) as rn
from section
) s
where s_id = 7
Or, if your version of SQLite does not support window functions, you can use a subquery:
select s_id,
(select count(*) from section s1 where s1.s_id <= s.id) as rn
from section s
where s_id = 7

Is there an efficiency problem with my query to select middle rows?

I am trying to select rows 3 - 5 of:
SELECT *
FROM Finance_User
ORDER BY email DESC
I originally had just:
SELECT
ROW_NUMBER() OVER (ORDER BY email DESC) AS RowNum, *
FROM
Finance_User
WHERE
RowNum BETWEEN 3 AND 5
But this did not work as RowNum was an invalid column.
Instead I did the below:
WITH OrderedUsers AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY email DESC) AS RowNum, *
FROM
Finance_User
)
SELECT *
FROM OrderedUsers
WHERE RowNum BETWEEN 3 AND 5
This works perfectly fine. However, I am concerned that there might be performance issues with this as it seems to be selecting from the table twice?
ROW_NUMBER() with a CTE (or a subquery) won't scan the table twice. However using the window function might incur additional processing for the RDBMS.
You could achieve the same results with ORDER BY ... OFFSET ... FETCH ..., available starting SQL-Server 2012, that are provided specifically for the purpose of paging a resultset:
SELECT *
FROM Finance_User
ORDER BY email DESC
OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY
From the documentation:
We recommend that you use the OFFSET and FETCH clauses instead of the TOP clause to implement a query paging solution and limit the number of rows sent to a client application.
Your query is fine.
WITH AS clause is a Common Table Expression which means that this query may be reused later and should be cached if needed and possible. So there should not be any problem with "selecting from the table twice".
The same result you can get with this query:
SELECT * from
(SELECT ROW_NUMBER() OVER (ORDER BY email DESC) AS RowNum, * FROM Finance_User)
where RowNum between 3 and 5
And finally, you can always check execution plan and make sure of it as well.

Selecting a 1% sample in Aginity Workbench SQL

I need to scoop up a random sample of 1% of the records in a table (with the number of rows growing every second).
My idea is to
SELECT DISTINCT
random(),
name,
age,
registrationNumber
FROM everGrowingTable
ORDER BY random desc
LIMIT (
(select count(*) from everGrowingTable) * 0.01
) -- this is attempting to get 1%
The compiler complains about the * operator. It is fine when I hard code the table size however.
I've tried IBM documentation, but this talks about calculations using known values, not values that grow (such is that case in my table)
There doesn't seem to be a Aginity SQL function that does this. I've notice the MINUS function in the Aginity Workbench Intellisense, but alas, no multiplication equivalent.
You could use window functions in a subquery to assign a random number to each record and compute the total record number, and then do the filtering in the outer query :
SELECT name, age, registrationNumber
FROM (
SELECT
name,
age,
registrationNumber,
ROW_NUMBER() OVER(ORDER BY random()) rn,
COUNT(*) OVER() cnt
FROM everGrowingTable
) x
WHERE rn <= cnt / 100
ORDER BY rn

Get two most frequent data from SQL tbl?

i have a tbl call it tbl_test in which continously data are inserting and it has approx 10^6 records at a time it has colums
Acquire_Id (Value between 1 to 20 ),
Status_Msg(value between 'A' to 'Z'),
Status_Code(value between 1 to 26)
There is one to one mapping b/w Status_Msg and Status_Code
Now i want to get two most frequent status_msg and Staus_Code Count for each acquirer if they are present in table
Query should be Cost Saving
Most databases support the ANSI standard window functions. You can get what you want using row_number() (or rank() or dense_rank(), depending on how ties are returned) after aggregating the values.
The following returns exactly two rows for each acquirer (even if there are ties).
select t.*
from (select t.acquire_id, t.status_msg, t.status_code, count(*) as cnt,
row_number() over (partition by t.acquire_id order by count(*) desc) as seqnum
from tbl_test t
group by t.acquire_id, t.status_msg, t.status_code
) t
where seqnum <= 2;

How do I use ROW_NUMBER()?

I want to use the ROW_NUMBER() to get...
To get the max(ROW_NUMBER()) --> Or i guess this would also be the count of all rows
I tried doing:
SELECT max(ROW_NUMBER() OVER(ORDER BY UserId)) FROM Users
but it didn't seem to work...
To get ROW_NUMBER() using a given piece of information, ie. if I have a name and I want to know what row the name came from.
I assume it would be something similar to what I tried for #1
SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'
but this didn't work either...
Any Ideas?
For the first question, why not just use?
SELECT COUNT(*) FROM myTable
to get the count.
And for the second question, the primary key of the row is what should be used to identify a particular row. Don't try and use the row number for that.
If you returned Row_Number() in your main query,
SELECT ROW_NUMBER() OVER (Order by Id) AS RowNumber, Field1, Field2, Field3
FROM User
Then when you want to go 5 rows back then you can take the current row number and use the following query to determine the row with currentrow -5
SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
FROM User ) us
WHERE Row = CurrentRow - 5
Though I agree with others that you could use count() to get the total number of rows, here is how you can use the row_count():
To get the total no of rows:
with temp as (
select row_number() over (order by id) as rownum
from table_name
)
select max(rownum) from temp
To get the row numbers where name is Matt:
with temp as (
select name, row_number() over (order by id) as rownum
from table_name
)
select rownum from temp where name like 'Matt'
You can further use min(rownum) or max(rownum) to get the first or last row for Matt respectively.
These were very simple implementations of row_number(). You can use it for more complex grouping. Check out my response on Advanced grouping without using a sub query
If you need to return the table's total row count, you can use an alternative way to the SELECT COUNT(*) statement.
Because SELECT COUNT(*) makes a full table scan to return the row count, it can take very long time for a large table. You can use the sysindexes system table instead in this case. There is a ROWS column that contains the total row count for each table in your database. You can use the following select statement:
SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2
This will drastically reduce the time your query takes.
You can use this for get first record where has clause
SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum
FROM Users
WHERE UserName = 'Joe'
ORDER BY rownum ASC
ROW_NUMBER() returns a unique number for each row starting with 1. You can easily use this by simply writing:
ROW_NUMBER() OVER (ORDER BY 'Column_Name' DESC) as ROW_NUMBER
May not be related to the question here. But I found it could be useful when using ROW_NUMBER -
SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID
FROM #Any_Table
select
Ml.Hid,
ml.blockid,
row_number() over (partition by ml.blockid order by Ml.Hid desc) as rownumber,
H.HNAME
from MIT_LeadBechmarkHamletwise ML
join [MT.HAMLE] h on ML.Hid=h.HID
SELECT num, UserName FROM
(SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
From Users) AS numbered
WHERE UserName='Joe'
You can use Row_Number for limit query result.
Example:
SELECT * FROM (
select row_number() OVER (order by createtime desc) AS ROWINDEX,*
from TABLENAME ) TB
WHERE TB.ROWINDEX between 0 and 10
--
With above query, I will get PAGE 1 of results from TABLENAME.
If you absolutely want to use ROW_NUMBER for this (instead of count(*)) you can always use:
SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)
FROM USERS
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC
Need to create virtual table by using WITH table AS, which is mention in given Query.
By using this virtual table, you can perform CRUD operation w.r.t row_number.
QUERY:
WITH table AS
-
(SELECT row_number() OVER(ORDER BY UserId) rn, * FROM Users)
-
SELECT * FROM table WHERE UserName='Joe'
-
You can use INSERT, UPDATE or DELETE in last sentence by in spite of SELECT.
SQL Row_Number() function is to sort and assign an order number to data rows in related record set. So it is used to number rows, for example to identify the top 10 rows which have the highest order amount or identify the order of each customer which is the highest amount, etc.
If you want to sort the dataset and number each row by seperating them into categories we use Row_Number() with Partition By clause. For example, sorting orders of each customer within itself where the dataset contains all orders, etc.
SELECT
SalesOrderNumber,
CustomerId,
SubTotal,
ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SubTotal DESC) rn
FROM Sales.SalesOrderHeader
But as I understand you want to calculate the number of rows of grouped by a column. To visualize the requirement, if you want to see the count of all orders of the related customer as a seperate column besides order info, you can use COUNT() aggregation function with Partition By clause
For example,
SELECT
SalesOrderNumber,
CustomerId,
COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader
This query:
SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'
will return all rows where the UserName is 'Joe' UNLESS you have no UserName='Joe'
They will be listed in order of UserID and the row_number field will start with 1 and increment however many rows contain UserName='Joe'
If it does not work for you then your WHERE command has an issue OR there is no UserID in the table. Check spelling for both fields UserID and UserName.