diff --git a/docs/questions/query-builder/expressions-list.md b/docs/questions/query-builder/expressions-list.md index 82c318b541a6674f83e22d10c4feca55b04849a5..b8815bc4609663f12c50a9a70d598d184a991264 100644 --- a/docs/questions/query-builder/expressions-list.md +++ b/docs/questions/query-builder/expressions-list.md @@ -6,7 +6,7 @@ redirect_from: # List of expressions -For an introduction to expressions, check out [Writing expressions in the notebook editor][expressions]. +For an introduction to expressions, check out the [overview of custom expressions][expressions]. - [Aggregations](#aggregations) - [Average](#average) @@ -24,53 +24,65 @@ For an introduction to expressions, check out [Writing expressions in the notebo - [Sum](#sum) - [SumIf](./expressions/sumif.md) - [Variance](#variance) -- [Functions](#functions) - - [abs](#abs) - - [between](#between) - - [case](./expressions/case.md) - - [ceil](#ceil) - - [coalesce](./expressions/coalesce.md) - - [concat](./expressions/concat.md) - - [contains](#contains) - - [convertTimezone](./expressions/converttimezone.md) - - [datetimeAdd](./expressions/datetimeadd.md) - - [datetimeDiff](./expressions/datetimediff.md) - - [datetimeSubtract](./expressions/datetimesubtract.md) - - [day](#day) - - [endswith](#endswith) - - [exp](#exp) - - [floor](#floor) - - [hour](#hour) - - [interval](#interval) - - [isempty](./expressions/isempty.md) - - [isnull](./expressions/isnull.md) - - [lefttrim](#lefttrim) - - [length](#length) - - [log](#log) - - [lower](#lower) - - [minute](#minute) - - [month](#month) - - [now](./expressions/now.md) - - [power](#power) - - [quarter](#quarter) - - [regexextract](./expressions/regexextract.md) - - [replace](#replace) - - [righttrim](#righttrim) - - [round](#round) - - [second](#second) - - [sqrt](#sqrt) - - [startswith](#startswith) - - [substring](./expressions/substring.md) - - [trim](#trim) - - [upper](#upper) - - [week](#week) - - [weekday](#weekday) - - [year](#year) + +- Functions + - [Logical functions](#logical-functions) + - [between](#between) + - [case](./expressions/case.md) + - [coalesce](./expressions/coalesce.md) + - [isnull](./expressions/isnull.md) + - [notnull](#notnull) + + - [Math functions](#math-functions) + - [abs](#abs) + - [ceil](#ceil) + - [exp](#exp) + - [floor](#floor) + - [log](#log) + - [power](#power) + - [round](#round) + - [sqrt](#sqrt) + + - [String functions](#string-functions) + - [concat](./expressions/concat.md) + - [contains](#contains) + - [doesNotContain](#doesnotcontain) + - [endsWith](#endswith) + - [isempty](./expressions/isempty.md) + - [ltrim](#ltrim) + - [length](#length) + - [lower](#lower) + - [notempty](#notempty) + - [regexextract](./expressions/regexextract.md) + - [replace](#replace) + - [rtrim](#rtrim) + - [startsWith](#startswith) + - [substring](./expressions/substring.md) + - [trim](#trim) + - [upper](#upper) + + - [Date functions](#date-functions) + - [convertTimezone](./expressions/converttimezone.md) + - [datetimeAdd](./expressions/datetimeadd.md) + - [datetimeDiff](./expressions/datetimediff.md) + - [datetimeSubtract](./expressions/datetimesubtract.md) + - [day](#day) + - [hour](#hour) + - [interval](#interval) + - [minute](#minute) + - [month](#month) + - [now](./expressions/now.md) + - [quarter](#quarter) + - [relativeDateTime](#relativedatetime) + - [second](#second) + - [week](#week) + - [weekday](#weekday) + - [year](#year) - [Database limitations](#database-limitations) ## Aggregations -Aggregation expressions take into account all values in a field. They can only be used in the **Summarize** section of the notebook editor. +Aggregation expressions take into account all values in a field. They can only be used in the **Summarize** section of the query builder. ### Average @@ -210,13 +222,8 @@ Related: [StandardDeviation](#standarddeviation), [Average](#average). Function expressions apply to each individual value. They can be used to alter or filter values in a column, or create new, custom columns. -### abs - -Returns the absolute (positive) value of the specified column. - -Syntax: `abs(column)` - -Example: `abs([Debt])`. If `Debt` were -100, `abs(-100)` would return `100`. +## Logical functions +Logical functions determine if a condition is satisfied or determine what value to return based on a condition. ### between @@ -236,16 +243,6 @@ Syntax: `case(condition, output, …)` Example: `case([Weight] > 200, "Large", [Weight] > 150, "Medium", "Small")` If a `Weight` is 250, the expression would return "Large". In this case, the default value is "Small", so any `Weight` 150 or less would return "Small". -### ceil - -Rounds a decimal up (ceil as in ceiling). - -Syntax: `ceil(column)`. - -Example: `ceil([Price])`. `ceil(2.99)` would return 3. - -Related: [floor](#floor), [round](#round). - ### [coalesce](./expressions/coalesce.md) Looks at the values in each argument in order and returns the first non-null value for each row. @@ -254,209 +251,217 @@ Syntax: `coalesce(value1, value2, …)` Example: `coalesce([Comments], [Notes], "No comments")`. If both the `Comments` and `Notes` columns are null for that row, the expression will return the string "No comments". -### [concat](./expressions/concat.md) +### [isnull](./expressions/isnull.md) -Combine two or more strings together. +Returns true if the column is null. -Syntax: `concat(value1, value2, …)` +Syntax: `isnull(column)` -Example: `concat([Last Name], ", ", [First Name])` would produce a string of the format "Last Name, First Name", like "Palazzo, Enrico". +Example: `isnull([Tax])` would return true if no value were present in the column for that row. -### contains +Related: [notnull](#notnull), [isempty](#isempty) -Checks to see if string1 contains string2 within it. +### notnull -Syntax: `contains(string1, string2)` +Returns true if the column contains a value. -Example: `contains([Status], "Class")`. If `Status` were "Classified", the expression would return `true`. +Syntax: `notnull(column)` -Related: [regexextract](#regexextract). +Example: `notnull([Tax])` would return true if there is a value present in the column for that row. -### [convertTimezone](./expressions/converttimezone.md) +Related: [isnull](#isnull), [notempty](#notempty) -Shifts a date or timestamp value into a specified time zone. +## Math functions +Math functions implement common mathematical operations. -Syntax: `convertTimezone(column, target, source)`. +### abs -Example: `convertTimezone("2022-12-28T12:00:00", "Canada/Pacific", "Canada/Eastern")` would return the value `2022-12-28T09:00:00`, displayed as `December 28, 2022, 9:00 AM`. +Returns the absolute (positive) value of the specified column. -### [datetimeAdd](./expressions/datetimeadd.md) +Syntax: `abs(column)` -Adds some unit of time to a date or timestamp value. +Example: `abs([Debt])`. If `Debt` were -100, `abs(-100)` would return `100`. -Syntax: `datetimeAdd(column, amount, unit)`. +### ceil -Example: `datetimeAdd("2021-03-25", 1, "month")` would return the value `2021-04-25`, displayed as `April 25, 2021`. +Rounds a decimal up (ceil as in ceiling). -Related: [between](#between), [datetimeSubtract](#datetimesubtract). +Syntax: `ceil(column)`. -### [datetimeDiff](./expressions/datetimediff.md) +Example: `ceil([Price])`. `ceil(2.99)` would return 3. -Returns the difference between two datetimes in some unit of time. For example, `datetimeDiff(d1, d2, "day") ` will return the number of days between `d1` and `d2`. +Related: [floor](#floor), [round](#round). -Syntax: `datetimeDiff(datetime1, datetime2, unit)`. +### exp -Example: `datetimeDiff("2022-02-01", "2022-03-01", "month")` would return `1`. +Returns [Euler's number](<https://en.wikipedia.org/wiki/E_(mathematical_constant)>), e, raised to the power of the supplied number. (Euler sounds like "Oy-ler"). -### [datetimeSubtract](./expressions/datetimesubtract.md) +Syntax: `exp(column)`. -Subtracts some unit of time from a date or timestamp value. +Example: `exp([Interest Months])` -Syntax: `datetimeSubtract(column, amount, unit)`. +Related: [power](#power). -Example: `datetimeSubtract("2021-03-25", 1, "month")` would return the value `2021-02-25`, displayed as `February 25, 2021`. +### floor -Related: [between](#between), [datetimeAdd](#datetimeadd). +Rounds a decimal number down. -### day +Syntax: `floor(column)` -Takes a datetime and returns the day of the month as an integer. +Example: `floor([Price])`. If the `Price` were 1.99, the expression would return 1. -Syntax: `day([datetime column])`. +Related: [ceil](#ceil), [round](#round). -Example: `day("2021-03-25T12:52:37")` would return the day as an integer, `25`. +### log -### endswith +Returns the base 10 log of the number. -Returns true if the end of the text matches the comparison text. +Syntax: `log(column)`. -Syntax: `endsWith(text, comparison)` +Example: `log([Value])`. -`endsWith([Appetite], "hungry")` +### power -Related: [contains](#contains) and [startswith](#startswith). +Raises a number to the power of the exponent value. -### exp +Syntax: `power(column, exponent)`. -Returns [Euler's number](<https://en.wikipedia.org/wiki/E_(mathematical_constant)>), e, raised to the power of the supplied number. (Euler sounds like "Oy-ler"). +Example: `power([Length], 2)`. If the length were `3`, the expression would return `9` (3 to the second power is 3\*3). -Syntax: `exp(column)`. +Databases that don't support `power`: SQLite. -Example: `exp([Interest Months])` +Related: [exp](#exp). -Related: [power](#power). +### round -### floor +Rounds a decimal number either up or down to the nearest integer value. -Rounds a decimal number down. +Syntax: `round(column)`. -Syntax: `floor(column)` +Example: `round([Temperature])`. If the temp were `13.5` degrees centigrade, the expression would return `14`. -Example: `floor([Price])`. If the `Price` were 1.99, the expression would return 1. +Example: `round([Temperature] * 10) / 10`. If the temp were `100.75`, the expression would return `100.8`. -Related: [ceil](#ceil), [round](#round). +### sqrt -### hour +Returns the square root of a value. -Takes a datetime and returns the hour as an integer (0-23). +Syntax: `sqrt(column)`. -Syntax: `hour([datetime column])`. +Example: `sqrt([Hypotenuse])`. -Example: `hour("2021-03-25T12:52:37")` would return `12`. +Databases that don't support `sqrt`: SQLite. -### interval +Related: [Power](#power). -Checks a date column's values to see if they're within the relative range. +## String functions +String functions manipulate or validate string data. -Syntax: `interval(column, number, text)`. +### [concat](./expressions/concat.md) -Example: `interval([Created At], -1, "month")`. +Combine two or more strings together. -Related: [between](#between). +Syntax: `concat(value1, value2, …)` -### [isempty](./expressions/isempty.md) +Example: `concat([Last Name], ", ", [First Name])` would produce a string of the format "Last Name, First Name", like "Palazzo, Enrico". -Returns true if the column is empty. +### contains -Syntax: `isempty(column)` +Checks to see if `string1` contains `string2` within it. -Example: `isempty([Discount])` would return true if there were no value in the discount field. +Performs case-sensitive match by default. +You can pass an optional parameter `"case-insensitive"` to perform a case-insensitive match. -### [isnull](./expressions/isnull.md) +Syntax: `contains(string1, string2)` for case-sensitive match. -Returns true if the column is null. +`contains(string1, string2, "case-insensitive")` for case-insensitive match. -Syntax: `isnull(column)` +Example: `contains([Status], "Class")`. -Example: `isnull([Tax])` would return true if no value were present in the column for that row. +If `Status` were "Classified", the expression would return `true`. If the `Status` were "**c**lassified", the expression would return `false`, because the case does not match. -### lefttrim +Related: [doesNotContain](#doesnotcontain), [regexextract](#regexextract). -Removes leading whitespace from a string of text. +### doesNotContain -Syntax: `ltrim(text)` +Checks to see if `string1` contains `string2` within it. -Example: `ltrim([Comment])`. If the comment were " I'd prefer not to", `ltrim` would return "I'd prefer not to". +Performs case-sensitive match by default. +You can pass an optional parameter `"case-insensitive"` to perform a case-insensitive match. -Related: [trim](#trim) and [righttrim](#righttrim). +Syntax: `doesNotContain(string1, string2)` for case-sensitive match. -### length +`doesNotContain(string1, string2, "case-insensitive")` for case-insensitive match. -Returns the number of characters in text. +Example: `doesNotContain([Status], "Class")`. If `Status` were "Classified", the expression would return `false`. -Syntax: `length(text)` +Related: [contains](#contains), [regexextract](#regexextract). -Example: `length([Comment])` If the `comment` were "wizard", `length` would return 6 ("wizard" has six characters). +### endsWith -### log +Returns true if the end of the text matches the comparison text. -Returns the base 10 log of the number. + Performs case-sensitive match by default. +You can pass an optional parameter `"case-insensitive"` to perform a case-insensitive match. -Syntax: `log(column)`. +Syntax: `endsWith(text, comparison)` for case-sensitive match. -Example: `log([Value])`. + `endsWith(text, comparison, "case-insensitive")` for case-insensitive match. -### lower +Example: `endsWith([Appetite], "hungry")` -Returns the string of text in all lower case. +Related: [startsWith](#startswith), [contains](#contains), [doesNotContain](#doesnotcontain). -Syntax: `lower(text)`. -Example: `lower([Status])`. If the `Status` were "QUIET", the expression would return "quiet". +### [isempty](./expressions/isempty.md) -Related: [upper](#upper). +Returns true if a _string column_ contains an empty string or is null. Calling this function on a non-string column will cause an error. You can use [isnull](#isnull) for non-string columns. -### minute +Syntax: `isempty(column)` -Takes a datetime and returns the minute as an integer (0-59). +Example: `isempty([Feedback])` would return true if `Feedback` was an empty string (`''`) or did not contain a value. -Syntax: `minute([datetime column])`. +Related: [notempty](#notempty), [isnull](#isnull) -Example: `minute("2021-03-25T12:52:37")` would return `52`. +### ltrim -### month +Removes leading whitespace from a string of text. -Takes a datetime and returns the month number (1-12) as an integer. +Syntax: `ltrim(text)` -Syntax: `month([datetime column])`. +Example: `ltrim([Comment])`. If the comment were `" I'd prefer not to"`, `ltrim` would return `"I'd prefer not to"`. -Example: `month("2021-03-25T12:52:37")` would return the month as an integer, `3`. +Related: [trim](#trim) and [rtrim](#rtrim). -### [now](./expressions/now.md) +### length -Returns the current date and time using your Metabase [report timezone](../../configuring-metabase/localization.md#report-timezone). +Returns the number of characters in text. -Syntax: `now`. +Syntax: `length(text)` -### power +Example: `length([Comment])`. If the `comment` were "wizard", `length` would return 6 ("wizard" has six characters). -Raises a number to the power of the exponent value. +### lower -Syntax: `power(column, exponent)`. +Returns the string of text in all lower case. -Example: `power([Length], 2)`. If the length were `3`, the expression would return `9` (3 to the second power is 3\*3). +Syntax: `lower(text)`. -Databases that don't support `power`: SQLite. +Example: `lower([Status])`. If the `Status` were "QUIET", the expression would return "quiet". -Related: [exp](#exp). +Related: [upper](#upper). -### quarter +### notempty -Takes a datetime and returns the number of the quarter in a year (1-4) as an integer. +Returns true if a _string column_ contains a value that is not the empty string. Calling this function on a non-string column will cause an error. You can use [notnull](#notnull) on non-string columns. -Syntax: `quarter([datetime column])`. +Syntax: `notempty(column)` + +Example: `notempty([Feedback])` would return true if `Feedback` contains a value that isn't the empty string (`''`). + + +Related: [isempty](#isempty), [isnull](#isnull), [notnull](#notnull) -Example: `quarter("2021-03-25T12:52:37")` would return `1` for the first quarter. ### [regexextract](./expressions/regexextract.md) @@ -468,7 +473,7 @@ Example: `regexextract([Address], "[0-9]+")`. Databases that don't support `regexextract`: H2, SQL Server, SQLite. -Related: [contains](#contains), [substring](#substring). +Related: [contains](#contains), [doesNotContain](#doesnotcontain), [substring](#substring). ### replace @@ -478,7 +483,7 @@ Syntax: `replace(text, find, replace)`. Example: `replace([Title], "Enormous", "Gigantic")`. -### righttrim +### rtrim Removes trailing whitespace from a string of text. @@ -486,47 +491,25 @@ Syntax: `rtrim(text)` Example: `rtrim([Comment])`. If the comment were "Fear is the mindkiller. ", the expression would return "Fear is the mindkiller." -Related: [trim](#trim) and [lefttrim](#lefttrim). - -### round - -Rounds a decimal number either up or down to the nearest integer value. - -Syntax: `round(column)`. - -Example: `round([Temperature])`. If the temp were `13.5` degrees centigrade, the expression would return `14`. - -Example: `round([Temperature] * 10) / 10`. If the temp were `100.75`, the expression would return `100.8`. - -### second - -Takes a datetime and returns the number of seconds in the minute (0-59) as an integer. - -Syntax: `second([datetime column)`. - -Example: `second("2021-03-25T12:52:37")` would return the integer `37`. - -### sqrt +Related: [trim](#trim) and [ltrim](#ltrim). -Returns the square root of a value. +### startsWith -Syntax: `sqrt(column)`. +Returns true if the beginning of the text matches the comparison text. Performs case-sensitive match by default. +You can pass an optional parameter `"case-insensitive"` to perform a case-insensitive match. -Example: `sqrt([Hypotenuse])`. - -Databases that don't support `sqrt`: SQLite. +Syntax: `startsWith(text, comparison)` for case-sensitive match. -Related: [Power](#power). + `startsWith(text, comparison, "case-insensitive")` for case-insensitive match. -### startswith +Example: `startsWith([Course Name], "Computer Science")` would return true for course names that began with "Computer Science", like "Computer Science 101: An introduction". -Returns true if the beginning of the text matches the comparison text. + It would return false for "Computer **s**cience 201: Data structures" because the case of "science" does not match the case in the comparison text. -Syntax: `startsWith(text, comparison)`. +`startsWith([Course Name], "Computer Science", "case-insensitive")` would return true for both "Computer Science 101: An introduction" and "Computer science 201: Data structures". -Example: `startsWith([Course Name], "Computer Science")` would return true for course names that began with "Computer Science", like "Computer Science 101: An introduction". -Related: [endswith](#endswith), [contains](#contains). +Related: [endsWith](#endswith), [contains](#contains), [doesNotContain](#doesnotcontain). ### [substring](./expressions/substring.md) @@ -554,6 +537,141 @@ Syntax: `upper(text)`. Example: `upper([Status])`. If status were "hyper", `upper("hyper")` would return "HYPER". +## Date functions +Date functions manipulate, extract, or create date and time values. + +### [convertTimezone](./expressions/converttimezone.md) + +Shifts a date or timestamp value into a specified time zone. + +Syntax: `convertTimezone(column, target, source)`. + +Example: `convertTimezone("2022-12-28T12:00:00", "Canada/Pacific", "Canada/Eastern")` would return the value `2022-12-28T09:00:00`, displayed as `December 28, 2022, 9:00 AM`. + +See the [database limitations](./expressions/converttimezone.md#limitations) for `convertTimezone`. + +### [datetimeAdd](./expressions/datetimeadd.md) + +Adds some unit of time to a date or timestamp value. + +Syntax: `datetimeAdd(column, amount, unit)`. + +Example: `datetimeAdd("2021-03-25", 1, "month")` would return the value `2021-04-25`, displayed as `April 25, 2021`. + +Related: [between](#between), [datetimeSubtract](#datetimesubtract). + +### [datetimeDiff](./expressions/datetimediff.md) + +Returns the difference between two datetimes in some unit of time. For example, `datetimeDiff(d1, d2, "day") ` will return the number of days between `d1` and `d2`. + +Syntax: `datetimeDiff(datetime1, datetime2, unit)`. + +Example: `datetimeDiff("2022-02-01", "2022-03-01", "month")` would return `1`. + +### [datetimeSubtract](./expressions/datetimesubtract.md) + +Subtracts some unit of time from a date or timestamp value. + +Syntax: `datetimeSubtract(column, amount, unit)`. + +Example: `datetimeSubtract("2021-03-25", 1, "month")` would return the value `2021-02-25`, displayed as `February 25, 2021`. + +Related: [between](#between), [datetimeAdd](#datetimeadd). + +### day + +Takes a datetime and returns the day of the month as an integer. + +Syntax: `day([datetime column])`. + +Example: `day("2021-03-25T12:52:37")` would return the day as an integer, `25`. + +### hour + +Takes a datetime and returns the hour as an integer (0-23). + +Syntax: `hour([datetime column])`. + +Example: `hour("2021-03-25T12:52:37")` would return `12`. + +### interval + +Checks a date column's values to see if they're within the relative range. + +Syntax: `interval(column, number, text)`. + +Example: `interval([Created At], -1, "month")`. + +Related: [between](#between). + +### minute + +Takes a datetime and returns the minute as an integer (0-59). + +Syntax: `minute([datetime column])`. + +Example: `minute("2021-03-25T12:52:37")` would return `52`. + +### month + +Takes a datetime and returns the month number (1-12) as an integer. + +Syntax: `month([datetime column])`. + +Example: `month("2021-03-25T12:52:37")` would return the month as an integer, `3`. + +### [now](./expressions/now.md) + +Returns the current date and time using your Metabase [report timezone](../../configuring-metabase/localization.md#report-timezone). + +Syntax: `now`. + +### quarter + +Takes a datetime and returns the number of the quarter in a year (1-4) as an integer. + +Syntax: `quarter([datetime column])`. + +Example: `quarter("2021-03-25T12:52:37")` would return `1` for the first quarter. + +### relativeDateTime + +Gets a timestamp relative to the current time. + +Syntax: `relativeDateTime(number, text)` + +`number`: Period of interval, where negative values are back in time. + +`text`: Type of interval like `"day"`, `"month"`, `"year"` + +`relativeDateTime` can only be used as part of a conditional expression. + +Example: `[Orders → Created At] < relativeDateTime(-30, "day")` will filter for orders created over 30 days ago from current date. + +Related: [datetimeAdd](#datetimeadd), [datetimeSubtract](#datetimesubtract). + +### second + +Takes a datetime and returns the number of seconds in the minute (0-59) as an integer. + +Syntax: `second([datetime column])`. + +Example: `second("2021-03-25T12:52:37")` would return the integer `37`. + +### timeSpan + +Gets a time interval of specified length. + +Syntax: `timeSpan(number, text)`. + +`number`: Period of interval, where negative values are back in time. + +`text`: Type of interval like `"day"`, `"month"`, `"year"` + +Example: `[Orders → Created At] + timeSpan(7, "day")` will return the date 7 days after the `Created At` date. + + + ### week Takes a datetime and returns the week as an integer. @@ -580,12 +698,12 @@ Example: ``` case( - weekday([Created At]) = 1, "Sunday", - weekday([Created At]) = 2, "Monday", - weekday([Created At]) = 3, "Tuesday", - weekday([Created At]) = 4, "Wednesday", - weekday([Created At]) = 5, "Thursday", - weekday([Created At]) = 6, "Friday", + weekday([Created At]) = 1, "Sunday", + weekday([Created At]) = 2, "Monday", + weekday([Created At]) = 3, "Tuesday", + weekday([Created At]) = 4, "Wednesday", + weekday([Created At]) = 5, "Thursday", + weekday([Created At]) = 6, "Friday", weekday([Created At]) = 7, "Saturday") ``` @@ -597,11 +715,21 @@ Syntax: `year([datetime column])`. Example: `year("2021-03-25T12:52:37")` would return the year 2021 as an integer, `2,021`. -## Database limitations +## Limitations + +- [Aggregation expressions](#aggregations) can only be used in the **Summarize** section of the query builder. +- Functions that return a boolean value, like [isempty](#isempty) or [contains](#contains), cannot be used to create a custom column. To create a custom column based on one of these functions, you must combine them with another function, like `case`. + +For example, to create a new custom column that contains `true` if `[Title]` contain `'Wallet'`, you can use the custom expression +``` +case(contains([Title], 'Wallet'), true, false) +``` + +### Database limitations Limitations are noted for each aggregation and function above, and here there are in summary: -**H2**: `Median`, `Percentile` and `regexextract` +**H2** (including Metabase Sample Database): `Median`, `Percentile`, `convertTimezone` and `regexextract` **MySQL/MariaDB**: `Median`, `Percentile`. @@ -615,6 +743,6 @@ Additionally, **Presto** only provides _approximate_ results for `Median` and `P If you're using or maintaining a third-party database driver, please [refer to the wiki](https://github.com/metabase/metabase/wiki/What's-new-in-0.35.0-for-Metabase-driver-authors) to see how your driver might be impacted. -See [Custom expressions in the notebook editor](https://www.metabase.com/learn/questions/custom-expressions) to learn more. +Check out our tutorial on [custom expressions in the query builder](https://www.metabase.com/learn/questions/custom-expressions) to learn more. [expressions]: ./expressions.md diff --git a/docs/questions/query-builder/expressions.md b/docs/questions/query-builder/expressions.md index d1e88bc15f29397c61b7df716fe7be271caabf0c..1f34c34bf90d369ce0c8793d49e6dc0b1d42cd64 100644 --- a/docs/questions/query-builder/expressions.md +++ b/docs/questions/query-builder/expressions.md @@ -16,9 +16,9 @@ To use custom expression, create a __Custom Column__ (where the custom expressio When using the query builder, you can use expressions to create new: -- **Filters**. The expression `= contains([comment], "Metabase")` would filter for rows where the `comment` field contained the word "Metabase". -- **Metrics**. Also known as summaries or aggregations. `= share([Total] > 50)` would return the percentage of orders with totals greater than 50 dollars. - **Custom columns**. You could use `= [Subtotal] / [Quantity]` to create a new column, which you could name "Item price". +- **Filters**. The expression `= contains([comment], "Metabase")` would filter for rows where the `comment` field contained the word "Metabase". +- **Summaries**. Also known as metrics or aggregations. `= Share([Total] > 50)` would return the percentage of orders with totals greater than 50 dollars. This page covers the basics of expressions. You can check out a [full list of expressions][expression-list] in Metabase, or walk through a tutorial that shows you how you can use [custom expressions in the notebook editor][custom-expressions]. @@ -40,7 +40,7 @@ Use `+`, `-`, `*` (multiply), `/` (divide) on numeric columns with numeric value For example, you could create a new column that calculates the difference between the total and subtotal of a order: `= [Total] - [Subtotal]`. -You can't currently do math on timestamp columns (we're working on adding new date functions soon, so stay tuned). +To do math on timestamp columns, you can use [Date functions](expressions-list.md#date-functions) like [dateDiff](./expressions/datetimediff.md). ## Conditional operators @@ -52,7 +52,7 @@ For example, you could create a filter for customers from California or Vermont: You can refer to columns in the current table, or to columns that are linked via a foreign key relationship. Column names should be included inside of square brackets, like this: `[Name of Column]`. Columns in connected tables can be referred to like this: `[ConnectedTableName.Column]`. -## Referencing Segments and metrics +## Referencing Segments and Metrics You can refer to saved [Segments or Metrics](../../data-modeling/segments-and-metrics.md) that are present in the currently selected table. You write these out the same as with columns, like this: `[Valid User Sessions]`. @@ -61,7 +61,7 @@ You can refer to saved [Segments or Metrics](../../data-modeling/segments-and-me Some things to keep in mind about filter expressions and conditionals: - Filter expressions are different in that they must return a Boolean value (something that's either true or false). For example, you could write `[Subtotal] + [Tax] < 100`. Metabase would look at each row, add its subtotal and tax, the check if that sum is greater than 100. If it is, the statement evaluates as true, and Metabase will include the row in the result. If instead you were to (incorrectly) write `[Subtotal] + [Tax]`, Metabase wouldn't know what to do, as that expression doesn't evaluate to true or false. -- You can use functions inside of the conditional portion of the `Countif` and `Sumif` aggregations, like so: `countif( round([Subtotal]) > 100 OR floor([Tax]) < 10 )`. +- You can use functions inside of the conditional portion of the `CountIf` and `SumIf` aggregations, like so: `CountIf( round([Subtotal]) > 100 OR floor([Tax]) < 10 )`. ## Working with dates in filter expressions @@ -77,7 +77,7 @@ This expression would return rows where `Created At` is between January 1, 2020 See a full list of [expressions][expression-list]. -For a tutorial on expressions, see [Custom expressions in the notebook editor][custom-expressions]. +For a tutorial on expressions, see [Custom expressions in the query builder][custom-expressions]. [aggregations]: ./expressions-list.md#aggregations [custom-expressions]: https://www.metabase.com/learn/questions/custom-expressions diff --git a/docs/questions/query-builder/expressions/converttimezone.md b/docs/questions/query-builder/expressions/converttimezone.md index a46b0d7ae842b3e62963913b4c6c3d40be001b05..22398bd14670eb3187fa2ac99e3d6516a0a5e619 100644 --- a/docs/questions/query-builder/expressions/converttimezone.md +++ b/docs/questions/query-builder/expressions/converttimezone.md @@ -121,6 +121,7 @@ Note that the first part of the timestamp is in UTC (same thing as GMT). The tim - Presto - SparkSQL - SQLite +- Metabase Sample Database ### Notes on source time zones diff --git a/docs/questions/query-builder/expressions/isempty.md b/docs/questions/query-builder/expressions/isempty.md index 10c18fc67685988c200152f8db0b2d312c8e4b3f..edfebf5eb151b49ff5d11b73c9d158282dbb5302 100644 --- a/docs/questions/query-builder/expressions/isempty.md +++ b/docs/questions/query-builder/expressions/isempty.md @@ -4,43 +4,55 @@ title: Isempty # Isempty -`isempty` checks if a value in a **string column** is an empty string (`""`). +`isempty` checks whether a value in a **string column** is an empty string (`""`) or null. Calling `isempty` on a non-string column would cause an error. -**In Metabase, you must combine `isempty` with another expression that accepts boolean values.** The table below shows you examples of the boolean output that will be passed to your other expression(s). +## Syntax + +``` +isempty(text column) +``` + +You can use `isempty` in [custom filters](../expressions.md#filter-expressions-and-conditionals), or as the condition for conditional aggregations [`CountIf`](../expressions/countif.md) and [`SumIf`](../expressions/sumif.md). To create a custom column using `isempty`, you must combine `isempty` with another function that accepts boolean values, like [`case`](./case.md). -| Syntax | Example with an empty string | Example with a true `null` | -| ------------------------------------------------------------------ | ---------------------------- | -------------------------- | -| `isempty(value)` | `isempty("")` | `isempty(null)` | -| Returns `true` if the value is an empty string, `false` otherwise. | `true` | `false` | -## How Metabase handles empty strings +## How Metabase handles empty strings and null values -In Metabase, columns with string [data types][data-types] will display blank cells for empty strings _or_ `null` values (if the column is nullable in your database). +In Metabase, columns with string [data types][data-types] will display blank cells for empty strings, strings of whitespace characters, _or_ `null` values (if the column is nullable in your database). +The table below shows you examples of the output of `isempty`. -For example, in the column below, the empty cells could contain either: +| Metabase shows| Database value | `isempty(value)` | +|---------------| --------------------| ------------------| +| | `null` | `true` | +| | `""` (empty string) | `true` | +| | `" "` (whitespace)| `false` | +| kitten |`"kitten"` | `false` | -- `""`: feedback was submitted and left intentionally blank, so the person had "no feedback to give". -- `null`: no feedback was submitted, so the person's thoughts are "unknown". +## Creating a boolean custom column + +To create a custom column using `isempty`, you must combine `isempty` with another function. +For example, if you want to create a custom column that contains `true` when the `Feedback` column is empty or null, and `false` otherwise, you can use the [`case expression`](./case.md) : + +``` +case(isempty([Feedback]), true, false) +``` -| Feedback | -| ------------------ | -| | -| | -| I like your style. | ## Replacing empty strings with another value -| Feedback | `case(isempty([Feedback]), "No feedback.", [Feedback])` | -| ------------------ | ------------------------------------------------------- | -| | | -| | No feedback. | -| I like your style. | I like your style. | +You can combine `isempty` with the [`case` expression](./case.md) to replace empty strings with something more descriptive. + +For example, you can create a new custom column that will contain `"No feedback"` when the original `[Feedback]` column is empty or null, and the feedback value when `[Feedback]` is has a non-empty value. The custom expression to do it is: +``` +case(isempty([Feedback]), "No feedback.", [Feedback]) +``` -Combine `isempty` with the [`case` expression](./case.md) to replace empty strings with something more descriptive. -Let's say that the second row's blank cell is actually an empty string, so `isempty` will return `true`. The `case` statement evaluates `true` to return the first output "No feedback". +| Feedback | `case(isempty([Feedback]), "No feedback.", [Feedback])` | +| ----------------------| ----------------------------------------------------------| +| `""` | `"No feedback."` | +| `null` | `"No feedback."` | +| `"I like your style."`| `"I like your style."` | -The first row's blank cell doesn't have an empty string, but because it's blank, we're not sure what's in it either---it could be a `null`, or even an emoji that blends into your table background. No matter what the edge case is, `isempty` will return `false`, and `case` will return whatever's in the Feedback column as the default output. ## Accepted data types @@ -54,9 +66,8 @@ The first row's blank cell doesn't have an empty string, but because it's blank, ## Limitations -- In Metabase, you must combine `isempty` with another expression that accepts boolean arguments (i.e., `true` or `false`). +- To create a custom column you must combine `isempty` with another expression that accepts boolean arguments (i.e., `true` or `false`). - `isempty` only accepts one value at a time. If you need to deal with empty strings from multiple columns, you'll need to use multiple `isempty` expressions with the [case expression](./case.md). -- If `isempty` doesn't seem to do anything to your blank cells, you might have `null` values. Try the [`isnull` expression](./isnull.md) instead. ## Related functions @@ -68,18 +79,18 @@ This section covers functions and formulas that can be used interchangeably with All examples below use the table from the [Replacing empty strings](#replacing-empty-strings-with-another-value) example: -| Feedback | `case(isempty([Feedback]), "No feedback.", [Feedback])` | -| ------------------ | ------------------------------------------------------- | -| | | -| | No feedback. | -| I like your style. | I like your style. | +| Feedback | `case(isempty([Feedback]), "No feedback.", [Feedback])` | +| ----------------------| ----------------------------------------------------------| +| `""` | `"No feedback."` | +| `null` | `"No feedback."` | +| `"I like your style."`| `"I like your style."` | ### SQL -In most cases (unless you're using a NoSQL database), questions created from the [notebook editor][notebook-editor-def] are converted into SQL queries that run against your database or data warehouse. +In most cases (unless you're using a NoSQL database), questions created from the [query builder][notebook-editor-def] are converted into SQL queries that run against your database or data warehouse. ```sql -CASE WHEN Feedback = "" THEN "No feedback" +CASE WHEN (Feedback = "" OR Feedback IS NULL) THEN "No feedback" ELSE Feedback END ``` @@ -107,8 +118,8 @@ case(isempty([Feedback]), "No feedback.", [Feedback]) Assuming the sample [feedback column](#replacing-empty-strings-with-another-value) is in a dataframe column called `df["Feedback"]`: -``` -df["Custom Column"] = np.where(df["Feedback"] == "", "No feedback.", df["Feedback"]) +```python +df["Custom Column"] = np.where((df["Feedback"] == "") | (df["Feedback"].isnull()), "No feedback.", df["Feedback"]) ``` is equivalent to the Metabase `isempty` expression: @@ -125,6 +136,6 @@ case(isempty([Feedback]), "No feedback.", [Feedback]) [custom-expressions-doc]: ../expressions.md [custom-expressions-learn]: https://www.metabase.com/learn/questions/custom-expressions [data-types]: https://www.metabase.com/learn/databases/data-types-overview#examples-of-data-types -[notebook-editor-def]: https://www.metabase.com/glossary/notebook_editor +[notebook-editor-def]: https://www.metabase.com/glossary/query_builder [numpy]: https://numpy.org/doc/ [pandas]: https://pandas.pydata.org/pandas-docs/stable/ diff --git a/docs/questions/query-builder/expressions/isnull.md b/docs/questions/query-builder/expressions/isnull.md index ebe0e0a373373bd939b247538d3b1ae1fed83677..9c26d37175db5d0fa323325337349332e5f9320c 100644 --- a/docs/questions/query-builder/expressions/isnull.md +++ b/docs/questions/query-builder/expressions/isnull.md @@ -6,39 +6,54 @@ title: Isnull `isnull` checks if a value is a `null`, a special kind of placeholder that's used by a database when something is missing or unknown. -**In Metabase, you must combine `isnull` with another expression that accepts boolean values.** The table below shows you examples of the boolean value that will be passed to your other expression(s). +## Syntax -| Syntax | Example with a true `null` | Example with an empty string | -| ----------------------------------------------------- | -------------------------- | ---------------------------- | -| `isnull(value)` | `isnull(null)` | `isnull("")` | -| Returns `true` if a value is `null`, false otherwise. | `true` | `false` | +``` +isnull(text column) +``` + +You can use `isnull` in [custom filters](../expressions.md#filter-expressions-and-conditionals), or as the condition for conditional aggregations [`CountIf`](../expressions/countif.md) and [`SumIf`](../expressions/sumif.md). To create a custom column using `isnull`, you must combine `isnull` with another function that accepts boolean values, like [`case`](./case.md). ## How Metabase handles nulls -In Metabase tables, `null`s are displayed as blank cells. For example, in the Feedback column below, the blank cells could contain either: +In Metabase tables, `null`s are displayed as blank cells. Additionally, for string columns, empty strings and strings containing only whitespace characters will be displayed as blank as well. + +The table below shows you examples of the output of `isnull`. -- `null`: no feedback was submitted, so the customer's thoughts are "unknown". -- `""`: feedback was submitted and left intentionally blank, so the customer had "no feedback to give". +| Metabase shows| Database value | `isnull(value)` | +|---------------| --------------------| ------------------| +| | `null` | `true` | +| | `""` (empty string) | `false`\* | +| | `" "` (whitespace)| `false` | +| kitten |`"kitten"` | `false` | -| Customer Feedback | -| ------------------ | -| | -| | -| I like your style. | +\*In Oracle and Vertica databases, empty strings are treated as nulls instead. + +## Creating a boolean custom column + +To create a custom column using `isnull`, you must combine `isnull` with another function. +For example, if you want to create a custom column that contains `true` when the `Discount` column is null, and `false` otherwise, you can use the [`case expression`](./case.md) : + +``` +case(isnull([Discount]), true, false) +``` ## Replacing null values with another value -| Feedback | `case(isnull([Feedback]), "Unknown feedback.", [Feedback])` | -| ------------------ | ----------------------------------------------------------- | -| | Unknown feedback. | -| | | -| I like your style. | I like your style. | +Combine `isnull` with the [`case` expression](./case.md) to replace missing information with something more descriptive: + +For example, you can create a new custom column that will contain `"Unknown feedback"` when the original `[Feedback]` column is null, and the actual feedback value when `[Feedback]` is has a value. The custom expression to do it is: +``` +case(isnull([Feedback]), "Unknown feedback.", [Feedback]) +``` -Combine `isnull` with the [`case` expression](./case.md) to replace "unknown" information with something more descriptive. -Let's say that the first row's blank cell is actually a `null`, so `isnull` will return `true`. The `case` statement evaluates `true` to return the first output "Unknown feedback". +| Feedback | `case(isnull([Feedback]), "Unknown feedback.", [Feedback])` | +| -----------------------| ----------------------------------------------------------- | +| `null` | `"Unknown feedback."` | +| `""` | `""` | +| `"I like your style."` | `"I like your style."` | -The second row's blank cell doesn't have a `null`, but we're not sure what's in it either---it could be an empty string, or even an emoji that blends into your table's background. No matter what the edge case is, `isnull` will return `false`, and `case` will return whatever's in the Feedback column as the default output. ## Accepted data types @@ -66,15 +81,15 @@ This section covers functions and formulas that can be used interchangeably with All examples below use the table from the [Replacing null values](#replacing-null-values-with-another-value) example: -| Feedback | `case(isnull([Feedback]), "Unknown feedback.", [Feedback])` | -| ------------------ | ----------------------------------------------------------- | -| | Unknown feedback. | -| | | -| I like your style. | I like your style. | +| Feedback | `case(isnull([Feedback]), "Unknown feedback.", [Feedback])` | +| -----------------------| ----------------------------------------------------------- | +| `null` | `"Unknown feedback."` | +| `""` | `""` | +| `"I like your style."` | `"I like your style."` | ### SQL -In most cases (unless you're using a NoSQL database), questions created from the [notebook editor][notebook-editor-def] are converted into SQL queries that run against your database or data warehouse. +In most cases (unless you're using a NoSQL database), questions created from the [query builder][notebook-editor-def] are converted into SQL queries that run against your database or data warehouse. ```sql CASE WHEN Feedback IS NULL THEN "Unknown feedback", @@ -127,6 +142,6 @@ case(isnull([Feedback]), "Unknown feedback.", [Feedback]) [custom-expressions-doc]: ../expressions.md [custom-expressions-learn]: https://www.metabase.com/learn/questions/custom-expressions [data-types]: https://www.metabase.com/learn/databases/data-types-overview#examples-of-data-types -[notebook-editor-def]: https://www.metabase.com/glossary/notebook_editor +[notebook-editor-def]: https://www.metabase.com/glossary/query_builder [numpy]: https://numpy.org/doc/ [pandas]: https://pandas.pydata.org/pandas-docs/stable/