Ga verder naar hoofdinhoud

Power Query-functies en voorbeeldquery's

Combineer de door Cognite Data Fusion (REST API) connector for Power BI weergegeven functies met Power Query om gegevens op te halen en te transformeren, en met de Cognite API om rapporten en dashboards te maken met Microsoft Power BI en Microsoft Excel.

Bèta

De functies die in dit gedeelte worden beschreven, worden momenteel in de bètafase getest door geselecteerde klanten en kunnen nog worden gewijzigd.

Kopieer de query's en Power Query-functies op deze pagina en pas ze aan uw zakelijke behoeften aan.

Nuttige functies

Tijdstempels van/naar tijdperk converteren

CDF-resourcetypen verwachten en retourneren tijdstempels in milliseconden sinds het Unix-tijdperk. Power Query beschikt niet over methoden om deze indeling automatisch te parseren naar een datetimezone-type om tijdstempels met informatie over de tijdzone weer te geven. CDF-gegevensmodellen geven tijdstempels weer in de ISO 8601-indeling voor primitieve velden.

Gebruik de onderstaande functies om te converteren tussen een datetimezone-variabele en milliseconden sinds het Unix-tijdperk en van een datetimezone-variabele naar tekst in de ISO 8601-indeling.

ConvertDateTimeZoneToMs

Convert datetimezone to milliseconds since epoch
//
(dtz as datetimezone) as number =>
let
// Convert the input DateTimeZone to UTC
UtcDateTime = DateTimeZone.RemoveZone(DateTimeZone.SwitchZone(dtz, 0)),
// Define the Unix epoch start
UnixEpochStart = #datetime(1970, 1, 1, 0, 0, 0),
// Calculate the duration between the input date and Unix epoch start
Delta = UtcDateTime - UnixEpochStart,
// Convert duration to total milliseconds
TotalMilliseconds = Duration.TotalSeconds(Delta) * 1000
in
TotalMilliseconds

ConvertMsToDateTimeZone

Convert milliseconds since epoch to datetimezone
(ms as number) as datetimezone =>
let
// Convert ms to seconds
SecondsSinceEpoch = ms / 1000,

// Create a duration
DurationSinceEpoch = #duration(0, 0, 0, SecondsSinceEpoch),

// Add duration to Unix epoch start to get UTC datetime
UnixEpochStart = #datetime(1970, 1, 1, 0, 0, 0),
UtcDateTime = UnixEpochStart + DurationSinceEpoch,

// Convert UTC datetime to local time zone
LocalDateTimeZone = DateTimeZone.From(UtcDateTime)
in
LocalDateTimeZone

ConvertDateTimeZoneToIso

Convert DateTimeZone to ISO 8601 text representation
(dtz as datetimezone) as text =>
let
// Use DateTimeZone.ToText with ISO 8601 format
Result = DateTimeZone.ToText(dtz, [Format="yyyy-MM-ddTHH:mm:sszzz", Culture="en-US"])
in
Result

Functie toevoegen

Als u een nieuwe functie wilt toevoegen in Power Query, selecteert u Get Data > Blank Query en schrijft u uw functie of kopieert u een van de onderstaande functies.

Tijdsdelta's

Het is gebruikelijk om start- en eindtijdstempels te definiëren op basis van tijdsverschillen. De waarden worden bijgewerkt wanneer een gegevensset wordt vernieuwd. In het onderstaande voorbeeld is EndTime de huidige tijd, en is StartTime 7 dagen vóór EndTime. U kunt dit voorbeeld aanpassen om andere tijdsverschillen te gebruiken.

Time deltas
CurrentTime = DateTimeZone.LocalNow(),
EndTime = CurrentTime,
StartTime = CurrentTime - #duration(7, 0, 0, 0)

Algemene GET-aanvraag

Wanneer u gegevens uit CDF ophaalt via de GetCDF-functie uit de CDF REST API connector for Power BI, moet u queryparameters gebruiken om filters door te geven waarmee u de gegevens selecteert die u wilt ophalen.

