THWACK logo
THWACK
  • Sign In
  • Search
  • Community
    Community

    Find all you need to begin your THWACK journey, including documentation, missions, blogs, community groups, events, and media.

    Command Central
    • Getting Started
    MVP Program
    • MVP Program
    Monthly Mission
    • Hidden Gems
    Blogs
    • Community Announcements
    • Product Blog
    Groups
    • DevOps Discourse
    • Data Driven
    • See All Groups
    Events
    • SolarWinds User Group
    • THWACKcamp
      • ↪ 2024: On Demand
    • Bracket Battle
    Media Vault
    • Movies & Mainframes
    • TechPod
    • THWACK Tech Tips
    • THWACK Livecast
    • SolarWinds Lab Archive
    • THWACKcamp Archive
    • See All Media
  • Products
    Products

    Find the best place to learn and ask questions about your SolarWinds products.

    Observability
    • Observability Solutions
    • SolarWinds Observability SaaS
    • SolarWinds Observability Self-Hosted
    • SolarWinds Platform
    Network Management
    • Network Performance Monitoring
    • NetFlow Traffic Analyzer
    • Network Configuration Manager
    • IP Address Manager
    • User Device Tracker
    • VoIP & Network Quality Manager
    • Log Analyzer
    • Engineer's Toolset
    • Network Topology Mapper
    • Kiwi CatTools
    • Kiwi Syslog Server
    • ipMonitor
    Application Management
    • AppOptics
    • Loggly
    • Papertrail
    • Pingdom
    • DevOps
    IT Security
    • Access Rights Manager
    • Identity Monitor
    • Security Event Manager
    • Patch Manager
    • Serv-U FTP & MFT
    IT Service Management
    • SolarWinds Service Desk
    • Web Help Desk
    • DameWare Remote Support
    • DameWare Remote Everywhere
    • DameWare Mini Remote Control
    System Management
    • Server & Application Monitor
    • Virtualization Manager
    • Storage Resource Monitor
    • Server Configuration Monitor
    • SolarWinds Backup
    • Web Performance Monitor
    Database Management
    • Database Performance Analyzer
    • SQL Sentry
    • Database Performance Monitor
    • Database Mapper
    • Task Factory
  • Content Exchange
    Content Exchange

    Find downloadable files and templates other users have built and found useful to share with others.

    SolarWinds Platform
    • Alerts
    • Custom HTML
    • Custom Queries
    • Modern Dashboards
    • Reports
    • Scripts
    Server & Application Monitor
    • API Pollers
    • Application Monitor Templates
    Database Performance Analyzer
    • Custom Alerts
    • Custom Metrics
    • Custom Queries
    Server Configuration Monitor
    • Policies
    • Profiles
    Network Performance Monitor
    • Device Pollers
    • Universal Device Pollers
    Network Configuration Manager
    • Config Change Scripts
    • Device Templates
    • Firmware Upgrade Templates
    • Policy Documents
    SQL Sentry
    • Advisory Conditions
    Web Help Desk
    • Style Sheets
  • Resources
    SolarWinds Customer Portal Customer Portal

    Create individual user accounts for your team, manage your licenses, download your SolarWinds software, create and track support tickets, and more.

    SolarWinds Academy Academy

    A one-stop-shop for world-class training for SolarWinds products through on-demand videos, and instructor-led classes. All SolarWinds Academy content is included with every software purchase.

    SolarWinds Customer Success Support

    Get help when you need it from a world-class support team, available to assist with technical product issues 24 hours a day, seven days a week, 365 days a year.

    SolarWinds Partner Portal Partner Portal

    Accelerate SolarWinds Partners’ ability to drive digital and IT transformation for customers with powerful tools, resources, and increased profit potential.

  • Free Tools & Trials
  • Store
The SolarWinds Platform
  • Products
