Forum Discussion
how to create a query that paginates?
Getting the total number of results and paginating are two different operations. For the sake of this example, let's assume that the query you're dealing with is
SELECT * FROM Orders WHERE OrderDate >= '1980-01-01' ORDER BY OrderDateIn this case, you would determine the total number of results using:
SELECT COUNT(*) FROM Orders WHERE OrderDate >= '1980-01-01'
...which may seem inefficient, but is actually pretty performant, assuming all indexes etc. are properly set up.
Next, to get actual results back in a paged fashion, the following query would be most efficient:
SELECT *
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY OrderDate ) AS RowNum, *
FROM Orders
WHERE OrderDate >= '1980-01-01'
) AS RowConstrainedResult
WHERE RowNum >= 1
AND RowNum < 20
ORDER BY RowNum
This will return rows 1-19 of the original query. The cool thing here, especially for web apps, is that you don't have to keep any state, except the row numbers to be returned.
- Anonymous5 years agoNot applicable
Thank you very much for your answer Anonymous !
I am so sorry, but I have no clue, how your answer helps me.
JIRA Rest API is limited to 1000 rows. As I understand it right, the problem is, I need some looping mechanism to get all datas. List.Generate seems like to act like a loop. But unfortunately I don´t get to work...
So I hope somebody already had the same problem.
freiburgc
- Anonymous5 years agoNot applicable
Here is a sample that I used on a similar issue. You can use list.generate in a similar way to loop thru all pages.
let
BaseUrl = "http://xxxx",
Token = [Headers=[#"key"="xxx"]],
EntitiesPerPage = 1000,
WebCall = try Json.Document(Web.Contents(BaseUrl,Token)),
Value = WebCall[Value],
count = Value[totalHits],
countMax = Number.RoundUp(List.Max({1,count/EntitiesPerPage})),nextURL = (counter,sid ) =>
let
url = BaseUrl & "&pageNumber=" & Text.From(counter) & "&scrollId="&Text.From(Record.Field(sid,"Value")),
call = Web.Contents(url,Token)
in
call,
FnGetOnePage =
(url) as record =>
let
Source = Json.Document(url),
data = try Source[featureMatchEvents] ,
next = try Source[scrollId] ,
res = [Data=data, Next=next]
in
res,
GeneratedList =
List.Generate(
()=>[i=1, res = FnGetOnePage(nextURL(1,[Value=""]))],
each [i]<countMax,
each [i=[i]+1, res = FnGetOnePage(nextURL(i,[res][Next]))],
each [res][Data]), - Anonymous5 years agoNot applicable
Hi Anonymous ,
This can be sorted by following the below steps.
You'll require 4 add ons i.e., 1 parameter and 3 functions. Replace the information suiting your organization URL.
- Parameter: URL
e.g., https : // [Replace with your organization URL] / jira
- Function 01: FetchPage
let
FetchPage = (url as text, pageSize as number, skipRows as number) as table =>
let
//Here is where you run the code that will return a single page
contents = Web.Contents(URL&"/rest/api/2/search",[Query = [maxResults= Text.From(pageSize), startAt = Text.From(skipRows)]]),
json = Json.Document(contents),
Value = json[issues],
table = Table.FromList(Value, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
table meta [skipRows = skipRows + pageSize, total = 500]
in
FetchPage
- Function: FetchPages
let
FetchPages = (url as text, pageSize as number) =>
let
Source = GenerateByPage(
(previous) =>
let
skipRows = if previous = null then 0 else Value.Metadata(previous)[skipRows],
totalItems = if previous = null then 0 else Value.Metadata(previous)[total],
table = if previous = null or Table.RowCount(previous) = pageSize then
FetchPage(url, pageSize, skipRows)
else null
in table,
type table [Column1])
in
Source
in
FetchPages
- Function: GeneratebyPage
(getNextPage as function, optional tableType as type) as table =>
let
listOfPages = List.Generate(
() => getNextPage(null),
(lastPage) => lastPage <> null,
(lastPage) => getNextPage(lastPage)
),
tableOfPages = Table.FromList(listOfPages, Splitter.SplitByNothing(), {"Column1"}),
firstRow = tableOfPages{0}?,
keys = if tableType = null then Table.ColumnNames(firstRow[Column1])
else Record.FieldNames(Type.RecordFields(Type.TableRow(tableType))),
appliedType = if tableType = null then Value.Type(firstRow[Column1]) else tableType
in
if tableType = null and firstRow = null then
Table.FromRows({})
else
Value.ReplaceType(Table.ExpandTableColumn(tableOfPages, "Column1", keys), appliedType)
Once the above is created, the next step will be is to use the function and parameters to retrieve the content. you can start with the below and expand the fields of choice to create your report.
Main query:
let
Source = FetchPages("", 500),
#"Expanded Column1" = Table.ExpandRecordColumn(Source, "Column1", {"key", "fields"}, {"key", "fields"}),
in
#"Expanded Column1"
Hope this helps you to build the report. Please note this query is only the search information and if you'd need change log information you can modify that in the 2nd function listed above.
Good luck.
Cheers,
Anand
- Anonymous5 years agoNot applicable
Hi Anonymous ,
Thanks a lot for your answer!!!
Unfortunately I still have a few because, because this topic overtaxes me at the moment a bit.
I added the parameter URL and it works.
The next step is to paste all the functions to my query, right?
I did it and got a failure on Function: FetchPages, there is a problem with “let”.
I don´t know why.
To understand a bit what your code does I just added 1.Function 01:FetchPage to my query.
I got three parameters: URL, SkipRows and pageSize.
Do I understood the first function right, that this one can give my table on one page, depending on the pageSize? If I add 2000 to this parameter, I get 2000 rows on one page. However, it´s just static and not dynamical?
Sorry for stupid questions, but M-language is difficult for me and try to understand it.
thanks a lot for your support and hopefully your patience!
freiburgc