Het onderstaande voorbeeld laat zien hoe u de queryparameters externalIdPrefix en limit vanuit het eindpunt van /timeseries kunt toevoegen aan de URL om gegevens op de server te filteren.

List all time series instances with an externalId starting with a specific string
let
Source = GetCDF("/timeseries?externalIdPrefix=EVE&limit=1000")
in
Source

Algemene POST-aanvraag

Wanneer u gegevens uit CDF ophaalt met de functie PostCDF, moet u een aanvraagtekst schrijven om te selecteren welke gegevens u wilt ophalen. De functie accepteert een tekstuele weergave van de JSON-tekst, maar u kunt de tekst ook schrijven met een Power Query-recordgegevenstype en dit vervolgens converteren naar een JSON-tekstgegevenstype voordat u de waarde aan de PostCDF-functie doorgeeft.

List all data modeling instances for a view using the DMS API
let
SpaceExternalId = "Geography",
ViewExternalId = "City",
ViewVersion = "1",
Body = [
sources = {
[
source = [
type = "view",
space = SpaceExternalId,
externalId = ViewExternalId,
version = ViewVersion
]
]
},
limit = 1000
],
BodyText = Text.FromBinary(Json.FromValue(Body)),
Source = PostCDF("/models/instances/list", BodyText)
in
Source