The SolarWinds Platform
SolarWinds Platform API Navigation Properties
  • Newsroom
  • Forums
  • SolarWinds Platform API
  • Content Exchange
  • What We're Working On
  • Feature Requests
  • More
  • Cancel
  • New
  • -SolarWinds Platform API
    • About the SolarWinds Information Service (SWIS)
    • +Setting up a Python Development Environment
    • +Using PowerShell 7+ and Visual Studio Code
    • -SolarWinds Query Language (SWQL) Basics
      • +What is the SolarWinds Query Language?
      • SWQL Studio
      • Query Basics in SWQL Studio
      • Query Construction in SWQL Studio
      • Navigation Properties
      • Architect
    • +Data Presentation Examples
    • Additional Resources
    • Glossary

Navigation Properties

Because many people (myself included) started to learn the syntax of SWQL Queries based on (sometimes limited) knowledge of SQL queries, I wanted to share with everyone the best way to avoid JOIN clauses.

The examples herein will be show in SWQL Studio, so if you don't already have SWQL Studio installed, you should do so if you'd like to follow along.  Some of my sample data from below is completely made up, but you should see something similar in your environment.

If you are not familiar with the traditional T-SQL JOIN clauses, there's multiple excellent articles on Microsoft's and other sites (Official Doc: Joins (SQL Server) - SQL Server | Microsoft Docs).  My non-technical description of a JOIN is "a way to connect one table to another through a shared element."

I will use terms like field and record and for the sake of clarity this is what I mean:

Fields vs. Records

Sample Tables

NodeID Caption ObjectSubType DetailsURL
27 EASTEXMBX01v WMI /Orion/NetPerfMon/NodeDetails.aspx?NetObject=N:27
42 EAST-2945-WAN SNMP /Orion/NetPerfMon/NodeDetails.aspx?NetObject=N:42
914 WESTAZLINUX01v Agent /Orion/NetPerfMon/NodeDetails.aspx?NetObject=N:914

Table 1: Selection of elements from Orion.Nodes

SELECT NodeID, Caption, ObjectSubType, DetailsURL FROM Orion.Nodes

NodeID InterfaceID InterfaceName InterfaceAlias TypeDescription PercentUtil DetailsURL
27 97 Ethernet MAPI Ethernet 67.6 /Orion/Interfaces/InterfaceDetails.aspx?NetObject=I:97
27 98 Ethernet Replication Ethernet 82.7 /Orion/Interfaces/InterfaceDetails.aspx?NetObject=I:98
42 168 Lo0 Loopback 0.5 /Orion/Interfaces/InterfaceDetails.aspx?NetObject=I:168
42 169 GigabitEthernet0/0 Inside Ethernet 42.4 /Orion/Interfaces/InterfaceDetails.aspx?NetObject=I:169
42 170 GigabitEthernet0/1 Outside Ethernet 69.9 /Orion/Interfaces/InterfaceDetails.aspx?NetObject=I:170
914 9147 eth0 Ethernet 18.7 /Orion/Interfaces/InterfaceDetails.aspx?NetObject=I:9147

Table 2: Selection of elements from Orion.NPM.Interfaces

SELECT NodeID, InterfaceID, InterfaceName, InterfaceAlas, TypeDescription, PercentUtil, DetailsURL FROM Orion.NPM.Interfaces

Moving the Queries to a more "readable" format

Converting the queries to something more readable helps me organize the fields and make the logical connection.  These are the same queries from above, but refactored.  For SQL and SWQL anything on a line after a double-dash is considered a comment.

-- Data from Orion.Nodes
-- Read the Comments in number order to understand the logic
--
SELECT [Nodes].NodeID          -- 2. Prepend the fields with the table alias.
     , [Nodes].Caption         -- 3. The same applies for all fields from this table.
     , [Nodes].ObjectSubType   -- 4. and again
     , [Nodes].DetailsURL      -- 5. you get the picture
FROM Orion.Nodes AS [Nodes]    -- 1. Choose an easy to comprehend alias for the table

