OQL examples
Team members
-
Purpose: retrieve all the members of a given Team (where the Team is specified by its name).
-
Compatibility: iTop 2.0
SELECT Person AS p JOIN lnkPersonToTeam AS l1 ON l1.person_id=p.id JOIN Team AS t ON l1.team_id=t.id WHERE t.name = 'My team'
Find objects with an empty external key
-
An ExternalKey is never NULL, it is set to 0 when
undefined
, -
An ExternalField can be NULL.
Those 2 queries will return the same results:
SELECT PhysicalDevice WHERE location_id=0 SELECT PhysicalDevice WHERE ISNULL(location_name)
Current week
-
Purpose: Get tickets created within the current week (monday to the current day)
-
Compatibility: iTop 2.0
SELECT UserRequest WHERE start_date > DATE(DATE_SUB(NOW(), INTERVAL IF(DATE_FORMAT(NOW(),'%w')=0,6,DATE_FORMAT(NOW(),'%w')-1)DAY))
Previous week
-
Purpose: Get tickets from the previous week (monday to sunday)
-
Compatibility: iTop 2.0
SELECT Ticket WHERE start_date < DATE(DATE_SUB(NOW(), INTERVAL IF(DATE_FORMAT(NOW(),'%w')=0,6,DATE_FORMAT(NOW(),'%w')-1)DAY)) AND start_date > DATE(DATE_SUB(NOW(), INTERVAL IF(DATE_FORMAT(NOW(),'%w')=0,6,DATE_FORMAT(NOW(),'%w')-1)+7 DAY))
Previous month
-
Purpose: Get tickets from the previous month
-
Compatibility: iTop 2.0
SELECT Ticket WHERE start_date < DATE_FORMAT(NOW(),'%Y-%m-01 00:00:00') AND start_date > DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 MONTH),'%Y-%m-01 00:00:00')
Organization hierarchies and locations
-
Purpose: Find out locations within a hierarchy of organizations
-
Compatibility: iTop 2.0
SELECT Location AS s JOIN Organization AS root ON s.org_id=root.id JOIN Organization AS child ON child.parent_id BELOW root.id WHERE child.name = 'TheWorldCompany'
Note that this previously supported syntax is no more compatible, due to query optimization algorithm:
SELECT s FROM Organization AS child
JOIN Organization AS root ON child.parent_id BELOW root.id
JOIN Location AS s ON s.org_id=root.id
WHERE child.name = 'TheWorldCompany'
It fails with “Allowed organizations” and in “Enhanced portal”:
FAQs with domains (TagSet)
Assuming you have 2 domains with code agent
and
enduser
, and some FAQs with those tags:
You can search for FAQs having either one
or the other of those 2 tags:
SELECT FAQ WHERE domains MATCHES 'agent enduser'
You can search for FAQs having both tags:
SELECT FAQ WHERE domains MATCHES 'agent' AND domains MATCHES 'enduser'
Opened tickets
-
Purpose: Find out all opened Tickets. This is not feasible in one simple SELECT because the attribute “status” is not defined in the class Ticket, but in each derived class. Solution: use an UNION query.
-
Compatibility: iTop 2.2.0
SELECT UserRequest WHERE status NOT IN ('rejected', 'resolved', 'closed') UNION SELECT Change WHERE status NOT IN ('rejected', 'closed')
Thus, in the above query, the results will be displayed as objects of the class Ticket.
Contacts of an organization
-
Purpose: Find out the contacts of the provider (hierarchy) and the persons of the customer (top level only)
-
Compatibility: iTop 2.2.0
SELECT Contact AS c JOIN Organization AS child ON c.org_id = child.id JOIN Organization AS root ON child.parent_id BELOW root.id WHERE root.friendlyname = 'TheProvider' UNION SELECT Person AS p JOIN Organization AS o ON p.org_id = o.id WHERE o.friendlyname = 'TheCustomer' AND p.phone != ''
Contacts of a ticket
-
Purpose: Notify the persons linked to a Ticket, who are not the caller and are willing to be notified.
SELECT Person AS p JOIN lnkContactToTicket AS l ON l.contact_id=p.id WHERE l.ticket_id = :this->id AND p.id != :this->caller_id AND notify='yes'
It must be done explicitly in the OQL
Searching on History
Changes made by someone
Let's assume you want to retrieve all field modifications made on a given day, on objects of class Person, by a user “Casimir” using interactive CSV import mechanism. Here is the OQL query you can run to do so.
SELECT CMDBChangeOpSetAttribute AS sa JOIN CMDBChange AS c ON sa.change = c.id WHERE c.date > '2019-07-16 00:00:00' AND c.date < '2019-07-17 00:00:00' AND c.origin = 'csv-interactive' AND c.userinfo LIKE '%Casimir%' AND sa.objclass = 'Person'
In the resulting list, check the key
which is the
id of the modified Person.
To get the previous value, you need to know the field type. It's
mapped to one of the children class of
CMDBChangeOpSetAttribute
:
-
There is in general one specific subclass per Attribute Type.
-
Except
CMDBChangeOpSetAttributeScalar
which handles multiple attribute types, those that can be treated as a simple mono-line string. It includes Integer, Decimal, String, Date,…
Persons reactivated
Here is how to get all Persons which have been reactivated while they were 'inactive', anytime since you've deployed iTop:
SELECT CMDBChangeOpSetAttributeScalar AS sa JOIN CMDBChange AS c ON sa.change = c.id WHERE sa.objclass ='Person' AND sa.attcode = 'status' AND sa.oldvalue = 'inactive' AND sa.newvalue = 'active'
Displaying multiple objects fields
When your search result should contains fields from multiple class, use the output specification.
For example the below query will only return Contact class fields :
SELECT Contact AS c JOIN lnkContactToFunctionalCI AS l ON l.contact_id = c.id JOIN FunctionalCI AS f ON l.functionalci_id = f.id
The little change below will allow to output fields from both Contact and FunctionalCI :
SELECT c, f FROM Contact AS c JOIN lnkContactToFunctionalCI AS l ON l.contact_id = c.id JOIN FunctionalCI AS f ON l.functionalci_id = f.id
Identifying duplicates
Lets assume you want to identify duplicates on employee number within the same organization:
SELECT Person AS p JOIN Organization AS o ON p.org_id = o.id JOIN Person AS p2 ON p2.org_id = o.id WHERE p2.employee_number = p.employee_number AND p.id != p2.id
OQL: new in 2.7
Empty Teams
Search for Teams which have no members
SELECT Team WHERE id NOT IN ( SELECT Team AS t JOIN lnkPersonToTeam AS l ON l.team_id=t.id )
UserRequest without CIs
Search for UserRequest which do not have any 'production' PhysicalDevice linked to it
SELECT UserRequest WHERE id NOT IN ( SELECT UserRequest AS u JOIN lnkFunctionalCIToTicket AS l ON l.ticket_id=u.id JOIN PhysicalDevice AS f ON l.functionalci_id=f.id WHERE f.status='production' )
Search for UserRequest which do not have 'production' PhysicalDevice neither 'active' ApplicationSolution linked to it
SELECT UserRequest WHERE id NOT IN ( SELECT UserRequest AS u JOIN lnkFunctionalCIToTicket AS l ON l.ticket_id=u.id JOIN PhysicalDevice AS f ON l.functionalci_id=f.id WHERE f.status='production' UNION SELECT UserRequest AS u JOIN lnkFunctionalCIToTicket AS l ON l.ticket_id=u.id JOIN ApplicationSolution AS f ON l.functionalci_id=f.id WHERE f.status='active' )
Persons without Users
Search for active Persons with no enabled User associated
SELECT Person WHERE status='active' AND id NOT IN ( SELECT Person AS p JOIN User AS u ON u.contactid=p.id WHERE u.status='enabled' )
Badly configured Users
Search for active User not allowed on their own organization
SELECT User AS U JOIN Person AS P ON U.contactid=P.id WHERE U.status='enabled' AND U.id NOT IN ( SELECT User AS U JOIN Person AS P ON U.contactid=P.id JOIN URP_UserOrg AS L ON L.userid = U.id WHERE U.status='enabled' AND L.allowed_org_id = P.org_id UNION SELECT User AS U WHERE U.status='enabled' AND U.id NOT IN ( SELECT User AS U JOIN URP_UserOrg AS L ON L.userid = U.id WHERE U.status='enabled' ) )
This request search for active Users with a Person associated, and the Person belongs to an organization which is not in the Allowed Organizations of the User and that Allowed Organizations list is not empty (remember an empty list means all organizations are allowed).