Maximo

Maximo

Come for answers, stay for best practices. All we're missing is you.

 View Only
  • 1.  Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Tue December 27, 2022 09:36 AM
    Looking for recommended sites for where clause testing and labs. We use where clauses a lot in our references to our internal clients and I want good resources to test SQL statements and where clauses for the Maximo applications. 

    Thank you for any support you can provide! Good with the application, not as advanced with languages, yet.

    ------------------------------
    Chelsea McCabe
    ------------------------------

    #AssetandFacilitiesManagement
    #Maximo


  • 2.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Wed December 28, 2022 05:56 PM
    HI Chelsea,

    I am not aware of a specific site "to test SQL statements and where clauses for the Maximo applications".  I learned by tearing apart the reports (first SQR Brio, then Actuate, and finally BIRT).  Also, using the Advanced Search dialog box then clicking on the "where" clause button revealed the generated where clause.  From there go to your SQL tool of choice to start interrogating the database.  (This is where the repots came in real handy.  They taught me the relationships.  

    When the relationships tab was introduced to the product I also learned that was a good source to understand the manner in which the table joins "should" be constructed.  Depending on the desired result set you can modify your joins according tot he various definitions shared there. (Note: Once upon a time there was an Entity Relationship Diagram or ERD that was published.  This was back in the old 5.2 days.  It has not been republished since). The Maximo database is a non-normalised DB and as such it is governed by the MBOs for referential integrity. This is again why I look to the reprots for valid SQL in both data extraction and insertion (there are a few reports with insert statements). 

    So, with all that said, the practice I encourage you to pursue is to use this forum, explore the repots for good SQL code, keep a database (or spreadsheet) of useful SQL, work with a good SQL tool of choice pointed at your Maxdemo or DEV database, and use Maximo itself to validate the SQL.  I hope this helps.

    ------------------------------
    Bradley K. Downing , MBA
    Senior Brand Technical Specialist
    IBM
    Bakersfield CA
    ------------------------------



  • 3.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Thu December 29, 2022 04:11 AM
    Hi Chelsea,

    I doubt there is a public Maximo database for people to view SQL, but all good setups should have a copy system of a production Maximo database for this purpose, it is needed for any SQL tuning.

    Bradley rightly says that there are ways to look at the Where clause. Although I rarely talk about technical issues in MaximoSecrets.com, every day I am in Database Configuration looking at Attributes and Relationships and over the years you build up a mental picture of the ERD of Maximo. When lots of new functionality was being released regularly, Database Configuration was my starting point, not the new applications themselves, they would help to confirm the picture I was creating by looking at the objects and relationships. The Where clause when you make a query in an application is also useful.

    However, this is only half the story. The application where clause that you see when a query is made is only part of the query - the other part is added mainly through your security settings. Therefore, from a SQL tuning point of view there is no substitution for logging in as a specific user (not Maxadmin) and trapping a SQL log as the query is executed to the database. When you see what is happening in a SQL log, you will get a few surprises, but you can look out for those longer running queries and then seek to do something about it.

    My biggest tip - never, never, never join two site level objects by ORGID = :orgid and SITEID = :siteid you are asking the database to filter the results of the join, it is completely unnecessary as SITEID is itself unique across the Maximo database.

    Good luck - Andrew

    ------------------------------
    Andrew Jeffery
    Maximo SME
    ZNAPZ b.v
    Barnstaple
    0777 1847873
    ------------------------------



  • 4.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Thu December 29, 2022 08:58 AM
    Andrew,

    Thanks for pointing out the Database Configuration application.  I make oblique reference to it with my "relationships tab" comment, but failed to state explicitly that it is in the DBConfig application. (Doh! Hahahahah!). 

    Also I agree with you that adding the "ORGID = :orgid" to the SQL where clause is redeundant and unnecessary.  Not sure about the "never, Never" part though.  Have you found that it adds cost to the query?  I have not found that it negatively impacts performance and I do see it in several canned reports.  Nevertheless, I agree it is unnecessary and does not enhance performance.

    The logging idea is also a good idea.  Access to logs in Websphere is the only limitation.  Depending on your role you may or may not have direct access to the logs.  Also with the MAS 8 architecture the process to access logs is a bit different.  But that is another topic (for more info you can look here.)

    ------------------------------
    Bradley K. Downing , MBA
    Senior Brand Technical Specialist
    IBM
    Bakersfield CA
    ------------------------------



  • 5.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Thu December 29, 2022 10:57 AM

    Hi Bradley,

    It depends on how selective the join is between the multiple tables where the ORGID = :orgid is used. If the join only retrieves a few records, you won't notice the difference. However, on a database with 20 million work orders, and 000's of assets and locations, yes it does make a difference. 

    Over my 35+ years working with databases I have been lucky enough to have a few periods of time when I have spent several weeks SQL tuning. When I started out in Oracle v3, you had to be precise, even down to the order of tables in a join, if a query didn't retrieve records fast enough, you had to stop the process.

    But it was the time spent working on a large database where I learnt the most. When some simple queries on a Start Center result set do not retrieve the expected few records in more than 20 seconds, you know you have issues, if they take longer than a minute, they are serious. The simple queries when examined under a Maximo SQL Log, became far from simple when the multiple Security Groups with Site or Data Restrictions were applied. The result of one seriously poor performing system was mainly down to a security group that was performing a subquery. To overcome this various DBAs had added numerous indexes over the years, so much so that the work order table had many indexes that included the STATUS field, no wonder it was slow when generating a PM work order with tasks, most of those indexes were greater than 1GB in disk file size.

    Understanding the structure of the Maximo database, the key fields which indexes will naturally use, and the effect of search types on attributes should all be standard learning for most Maximo consultants whether functional or technical. So good on Chelsea for wanting to get to grips with this.

    Regards - Andrew

     



    ------------------------------
    Andrew Jeffery
    Maximo SME
    ZNAPZ b.v
    Barnstaple
    0777 1847873
    ------------------------------



  • 6.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Thu December 29, 2022 10:49 AM
    Hi Chelsea,

    I have a copy of Tableau which allows me to see the tables in the DB and write queries directly against them, that has been most useful.  Other reporting engines may allow the same.

    You could try the Max preview site as a place to practice:
    https://www.ibm.com/support/pages/maximo-asset-management-761-preview-site

    I learned to write where clauses initially through trial and error and using the Alt-I a lot so I could see what tables different fields were in.  There used to be an ERD but I cannot find it on the web anymore (IBM docs now have a lot of broken links).  This page talks about building your own:
    https://www.ibm.com/support/pages/how-generate-entity-relationship-erd-document-maximo

    These site have some useful notes:
    https://bportaluri.com/2022/12/useful-queries-for-users-monitoring.html
    http://mygeekdaddy.net/2014/01/09/building-your-own-special-maximo-query/

    Brian


    ------------------------------
    Brian Hobbs
    ------------------------------



  • 7.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Fri December 30, 2022 06:21 AM
    Hi all,

    My journey with SQL started with attending a SQL course run by Oracle and then writing many reports using the Oracle PL/SQL book as my bible combined with a printout of the MAXATTRIBUTES table which you may hear referred to as the data dictionary.  Be careful as there are two data dictionaries, I am referring to Maximo's, not the database.  Your other friends will be ALT+F1 or ALT+I to get the field help and information, then the WhereClauses build up through searching.

    Again, be careful as the SQL that is generated from the Query By Example (QBE) search is not always optimised.  You may have to use an external SQL query tool like DBeaver, SQL Analyzer, or the like to run an Explain Plan which tells you how efficient your SQL is.

    I do agree that you should not write your code with ORGID=:ORGID and SITEID=:SITEID.  Why?  Normally when you are involving the SITEID, the indexes are optimised to use that and when you use ORGID it will force a full table scan, which can be bad.

    I've run a number of beginner SQL courses that PSDI designed that aligned with Maximo, but the whole thing is that you don't need Maximo to learn SQL.  It just really helps as you are designing the queries for reporting anyway.

    As always, I'm happy to help.

    ------------------------------
    ===============================
    Craig Kokay,
    Lead Senior Maximo/IoT Consultant
    ISW
    Sydney, NSW, Australia
    Ph: 0411-682-040
    =================================
    #IBMChampion2022
    ------------------------------



  • 8.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Fri December 30, 2022 12:41 PM
      |   view attached
    The script below (and attached) will let you try out sql from a browser or using a tool like Postman (https://www.postman.com/).  You can deploy the script using the VisualCode extension here https://marketplace.visualstudio.com/items?itemName=sharptree.maximo-script-deploy , which is a great help when creating scripts and worth getting to know anyway.  Otherwise, you can create a script manually, just name is SQL and select Javascript as the script language.

    For the following examples I am going to assume your server is at https://maximo-server/maximo.  The results are returned in JSON and for formatting you may want to use Firefox as the browser since it has a nice JSON formatter built in and the results will look a lot nicer than in Chrome.

    To invoke the script put the following in your browser address bar, not that only the first 1000 records will be returned.

    https://maximo-server/maximo/oslc/script/sql/[OBJECT_NAME]?sql=[WHERE_CLAUSE]

    For example if I wanted to query for work order number 1001: 

    https://maximo-server/maximo/oslc/script/sql/workorder?sql=wonum='1001'

    You can also query for related records with the following:

    https://maximo-server/maximo/oslc/script/sql/[OBJECT_NAME]?sql=[WHERE_CLAUSE]&parentMbo=[PARENT_OBJECT_NAME]&parentId=[PARENT_UNIQUE_ID]

    For example if I wanted to get the asset information for work order 1022 in the Maximo demo database, the unique Id as found in the WORKORDERID attribute is 202 so the request would look like the following:

    https://maximo-server/maximo/oslc/script/sql/asset?sql=assetnum=:assetnum&parentMbo=workorder&parentId=202

    If you are need to use special characters like & or % if your query then make sure you encode them as described here:

    https://www.w3schools.com/tags/ref_urlencode.asp

    Here is the script.  Standard disclaimer, I am providing it as-is and for development and educational purposes only.  It should not be applied to production environments.

    MXServer = Java.type("psdi.server.MXServer");
    MXException = Java.type("psdi.util.MXException");
    
    main();
    
    function main() {
        var isHttpRequest = typeof request != 'undefined';
    
        // this is only supported when invoked from a web request.
        if (!isHttpRequest) {
            return;
        }
    
        var objectName = __getRequestObject();
    
        if (!objectName) {
            var httpRequest = request.getHttpServletRequest();
            var port = httpRequest.getServerPort();
            var url = (httpRequest.isSecure() ? "https" : "http") + "://" + httpRequest.getServerName() + ((port != 80 && port != 443) ? ":" + port : "")  + httpRequest.getServletContext().getContextPath() + "/oslc/script/sql/[OBJECT_NAME]";
            var error = { "status": "error", "reason": "The object name could not be determined.  Call this script with " + url + ". Where [OBJECT_NAME] is the name of the Maximo object." };
    
            responseBody = JSON.stringify(error);
            return;
        }
    
        var sql = request.getQueryParam("sql");
    
        if (!sql || sql.trim() == '') {
            var httpRequest = request.getHttpServletRequest();
            var port = httpRequest.getServerPort();
            var url = (httpRequest.isSecure() ? "https" : "http") + "://" + httpRequest.getServerName() + ((port != 80 && port != 443) ? ":" + port : "") + httpRequest.getServletContext().getContextPath() + "/oslc/script/sql/" + objectName + "?sql=[YOUR_SQL_HERE]";
            var error = { "status": "error", "reason": "The object name could not be determined.  Call this script with " + url + ". Where [YOUR_SQL_HERE] is the SQL you want to test." };
    
            responseBody = JSON.stringify(error);
            return;
        }
    
        var result = {};
        var records = [];
        var max = 1000;
        if (request.getQueryParam("maxCount")) {
            max = request.getQueryParam("maxCount");
        }
    
        var parentMbo;
        var parentId;
    
        if (request.getQueryParam("parentMbo")) {
            parentMbo = request.getQueryParam("parentMbo");
        }
    
        if (request.getQueryParam("parentId")) {
            parentId = request.getQueryParam("parentId");
        }
    
        var mboSet;
        var parentSet;
        try {
    
            if (parentMbo && parentId) {
                parentSet = MXServer.getMXServer().getMboSet(parentMbo, userInfo);
                var mbo = parentSet.getMboForUniqueId(parentId);
                if (mbo) {
                    mboSet = mbo.getMboSet("$" + objectName.toLowerCase(), objectName, sql);
                } else {
                    error = { "status": "error", "reason": "A record was not found for " + parentMbo + " with a unique Id " + parentId };
                    responseBody = JSON.stringify(error);
                    return;
                }
            } else {
                mboSet = MXServer.getMXServer().getMboSet(objectName, userInfo);
                mboSet.setWhere(sql);
            }
    
            var mbo = mboSet.getMbo(0);
            var i = 0;
    
            while (mbo && i++ < max) {
                records.push(___serializeMbo(mbo));
                mboSet.remove(0);
                mbo = mboSet.getMbo(0);
            }
            result.count = mboSet.count();
            result.records = records;
    
            responseBody = JSON.stringify(result);
            return;
    
        } catch (error) {
            if (error instanceof MXException) {
                var error = { "status": "error", "reason": error.getDisplayMessage() };
            } else {
                var error = { "status": "error", "reason": error.getMessage() };
            }
        } finally {
            ___close(mboSet);
            ___close(parentSet);
        }
    }
    
    function ___serializeMbo(mbo) {
        var mboSetInfo = mbo.getThisMboSet().getMboSetInfo();
        var attributes = mboSetInfo.getAttributes();
    
        var object = {};
        while (attributes.hasNext()) {
            var attribute = attributes.next();
            object[attribute.getAttributeName()] = mbo.getString(attribute.getAttributeName());
        }
    
        return object;
    }
    
    
    function __getRequestObject() {
    
        var httpRequest = request.getHttpServletRequest();
    
        var requestURI = httpRequest.getRequestURI();
        var contextPath = httpRequest.getContextPath();
        var resourceReq = requestURI;
    
        if (contextPath && contextPath !== '') {
            resourceReq = requestURI.substring(contextPath.length());
        }
    
        if (!resourceReq.startsWith("/")) {
            resourceReq = "/" + resourceReq;
        }
    
        var isOSLC = true;
    
        if (!resourceReq.toLowerCase().startsWith('/oslc/script/' + service.scriptName.toLowerCase())) {
            if (!resourceReq.toLowerCase().startsWith('/api/script/' + service.scriptName.toLowerCase())) {
                return null;
            } else {
                osOSLC = false;
            }
        }
    
        var baseReqPath = isOSLC ? '/oslc/script/' + service.scriptName : '/api/script/' + service.scriptName;
    
        var action = resourceReq.substring(baseReqPath.length);
    
        if (action.startsWith("/")) {
            action = action.substring(1);
        }
    
        if (!action || action.trim() === '') {
            return null;
        }
    
        return action.toLowerCase();
    }
    
    function ___close(mboSet) {
        if (mboSet) {
            try {
                mboSet.close();
                mboSet.cleanup();
            } catch (ignored) { }
        }
    }
    
    var scriptConfig = {
        "autoscript": "SQL",
        "description": "SQL Testing Script",
        "version": "1.0.0",
        "active": true,
        "logLevel": "INFO"
    };​


    ------------------------------
    Jason VenHuizen
    https://sharptree.io
    https://opqo.io
    ------------------------------

    Attachment(s)

    js
    sql.js   5 KB 1 version


  • 9.  RE: Is there a suggested site to build or learn about Maximo Where Clauses

    Posted Mon January 02, 2023 10:23 AM
    Hi Chelsea,

    Create your own ERD for your own unique instance.
    This will give you the entire Data Dictionary and the relationships you have in an easily browseable HTML format.
    You can also use the expression builder in some applications that will at least check your expressions are valid.
    Can also use formulae with a count returned, again to validate an expression.

    How to Generate an Entity Relationship Diagram for Maximo

    https://www.ibm.com/support/pages/node/6403201



    ------------------------------
    Visium Workflow
    ------------------------------