-- Data from Orion.NPM.Interfaces
-- Read the comments in number order to understand the logic
--
SELECT [Interfaces].NodeID                -- 2. Prepend the fields with the table alias.
     , [Interfaces].InterfaceID           -- 3. The same applies for all fields from this table.
     , [Interfaces].InterfaceName         -- 4. and again
     , [Interfaces].InterfaceAlias        -- 5. lather
     , [Interfaces].TypeDescription       -- 6. rinse
     , [Interfaces].PercentUtil           -- 7. repeat
     , [Interfaces].DetailsURL            -- 8. you see where I'm going, right?
FROM Orion.NPM.Interfaces AS [Interfaces] -- 1. Choose an easy to comprehend alias for the table

Joining the Tables (Traditional)

Using the JOIN clause (which is 100% supported in SWQL), you can join these two tables on a common element (NodeID).

--
-- Read the Comments in number order to understand the logic
--
SELECT [Nodes].NodeID                           -- 3. Field from the original table
     , [Nodes].Caption                          -- 4. Another from the Nodes table
     , [Nodes].ObjectSubType                    -- 5. Yep, this one is also from Nodes
     , [Nodes].DetailsURL                       -- 6. Nodes as well
     , [Interfaces].NodeID                      -- 7. This is from our joined Interfaces table
     , [Interfaces].InterfaceID                 -- 8. Also from the Interfaces table
     , [Interfaces].InterfaceName               -- 9. More from Interfaces
     , [Interfaces].InterfaceAlias              -- 10. You can see why the alias...
     , [Interfaces].TypeDescription             -- 11. ... makes it easy to understand ...
     , [Interfaces].PercentUtil                 -- 12. ... the source of the field in question.
     , [Interfaces].DetailsURL                  -- 13. I ran out of clever things to say
FROM Orion.Nodes AS [Nodes]                     -- 1. Our original table
INNER JOIN Orion.NPM.Interfaces AS [Interfaces] -- 2. Our second table
  ON [Nodes].NodeID = [Interfaces].NodeID

Now each record will show all of the requested fields from both tables.

Notice the second reference to NodeID (the fifth field in the above record)?  Since our JOIN guarantees that the field NodeID and NodeID1 are equal, we could remove one of them.

But there's also a second reference to DetailsURL.  In this case, the Node's details link and that for the interface are different.  We should probably come up with a more logical way to present this.

