BQL Basics
The Logical Query Language (BQL) includes various pieces of functionality.
Basic Elements and Query Syntax
The basic form of a BQL query is:
SELECT [attribute],[measure] FROM [subject_area] WHERE condition ORDER BY
[attribute|measure] ASCENDING|DESCENDING
You can select one or more attributes or measures from a given subject area, filter results, and sort them.
BQL syntax requires that attribute, measure, and subject area names are surrounded by square brackets. Strings are surrounded by single quotes.
A subject area is a grouping of attributes and measures in the space. The default subject area is “ALL”, which indicates the entire set. Most BQL statements use [ALL]. For ease of use or security reasons, you may create a custom subject area having a subset from the entire list. See Creating and managing a subject area in the Infor Birst Administrator User Guide.
This is an example of a basic BQL query:
SELECT [Order_Date: Sum: Quantity], [Products.Products] FROM [ALL] WHERE
[Order_Date: Sum: Quantity]>=50000 ORDER BY [Order_Date: Sum: Quantity]
DESCENDING
To put comments in BQL code, use this syntax:
/* my comment */
- Syntax and Conventions for Examples
- These are the conventions followed in the examples:
- Keywords are in ALL CAPS.
- Pipes (|) separate multiple possible entries (attribute|measure means either an attribute name or a measure name).
- Placeholders for element names are in italic font.
- Optional elements are in curly brackets { }.
- Most examples do not specify header strings.
- Most examples use [ALL] as the subject area.
- It is not required to write all queries by hand. You can use the Visualizer drag-drop interface to interactively build queries, then click to see the BQL statement that was generated via drag and drop.
- For advanced users with data warehousing experience, use Navigate Query in the to see how the query engine executes the logical query against the physical tables. See Query Admin in the Infor Birst Administrator User Guide.
- These are the conventions followed in the examples:
Hierarchy Attributes (Dimensional Attributes)
To create a query that includes a hierarchy column, use its fully qualified name, the column name preceded by the hierarchy name. For example, to select an attribute:
SELECT [hierarchy.attribute] FROM [subject_area]
For example, to select all categories of products:
SELECT [Products.Categories] FROM [ALL]
Categories |
---|
Desktop |
MP3 Players |
Mobile Phones |
Notebooks |
Tablets |
Measures (Fact Columns)
The syntax for including measures in a query is similar to attributes. Because measures are for counting, they have additional functionality including aggregates and date type (Analyze by Date enablement in Prepare/Model Properties). Aggregates are required; date types are optional though strongly encouraged on those date columns where it is important to slice data by time series (i.e., YTD).
SELECT [{date_type: }aggregate: measure] FROM [ALL]
- Aggregates for Measures
- Aggregates are required in the SELECT statement and they are case-sensitive.
Aggregates include:
- Avg
- Count
- Count Distinct
- Max
- Min
- Sum
-
For example:
SELECT [Order_Date: Sum: Quantity] FROM [ALL]
Table 2. Query Result Order_Date: Sum: Quantity 2,833,776 - Two special aggregates use a slightly different syntax. Count and Count Distinct use
the hash sign (#) and do not use a colon:
- # Distinct (count distinct)
- # (count)
-
For example:
SELECT [# Distinct Quantity] FROM [ALL]
Table 3. Query Result # Distinct Quantity 502
- Aggregates are required in the SELECT statement and they are case-sensitive.
Aggregates include:
Data Types for Measures
For all measures there is a default. For many of the measures, there is an optional syntax for specifying a "by Date Type".
The default date type is Load Date, the last time the data source was loaded.
Use the date type syntax before the aggregate syntax:
SELECT [attribute],[{date_type: }aggregate: measure_name] FROM [ALL]
For example, by Order Date:
SELECT [Order_Date: Sum: Quantity] FROM [ALL]
Order_Date: Sum: Quantity |
---|
944,592 |
To ensure measures make sense in a visualization, include at least one attribute in the query.
For example, to analyze quantity by category:
SELECT [Products.Categories],[Order_Date: Sum: Quantity] FROM [ALL]
Categories | Quantity |
---|---|
Desktop | 74,485 |
MP3 Players | 308,100 |
Mobile Phones | 135.397 |
Notebooks | 117,216 |
Tablets | 309.394 |
Column Header Strings
The syntax for changing column headers is optional. By default Birst uses the column name from the data store as the header.
SELECT [attribute | measure {'header_string'},
attribute | measure {'header_string'} ...] FROM
[subject_area]
For example, to change the column headers from Categories to Category and Quantity to Total:
SELECT [Products.Categories] 'Category', [Order_Date: Sum: Quantity]
'Total' FROM [ALL]
Categories | Quantity |
---|---|
Desktop | 74,485 |
MP3 Players | 308,100 |
Mobile Phones | 135.397 |
Notebooks | 117,216 |
Tablets | 309.394 |
- Column Headers in Designer and Visualizer
- When Designer automatically creates queries for you based on what you drag-and-drop, it uses internal syntax ('F1', 'F2', etc.) to map the header placeholder to the header from the data store, and it displays the header. In Designer you do not use BQL to change the headers, instead you click on the column header and select to modify the column label.
- Visualizer does the same, though it uses 'COL0', 'COL1', etc. as the placeholder. You can see this for a report's query at . To change headers in Visualizer, double-click on the column label in a table or on the axis label text on a chart.
Filtering Results: WHERE
In addition to selecting attributes and measures, you can restrict the results to various subsets using a WHERE clause.
For example, if you want to know the sales for 2014:
SELECT [Order_Date: Sum: Unit_Sale_Price] 'Sum of Unit Sale Price in 2014' , FROM
[ALL] WHERE [Time.Year]=2014
Sum of Unit Sale Price in 2014 |
---|
14,594,869.03 |
- = (equals)
- > (greater than)
- < (less than)
- >= (greater than or equals)
- <= (less than or equals)
- <> (not equals)
For example:
SELECT [Order_Date: Sum: Unit_Sale_Price] 'Sum of Sales Before 2014' , FROM [ALL]
WHERE [Time.Year]<=2014
Sum of Unit Sale Price Before 2014 |
---|
94,639,114.88 |
- Filtering Results on Measure Values
-
You can restrict results based on measures. For example, to see a list of products that sold at least 50000 units in 2014:
SELECT [Order_Date: Sum: Quantity] 'Quantity', [Products.Products] FROM [ALL] WHERE [Order_Date: Sum: Quantity]>=50000
Table 9. Query Results Quantity Products 103,445 mangoPad 3 32 GB 94.946 mangoPad 3 64 GB 105.703 mangoPhone 4G 32 GB 65,229 mangoPad 3 64 GB The query returns only the records where the measure column matches the filter when grouped by the attributes in the query.
-
- Using Multiple Filters: AND, OR
-
More complicated queries can combine several individual filters using AND and OR syntax. For example, to see a list of products that sold at least 50000 units in 2014:
SELECT [Order_Date: Sum: Quantity] 'Quantity', [Products.Products] FROM [ALL] WHERE [Order_Date: Sum: Quantity]>=50000 AND [Time.Year] = 2014
Quantity Products 50,117 mangoPhone 4G 32 GB You can add an OR clause and use parenthesis to indicate which AND or OR takes precedence:
SELECT [Order_Date: Sum: Quantity] 'Quantity', [Products.Products] FROM [ALL] WHERE [Order_Date: Sum: Quantity]>=50000 AND ([Time.Year] = 2014 OR [Time.Year] = 2013)
Table 10. Query Results Quantity Products 103,445 mangoPad 3 32 GB 105,703 mangoPhone 4G 32 GB 65,229 mangoPhone 4G 64 GB 94,946 mangoPad 3 64 GB
-
- Filtering a Single Measure
-
In addition to filtering an entire result set, it is often useful to be able to filter specific measures by an attribute. This is also called a measure filter. An example is to show Quantity for all sales and only for sales in France. To calculate this, you add a WHERE clause to the measure section, instead of after the FROM clause:
SELECT [Order_Date: Sum: Quantity] 'Quantity All', [Order_Date: Sum: Quantity] WHERE [Retail_Stores.Retailer Country]='France' 'France Only' FROM [ALL]
Quantity All France Only 944,592 3,352 Only filters on attributes are allowed in a measure filter. This is because a measure is undefined without a level of aggregation. If you want to filter based on a measure at a given level, you can use bucketed measures that turn measures into attributes with values bucketed based on the measure. This will make certain what level of aggregation is applied to a measure before it is applied in a measure filter.
-
- Filtering on a Measure-Filtered Column
-
Occasionally, you would like to filter a result set based on a filtered measure column. The syntax to do this is a slight alteration of both the normal filter syntax and the measure filter syntax. The filtered measure is surrounded by parenthesis to indicate that this is a measure filter.
SELECT [Time.Year/Quarter], [Products.Categories], [Order_Date: Sum: Quantity] 'Quantity', FROM [ALL] WHERE ([Order_Date: Sum: Quantity] WHERE [Products.Categories]='Tablets')>=25000
Table 11. Query Results Year/Quarter Categories Quantity 2013/Q1 Tablets 35,284 2013/Q2 Tablets 45,466 2013/Q3 Tablets 33,849 2013/Q4 Tablets 25,436 2014/Q1 Tablets 45,848 2014/Q2 Tablets 41,534
-
- Set-Based Filtering: IN, NOT IN
- You can create a subquery that defines a set of values used to filter the parent
query. This allows for more complex filtering conditions. For
example:
SELECT [Products.Products],[Order_Date: Sum: Quantity] FROM [ALL] WHERE [Products.Categories] IN (SELECT [Products.Categories] FROM [ALL] WHERE [Order_Date: Sum: Quantity]<=100000)
Table 12. Query Results Products Order_Date: Sum: Quantity iMango Desktop 22 15,439 iMango Desktop 27 12,823 iMango Mini 3.0 GHz 3,348 iMango Mini 3.5 GHz 11,810 Mango Server 5,211 Mango Workstation 12 Core 2,355 Mango Workstation 8 Core 10,003 Mango Workstation Quad Core 13,496 In this example the filtering is done on Products.Categories, which is not displayed, and all the Products in the category that meets the criteria are displayed.
Note: BQL expressions that perform operations, including query functions (RANK, CONCAT, etc.) and positional calculations, in subqueries are not supported. The "IN" or "NOT IN" subquery can use the basic operators such as equal to (=), less than (<), etc.Note: Designer supports set-based filters. Visualizer does not.
- You can create a subquery that defines a set of values used to filter the parent
query. This allows for more complex filtering conditions. For
example:
- Date Syntax in Filters
-
You may need to refer to a specific date in a BQL query WHERE filter. For slash-style dates, add the hash sign around the string. For example:
...WHERE [Month.Start Date]=#11/1/2015#
-
Controlling Sort Ordering: ORDER BY
You can specify how results should be sorted by attribute orderings or measure orderings. Sorts can be either ASCENDING or DESCENDING. The abbreviated syntax ASC and DESC are also supported.
For example, to show product categories in descending order of sales:
SELECT [Order_Date: Sum: Quantity], [Products.Categories] FROM [ALL] ORDER BY
[Order_Date: Sum: Quantity] DESCENDING
Order_Date: Sum: Quantity | Categories |
---|---|
309,394 | Tablets |
308,100 | Mobile Phones |
135,397 | MP3 Players |
117,216 | Notebooks |
74,485 | Desktops |
You can define multiple sorts. For example, to sort by store region, then by quarter for 2013:
SELECT [Order_Date: Sum: Quantity], [Retail_Stores.Retail Region], [Time.Quarter]
FROM [ALL] WHERE [Time.Year]='2013' ORDER BY [Retail_Stores.Retail Region] ASC,
[Time.Quarter] DESC
Returning a Limited Result Set: TOP
Use the TOP operator to return a limited number of rows in the result set from the database.
For example:
SELECT TOP 5 [Order_Date: Sum: Quantity], [Products.Products] FROM [ALL] ORDER BY
[Order_Date: Sum: Quantity] ASCENDING
Order_Date: Sum: Quantity | Products |
---|---|
1,218 | Mango Air 11 128GB |
1,623 | MangoBook Pro 15 3.5 GHz |
2,355 | Mango Workstation 12 Core |
3,348 | Mango Mini 3.0 GHz |
4,525 | MangoBook Pro 17 3.5 GHz |
This example causes the query to return only the top 5 records, as determined by sort order.
Whatever sort ordering is applied, TOP limits the results to the first ones in the result set. For example, if you change the sort order to DESCENDING, the TOP would be very different.
SELECT TOP 5 [Order_Date: Sum: Quantity], [Products.Products] FROM [ALL] ORDER BY
[Order_Date: Sum: Quantity] DESCENDING
Order_Date: Sum: Quantity | Products |
---|---|
105,703 | mangoPhone 4G 32GB |
103,445 | MangoBook Pro 15 3.5 GHz |
94,946 | Mango Workstation 12 Core |
65,229 | Mango Mini 3.0 GHz |
48,641 | MangoBook Pro 17 3.5 GHz |
INNER and OUTER Joins: USING OUTER Join
Depending on the underlying data, you combine measures in a result set with the
USING OUTER JOIN
syntax.
By default, the BQL query engine returns only results that have values for all measures that are specified. This behavior generates more efficient underlying queries and conforms to standardized data warehousing techniques.
However, sometimes you want to include all dimensional attributes that have any cells
filled, regardless of whether some measures have values. This is called an outer join and
you employ the USING OUTER JOIN
syntax. For example:
SELECT USING OUTER JOIN [Products.Categories], [Order_Date: Sum: Quantity],
[Order_Date: Sum: Revenue] FROM [ALL]
USING OUTER JOIN
syntax.Constants
BQL supports string or numeric constants in queries. Surround strings in single quotes.
SELECT 'Test_Constant', [Order_Date: Sum: Quantity] FROM [ALL]
A string constant in the SELECT statement results in a column that includes the string in each row, including the header. For example:
Test_Constant | Quantity |
---|---|
Test_Constant | 150,028 |
Test_Constant | 215,021 |
Test_Constant | 330,081 |
Test_Constant | 249,462 |
For more BQL syntax, see Advanced BQL.