U kunt de POST-tekst ook handmatig als tekst schrijven, maar u moet dan dubbele aanhalingstekens (") gebruiken, omgeven door een andere set dubbele aanhalingstekens:

let
BodyText = "{""sources"": [{""source"": {""type"": ""view"", ""space"": ""Geography"", ""externalId"": ""City"", ""version"": ""1""}}], ""limit"": 1000}",
Source = PostCDF("/models/instances/list", BodyText)
in
Source

Als u een POST-aanvraag opnieuw wilt gebruiken, kunt u deze omzetten in een Power Query-functie. Bijvoorbeeld:

(SpaceExternalId as text, ViewExternalId as text, ViewVersion as text) as table =>
let
Body = [
sources = {
[
source = [
type = "view",
space = SpaceExternalId,
externalId = ViewExternalId,
version = ViewVersion
]
]
},
limit = 1000
],
BodyText = Text.FromBinary(Json.FromValue(Body)),
Source = PostCDF("/models/instances/list", BodyText)
in
Source

U kunt de functienaam definiëren door met de rechtermuisknop op het item in de querylijst in de Power Query-editor te klikken en Naam wijzigen te selecteren.

Als de bovenstaande functie de naam ListInstancesDMS heeft, kunt u deze gebruiken in een nieuwe query door de veldwaarden in te voeren in Power Query of door een nieuwe query te schrijven:

let
Source = ListInstancesDMS("Geography", "City", "1")
in
Source

GraphQL-aanvragen

Wanneer u gegevens uit CDF ophaalt via de GraphQL-functie, moet u een GraphQL-aanvraag schrijven om te selecteren welke gegevens u wilt ophalen uit een specifiek gegevensmodel. De functie verwacht dat u de externe ID van de space, de externe ID van de view, de versie van de view, de uit te voeren GraphQL-query en optioneel een set variabelen opgeeft die in de query moeten worden gebruikt.

De onderstaande query gebruikt de GraphQL-syntaxis en geeft de variabelen door als JSON-teksten. Door variabelen in de query te gebruiken, kunt u eenvoudiger parameters toekennen en externe waarden gebruiken.

List all work orders with an end date greater than a specific date
let
Source = GraphQL(
"cdf_idm",
"CogniteProcessIndustries",
"v1",
"query MyQuery($cursor: String, $endTime: Timestamp) {#(lf) listCogniteMaintenanceOrder(#(lf) first: 1000#(lf) after: $cursor#(lf) filter: {endTime: {gte: $endTime}}#(lf) ) {#(lf) items {#(lf) name#(lf) type#(lf) startTime#(lf) endTime#(lf) priority#(lf) }#(lf) pageInfo {#(lf) endCursor#(lf) hasNextPage#(lf) }#(lf) }#(lf)}",
"{""endTime"": ""2024-10-01T00:00:00+02:00""}"
)
in
Source

De M-taal die momenteel door Power Query wordt gebruikt, ondersteunt geen tekenreeksen met meerdere regels. De query moet dus op één regel staan. De #(lf) staat voor een regelafbrekingsteken. In het bovenstaande voorbeeld is de query geplakt in het tekstvakveld in Power Query en zijn de variabelen als JSON-tekst doorgegeven. Power BI heeft regeleinden toegevoegd aan de oorspronkelijke query en deze worden weergegeven als een tekstvariabele met één regel.

U kunt de query ook schrijven als meerdere teksten van één regel en de Text.Combine-functie gebruiken om de regeleinden toe te voegen aan de query. U kunt de variabelen definiëren als Power Query-records en ze omzetten in JSON-tekst voordat u ze doorgeeft aan de GraphQL-functie. Zie bijvoorbeeld hoe de functie ConvertDateTimeZoneToIso een datetimezone-variabele omzet in een tekstweergave in de ISO 8601-indeling en deze vervolgens als variabele doorgeeft aan de query.

let
// This could be a parameter or referenced from another query
EndTime = #datetimezone(2024, 10, 1, 0, 0, 0, 2, 0),
VariablesRecord = [
endTime = ConvertDateTimeZoneToIso(EndTime)
],
VariablesText = Text.FromBinary(Json.FromValue(VariablesRecord)),
Query = Text.Combine({
"query MyQuery($cursor: String, $endTime: Timestamp) {",
" listCogniteMaintenanceOrder(",
" first: 1000",
" after: $cursor",
" filter: {endTime: {gte: $endTime}}",
" ) {",
" items {",
" name",
" type",
" startTime",
" endTime",
" priority",
" }",
" pageInfo {",
" endCursor",
" hasNextPage",
" }",
" }",
"}"
}, "#(lf)"),
Data = GraphQL(
"cdf_idm",
"CogniteProcessIndustries",
"v1",
Query,
VariablesText
)
in
Data

Geavanceerde voorbeelden

Afhankelijk van de vorm van de Cognite API-respons hebt u mogelijk aanvullende Power Query-transformaties nodig om de gegevens op te halen en te transformeren. Kopieer de onderstaande voorbeelden en pas ze aan uw zakelijke behoeften aan.

Rijen met reeksen ophalen met de functie PostCDF

De onderstaande Power Query-functie haalt gegevens op uit rijen met reeksen en verwerkt deze voor een externe reeks-ID van CDF. Er wordt een POST-aanvraag verzonden, kolominformatie wordt opgehaald, geneste reactiegegevens worden uitgevouwen en de gegevens worden opnieuw geordend in tabelvorm. De functie verwerkt de conversie van gegevenstypen, verwijdert onnodige velden en groepeert gegevens per rij. Het eindresultaat is een goed gestructureerde tabel met correct getypte kolommen.

Fetch sequence rows with PostCDF
(externalId as text) as table =>
let
RequestBody = "{""externalId"": """ & externalId & """, ""limit"": 10000}",
Response = PostCDF("/sequences/data/list", RequestBody),
// Extract columns information from the first page
FirstPage = Response{0},
Columns = FirstPage[columns],
ColumnNames = List.Transform(Columns, each [externalId]),
ColumnTypes = List.Transform(Columns, each
if [valueType] = "STRING" then type text else
if [valueType] = "DOUBLE" then type number else
if [valueType] = "LONG" then Int64.Type
else type any
),
// Extract the 'values' from each row
Rows = Table.ExpandListColumn(Response, "rows"),
ValuesTable = Table.ExpandRecordColumn(Rows, "rows", {"rowNumber", "values"}, {"rows.rowNumber", "rows.values"}),
RemoveColumns = Table.RemoveColumns(ValuesTable,{"id", "externalId", "columns", "nextCursor"}),
ExpandValues = Table.ExpandListColumn(RemoveColumns, "rows.values"),
// Group by rowNumber and create a record for each row
GroupedRows = Table.Group(ExpandValues, {"rows.rowNumber"}, {
{"RowData", (t) => Record.FromList(t[rows.values], ColumnNames)}
}),
// Expand the RowData column
ExpandRows = Table.ExpandRecordColumn(GroupedRows, "RowData", ColumnNames),
// Set column data types
FinalTable = Table.TransformColumnTypes(ExpandRows, List.Zip({ColumnNames, ColumnTypes}))
in
FinalTable

De functie gebruiken:

let
Source = RetrieveSequenceRows("sequence-externalId")
in
Source

Exemplaren ophalen van het DMS-query-eindpunt met de PostCDF-functie

Met de onderstaande Power Query-functie worden gegevensmodelleringsexemplaren voor een DMS-query opgehaald en verwerkt. Er wordt door de reactie gebladerd, de exemplaren worden geëxtraheerd en de geneste gegevens worden uitgevouwen.

Fetch instances from the DMS query endpoint with PostCDF
(query as text) as table =>
let
FetchPage = (query as text, optional cursors as nullable record) as table =>
let
Query = Json.Document(query),
UpdatedQuery =
if cursors <> null then
let
// Get all field names of both records
QueryWithFields = Record.FieldNames(Query[with]),
QUerySelectFields = Record.FieldNames(Query[select]),
CursorsFields = Record.FieldNames(cursors),
// Find the intersection of field names
CommonFields = List.Intersect({QueryWithFields, QUerySelectFields, CursorsFields}),
// Create new records containing only the common fields
UpdatedQueryWithAndSelect = Record.TransformFields(
Query,
{
{"with", each Record.SelectFields(_, CommonFields)},
{"select", each Record.SelectFields(_, CommonFields)}
}
)
in
UpdatedQueryWithAndSelect
else
Query,
// Add cursors if they are provided
UpdatedQueryWithCursors =
if cursors <> null then
Record.AddField(UpdatedQuery, "cursors", cursors)
else
UpdatedQuery,
FinalBody = Text.FromBinary(Json.FromValue(UpdatedQueryWithCursors)),
Response = PostCDF("/models/instances/query", FinalBody)
in
Response,
// Helper function to create next cursor record from result table
CreateNextCursorRecordFromTable = (inputTable as table) as record =>
let
RecordsList = List.Transform(
Table.ToRecords(inputTable), each Record.FromList({[nextCursor]}, {[resultExpression]})
),
CombinedRecord = Record.Combine(RecordsList)
in
CombinedRecord,
// Helper function to check if all cursors are null
AllCursorsNull = (cursorsRecord as record) as logical =>
let
CursorValues = Record.ToList(cursorsRecord),
NullCount = List.Count(List.Select(CursorValues, each _ = null))
in
NullCount = List.Count(CursorValues),
// Helper function to aggregate items from all pages and convert to tables
AggregateResults = (results as list) as table =>
let
// Combine all tables
CombinedTable = Table.Combine(results),
// Group by resultExpression and convert items to tables
GroupedTable = Table.Group(
CombinedTable,
{"resultExpression"},
{
{
"items",
each
Table.FromRecords(
List.Combine(List.Transform([items], each if Value.Is(_, type list) then _ else {
_
}))
),
type table
}
}
)
in
GroupedTable,
// Main pagination logic
FetchAllPages = () as list =>
let
// Initialize accumulator
InitialAcc = [
results = {},
currentCursors = null,
hasMore = true
],
// Pagination function
PaginationFunction = (acc as record) =>
let
CurrentPage = FetchPage(query, acc[currentCursors]),
NextCursors = CreateNextCursorRecordFromTable(CurrentPage),
HasMoreResults = not AllCursorsNull(NextCursors) and Table.RowCount(CurrentPage) > 0,
UpdatedResults = List.Combine({acc[results], {CurrentPage}})
in
[
results = UpdatedResults,
currentCursors = NextCursors,
hasMore = HasMoreResults
],
// Keep fetching until no more results
AllResults = List.Generate(
() => InitialAcc, each _[hasMore], each PaginationFunction(_), each _[results]
),
// Get the final list of results
FinalResults = List.Last(AllResults)
in
FinalResults,
// Execute pagination and combine results
AllPages = FetchAllPages(),
FinalTable = AggregateResults(AllPages)
in
FinalTable

De functie gebruiken:

let
Query = [
with = [
cities = [
nodes = [
filter = [
hasData = {
[
space = "Geography",
externalId = "City",
version = "1",
#"type" = "view"
]
}
],
chainTo = "destination",
direction = "outwards"
]
],
countries = [
nodes = [
filter = [
hasData = {
[
space = "Geography",
externalId = "Country",
version = "1",
#"type" = "view"
]
}
],
chainTo = "destination",
direction = "outwards"
]
]
],
select = [
cities = [
sources = {
[
source = [
space = "Geography",
externalId = "City",
version = "1",
#"type" = "view"
],
properties = {
"name"
}
]
}
],
countries = [
sources = {
[
source = [
space = "Geography",
externalId = "Country",
version = "1",
#"type" = "view"
],
properties = {
"name"
}
]
}
]
]
],
QueryText = Text.FromBinary(Json.FromValue(Query)),
Source = QueryDMS(QueryText)
in
Source
tip

Voeg filters toe zoals het hasData-filter in het bovenstaande voorbeeld om te voorkomen dat alle exemplaren van CDF worden opgehaald.

Tijdreeksgegevenspunten ophalen met de PostCDF-functie

Met de onderstaande Power Query-functie worden geaggregeerde tijdreeksgegevenspunten voor een tijdreeks binnen een tijdsbereik opgehaald en verwerkt. Invoer in de lokale tijdzone wordt geconverteerd naar UTC voor de CDF API-aanvragen, meerdere aggregaties en aangepaste granulariteit worden ondersteund en de paginering van gegevens wordt verwerkt. De functie converteert vervolgens de geretourneerde UTC-tijdstempels terug naar de lokale tijdzone, vouwt de geneste API-reactie uit en geeft een correct opgemaakte tabel met correct getypte kolommen weer. Lokale tijdstempels en decimale totaalwaarden worden ook weergegeven.

In het voorbeeld worden de functies ConvertDateTimeZoneToMs en ConvertMsToDateTimeZone gebruikt om tijdstempels te converteren.

(
item as record,
start as datetimezone,
optional end as nullable datetimezone,
optional aggregates as nullable text,
optional granularity as nullable text,
optional targetUnit as nullable text,
optional targetUnitSystem as nullable text,
optional timeZone as nullable text
) =>
let
// Function to detect query type based on item record structure
DetectQueryType = (item as record) =>
let
Fields = Record.FieldNames(item),
HasId = List.Contains(Fields, "id"),
HasExternalId = List.Contains(Fields, "externalId"),
HasSpace = List.Contains(Fields, "space"),
FieldCount = List.Count(Fields),
QueryType =
if HasId and not HasExternalId and not HasSpace and FieldCount = 1 then
"id"
else if HasExternalId and not HasId and not HasSpace and FieldCount = 1 then
"externalId"
else if HasExternalId and HasSpace and not HasId and FieldCount = 2 then
"instanceId"
else
Error.Record(
"Invalid item content", "The item record does not match any supported query type", item
)
in
QueryType,
// Detect query type
queryType = DetectQueryType(item),
// Determine limit based on presence of aggregates
limit = if aggregates <> null then 10000 else 100000,
// Convert aggregates from comma-separated string to list format accepted by the API
AggregatesList = Text.Split(aggregates, ","),
AggregatesTrimmedList = List.Transform(AggregatesList, each Text.Trim(_)),
StartMs = Number.Round(ConvertDateTimeZoneToMs(start)),
EndMs = Number.Round(ConvertDateTimeZoneToMs(end)),
// Function to fetch a single page of data
FetchPage = (cursor as nullable text) =>
let
// Build body item
bodyItem =
if queryType = "id" then
[id = Record.Field(item, "id")]
& (if targetUnit <> null then [targetUnit = targetUnit] else [])
& (if targetUnitSystem <> null then [targetUnitSystem = targetUnitSystem] else [])
& (if cursor <> null then [cursor = cursor] else [])
else if queryType = "externalId" then
[externalId = Record.Field(item, "externalId")]
& (if targetUnit <> null then [targetUnit = targetUnit] else [])
& (if targetUnitSystem <> null then [targetUnitSystem = targetUnitSystem] else [])
& (if cursor <> null then [cursor = cursor] else [])
else if queryType = "instanceId" then
[ instanceId = [ space = Record.Field(item, "space"), externalId = Record.Field(item, "externalId") ] ]
& (if targetUnit <> null then [targetUnit = targetUnit] else [])
& (if targetUnitSystem <> null then [targetUnitSystem = targetUnitSystem] else [])
& (if cursor <> null then [cursor = cursor] else [])
else
error "Invalid query type",
// Build request body
body = [
items = {bodyItem},
limit = limit,
ignoreUnknownIds = true,
start = Text.From(StartMs)
]
& (if end <> null then [end = Text.From(EndMs)] else [])
& (if aggregates <> null then [aggregates = AggregatesTrimmedList] else [])
& (if granularity <> null then [granularity = granularity] else [])
& (if timeZone <> null then [timeZone = timeZone] else []),
Response = PostCDF("/timeseries/data/list", Text.FromBinary(Json.FromValue(body))),
// Try to fetch the cursor from the first item in the response
FirstItem =
if Type.Is(Value.Type(Response), type table) and Table.RowCount(Response) > 0 then
Table.First(Response)
else
null,
NextCursor = if FirstItem <> null then Record.FieldOrDefault(FirstItem, "nextCursor", null) else null,
// Handles empty response and extracts data points when present
FinalItemsList =
if Table.HasColumns(Response, "datapoints") then
let
// Clean up the response table
ColumnsToRemove = {"nextCursor", "isStep", "unit"},
ColumnsPresent = List.Intersect({Table.ColumnNames(Response), ColumnsToRemove}),
CleanedTable = Table.RemoveColumns(Response, ColumnsPresent),
// Expand the "datapoints" column
ExpandedDatapointsList = Table.ExpandListColumn(CleanedTable, "datapoints"),
// Handles the case where the list of "datapoints" is empty
FinalDataPointsList =
if List.NonNullCount(ExpandedDatapointsList[datapoints]) > 0 then
let
// Extract a sample record to determine available fields dynamically
SampleRecord = ExpandedDatapointsList[datapoints]{0},
AvailableFields = Record.FieldNames(SampleRecord),
// Expand the "datapoints" records using the available fields
ExpandedDatapointsRecords = Table.ExpandRecordColumn(
ExpandedDatapointsList, "datapoints", AvailableFields, AvailableFields
),
DataPointsList = Table.ToRecords(ExpandedDatapointsRecords)
in
DataPointsList
else
{}
in
FinalDataPointsList
else
Table.ToRecords(Response)
in
{FinalItemsList, NextCursor},
// Recursive function to accumulate all pages of data
AccumulateData = (cursor as nullable text, accumulatedItems as list) =>
let
CurrentPage = FetchPage(cursor),
NewItems = CurrentPage{0},
NextCursor = CurrentPage{1},
UpdatedAccumulatedItems = accumulatedItems & NewItems,
Result =
if NextCursor <> null then
@AccumulateData(NextCursor, UpdatedAccumulatedItems)
else
UpdatedAccumulatedItems
in
Result,
// Fetch all data
AllItems = AccumulateData(null, {}),
// Convert the accumulated items to a table
ConvertToTable =
if List.IsEmpty(AllItems) then
Table.FromList({}, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
else
Table.FromList(AllItems, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
// Expand the table column and convert timestamps
ExpandedTable =
if not Table.IsEmpty(ConvertToTable) and Table.HasColumns(ConvertToTable, "Column1") then
let
TmpTable = Table.ExpandRecordColumn(
ConvertToTable, "Column1", Record.FieldNames(ConvertToTable{0}[Column1])
),
// timestamp should be always present when there are datapoints
FixType = Table.TransformColumnTypes(TmpTable, {{"timestamp", Int64.Type}}),
ParseTimestamp = Table.TransformColumns(FixType, {"timestamp", each ConvertMsToDateTimeZone(_)}),
ParsedWithType = Table.TransformColumnTypes(ParseTimestamp, {{"timestamp", type datetimezone}}),
// check if the timeseries is of type string
FirstEntry = ParsedWithType{0},
IsString = FirstEntry[isString],
CleanedTable = Table.RemoveColumns(ParsedWithType, {"isString"}),
// Convert aggregate/value columns to decimal number
ValuesAsDecimal =
if aggregates <> null then
Table.TransformColumnTypes(
CleanedTable, List.Transform(AggregatesTrimmedList, each {_, type number})
)
else if IsString then
CleanedTable
else
Table.TransformColumnTypes(
CleanedTable, List.Transform({"value"}, each {_, type number})
),
// Check if "id" column is present and convert to integer
IdAsInteger =
if Table.HasColumns(ValuesAsDecimal, "id") then
Table.TransformColumnTypes(ValuesAsDecimal, {{"id", Int64.Type}})
else
ValuesAsDecimal
in
IdAsInteger
else
ConvertToTable
in
ExpandedTable

De functie is complexer dan de vorige voorbeelden en kan veel verschillende scenario's verwerken, met paginering, conversie van gegevenstypen en het uitvouwen van geneste gegevens. De functie gebruiken:

let
Source = RetrieveDataPoints(
[ externalId = "EVE-TI-FORNEBU-01-3" ],
#datetimezone(2024, 10, 1, 0, 0, 0, 2, 0),
#datetimezone(2024, 10, 13, 10, 0, 0, 2, 0),
"average,max,min",
"1d",
null,
"SI",
"Europe/Oslo"
)
in
Source

Op basis van deze functie kunt u een andere functie maken om te itereren in een lijst met externe tijdreeks-ID's en de resultaten te combineren in een grote tabel. De lijst kan een kolom in een andere tabel zijn, waarin u bijvoorbeeld tijdreeksen filtert. U kunt de functie aanpassen om te itereren in een lijst met interne ID's of exemplaar-ID's.

(
externalIds as list,
start as datetimezone,
end as datetimezone,
aggregates as text,
granularity as text,
optional targetUnitSystem as nullable text,
optional timeZone as nullable text
) =>
let
// Iterate over each externalId and get corresponding table
TablesList = List.Transform(
externalIds,
each RetrieveDataPoints(
[ externalId = _ ],
start,
end,
aggregates,
granularity,
null,
targetUnitSystem,
timeZone
)
),
// Combine all tables into one
CombinedTable = Table.Combine(TablesList)
in
CombinedTable

De functie gebruiken:

let
Source = RetrieveDataPointsMultipleTs(
{"EVE-TI-FORNEBU-01-2", "EVE-TI-FORNEBU-01-3"},
#datetimezone(2024, 10, 1, 0, 0, 0, 2, 0),
#datetimezone(2024, 10, 13, 10, 0, 0, 2, 0),
"average,max,min",
"1d",
"SI",
"Europe/Oslo"
)
in
Source
Meer informatie