--
-- Read the Comments in number order to understand the logic
--
SELECT [Nodes].NodeID
     , [Nodes].Caption
     , [Nodes].ObjectSubType
     , [Nodes].DetailsURL AS [NodeDetailsUrl]           -- 2. Provide a field alias to the field name
     -- , [Interfaces].NodeID                           -- 1. (commented out the duplicate NodeID because the JOIN already guarantees these match
     , [Interfaces].InterfaceID
     , [Interfaces].InterfaceName
     , [Interfaces].InterfaceAlias
     , [Interfaces].TypeDescription
     , [Interfaces].PercentUtil
     , [Interfaces].DetailsURL AS [InterfaceDetailsUrl] -- 3. Provide a different field alias for this other one
FROM Orion.Nodes AS [Nodes]
INNER JOIN Orion.NPM.Interfaces AS [Interfaces]
     ON [Nodes].NodeID = [Interfaces].NodeID

Neat, right?  Now we can join two tables on a matching record and show fields from either table in a single record.

But what about 3 tables?  What about 4, 5, 6, 11?  It can be done with multiple JOIN operations between the tables, but you can see that things could get complex, right?

The Easier Way - Navigation Properties

The incredibly smart people at SolarWinds Orion Architecture decided that although JOINs do work, you need to have an intrinsic knowledge of the connected tables before you can be successful.

Each table (technically called an "entity") in the SolarWinds Orion API can have up to 5 different types of elements.

Available Resources in Orion Entities

  • Primary Key - this is the unique identifier(s) for this table
  • Fields - the things you can query
  • Inherited Fields - additional things you can query (but aren't the default)
  • Navigation Properties - connected entities <-- this is the focus of the discussion today
  • Verbs - actions you can take on the elements in the entity (records in the table)

What is a Navigation Property?

The Official Definition: a property on one entity type whose value is a set of zero or more other entities of a particular type

The "KMSigma" Definition: a way to skip doing JOINs.

I'm going to zoom in on one specific navigation property under Orion.Nodes.

Looks familiar right?  Remember that this is a child of the Orion.Nodes entity, not of Orion.NPM.Interfaces.

Here's what it's saying in plain language: You can query for fields from Orion.Nodes and then connect to Orion.NPM.Interfaces via the Interfaces navigation property.

Taking our above examples, we can connect Orion.Nodes with Orion.NPM.Interfaces via the navigation property.  Starting simple, let's just include the interfaceID.

--
-- Read the Comments in number order to understand the logic
--
SELECT [Nodes].NodeID
     , [Nodes].Caption
     , [Nodes].ObjectSubType
     , [Nodes].DetailsURL
     , [Nodes].Interfaces.InterfaceID
--        ^        ^           ^
--        |        |           |
--        +- 1. Starting with Orion.Nodes
--                 |           |
--                 +- 2. Connect to Orion.NPM.Interfaces via the Navigation Property
--                             |
--                             + 3. Pull this field from Orion.NPM.Interfaces
FROM Orion.Nodes AS [Nodes] -- 1. Having a table alias here is practically mandatory to keep things stright in your head - get in the habit.

Huzzah!  We've connected Orion.Nodes to Orion.NPM.Interfaces without using a JOIN clause.

If we wanted to add the other fields, it's the same as following the formula.  Thankfully, SWQL Studio has autocomplete, so it's easy.

SWQL Studio Support Navigation Property Autocompletion

And the results are pretty much what you would expect.

But all of this was done WITH NO JOIN CLAUSES.

You can even continue further.  If you look at the Orion.NPM.Interfaces entity, it also has navigation properties.

--
-- Read the Comments in number order to understand the logic
--
SELECT [Nodes].NodeID
     , [Nodes].Caption
     , [Nodes].ObjectSubType
     , [Nodes].DetailsURL
     , [Nodes].Interfaces.InterfaceID
     , [Nodes].Interfaces.InterfaceName
     , [Nodes].Interfaces.InterfaceAlias
     , [Nodes].Interfaces.TypeDescription
     , [Nodes].Interfaces.PercentUtil
     , [Nodes].Interfaces.DetailsUrl
--     * Show two table hops *
     , [Nodes].Interfaces.ForecastCapacity.DaysToCapacityAvg
--        ^        ^           ^                 ^
--        |        |           |                 |
--        +- 1. Starting with Orion.Nodes        |
--                 |           |                 |
--                 +- 2. Connect to Orion.NPM.Interfaces via the Navigation Property
--                             |                 |
--                             + 3. Connect to Orion.NPM.InterfacesForecastCapacity via the Navigation Property on Orion.NPM.Interfaces
--                                               |
--                                               +- 4. Pull DaysToCapacity field from Orion.NPM.InterfacesForecastCapacity
FROM Orion.Nodes AS [Nodes] -- 1. Having a table alias here is practically mandatory to keep things stright in your head - get in the habit.

Summary

Navigation Properties are one of the most underappreciated features of the SolarWinds Orion API.  The API already knows how the various data types are connected, so use what's already been built for you.  Go forth and explore!

  • Navigation Properties
  • SolarWinds Query Language (SWQL)
  • Share
  • History
  • More
  • Cancel
Related
Recommended

SolarWinds solutions are rooted in our deep connection to our user base in the THWACK® online community. More than 200,000 members are here to solve problems, share technology and best practices, and directly contribute to our product development process.

SolarWinds Customer Success Center Certification SolarWinds Lab Link Customer Portal
About THWACK SolarWinds Blog Federal & Government Edit Settings Free Tools & Trials
Legal Documents Terms of Use Privacy California Privacy Rights Security Information
©2021 SolarWinds Worldwide, LLC. All Rights Reserved.