Skip to content

Commit 5b2b71e

Browse files
authored
Add column_ifexists (#273)
1 parent 6e61aea commit 5b2b71e

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
title: column_ifexists
3+
description: 'This page explains how to use the column_ifexists function in APL.'
4+
---
5+
6+
Use `column_ifexists()` to make your queries resilient to schema changes. The function checks if a field with a given name exists in the dataset. If it does, the function returns it. If not, it returns a fallback field or expression that you provide.
7+
8+
This is especially useful when working with datasets that evolve over time or come from multiple sources with different schemas. Instead of failing when a field is missing, your query continues running by using a default. Use this function to safely handle queries where the presence of a field isn’t guaranteed.
9+
10+
## For users of other query languages
11+
12+
If you come from other query languages, this section explains how to adjust your existing queries to achieve the same results in APL.
13+
14+
<AccordionGroup>
15+
<Accordion title="Splunk SPL users">
16+
17+
In Splunk, field selection is strict—missing fields typically return `null` in results, but conditional logic for fallback fields requires using `eval` or `coalesce`. In APL, `column_ifexists()` directly substitutes the fallback field at query-time based on schema.
18+
19+
<CodeGroup>
20+
```sql Splunk example
21+
... | eval field=if(isnull(Capital), State, Capital)
22+
```
23+
24+
```kusto APL equivalent
25+
StormEvents | project column_ifexists('Capital', State)
26+
```
27+
</CodeGroup>
28+
29+
</Accordion>
30+
<Accordion title="ANSI SQL users">
31+
32+
In SQL, you need to check for the existence of a field using system views or error handling. `column_ifexists()` in APL simplifies this by allowing fallback behavior inline without needing procedural code.
33+
34+
<CodeGroup>
35+
```sql SQL example
36+
SELECT CASE
37+
WHEN EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS
38+
WHERE TABLE_NAME = 'StormEvents' AND COLUMN_NAME = 'Capital')
39+
THEN Capital ELSE State END AS Result
40+
FROM StormEvents
41+
```
42+
43+
```kusto APL equivalent
44+
StormEvents | project column_ifexists('Capital', State)
45+
```
46+
</CodeGroup>
47+
48+
</Accordion>
49+
</AccordionGroup>
50+
51+
## Usage
52+
53+
### Syntax
54+
55+
```kusto
56+
column_ifexists(FieldName, DefaultValue)
57+
```
58+
59+
### Parameters
60+
61+
- `FieldName`: The name of the field to return as a string.
62+
- `DefaultValue`: The fallback value to return if `FieldName` doesn’t exist. This can be another field or a literal.
63+
64+
### Returns
65+
66+
Returns the field specified by `FieldName` if it exists in the table schema. Otherwise, returns the result of `DefaultValue`.
67+
68+
## Use case examples
69+
70+
<Tabs>
71+
<Tab title="Log analysis">
72+
73+
You want to examine HTTP logs, and your schema might have a `geo.region` field in some environments and not in others. You fall back to `geo.country` when `geo.region` is missing.
74+
75+
**Query**
76+
77+
```kusto
78+
['sample-http-logs']
79+
| project _time, location = column_ifexists('geo.region', ['geo.country'])
80+
```
81+
82+
[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20project%20_time%2C%20location%20%3D%20column_ifexists('geo.region'%2C%20%5B'geo.country'%5D)%22%7D)
83+
84+
**Output**
85+
86+
| _time | location |
87+
|----------------------|----------------|
88+
| 2025-04-28T12:04:10Z | United States |
89+
| 2025-04-28T12:04:12Z | Canada |
90+
| 2025-04-28T12:04:15Z | United Kingdom |
91+
92+
The query returns `geo.region` if it exists; otherwise, it falls back to `geo.country`.
93+
94+
</Tab>
95+
<Tab title="OpenTelemetry traces">
96+
97+
You analyze OpenTelemetry traces and you’re not sure if your data contains `status_code` and `status` fields. You fall back to `100` when it’s missing.
98+
99+
**Query**
100+
101+
```kusto
102+
['otel-demo-traces']
103+
| extend status_code_field = column_ifexists('status_code', '100')
104+
| extend status_field = column_ifexists('status', 100)
105+
| project _time, trace_id, span_id, status_code_field, status_field
106+
```
107+
108+
[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'otel-demo-traces'%5D%20%7C%20extend%20status_code_field%20%3D%20column_ifexists('status_code'%2C%20'100')%20%7C%20extend%20status_field%20%3D%20column_ifexists('status'%2C%20100)%20%7C%20project%20_time%2C%20trace_id%2C%20span_id%2C%20status_code_field%2C%20status_field%22%7D)
109+
110+
**Output**
111+
112+
| _time | trace_id | span_id | status_code_field | status_field |
113+
|---------------------|--------------|-------------|--------|---|
114+
| 2025-04-28T10:30:12Z | abc123 | span567 | nil | 100 |
115+
| 2025-04-28T10:30:15Z | def456 | span890 | 200 | 100 |
116+
117+
The query returns the `status_code` field if it exists. Otherwise, it falls back to `100`.
118+
119+
</Tab>
120+
<Tab title="Security logs">
121+
122+
You inspect logs for suspicious activity. In some datasets, a `threat_level` field exists, but not in all. You use the `status` field as a fallback.
123+
124+
**Query**
125+
126+
```kusto
127+
['sample-http-logs']
128+
| project _time, id, threat = column_ifexists('threat_level', status)
129+
```
130+
131+
[Run in Playground](https://play.axiom.co/axiom-play-qf1k/query?initForm=%7B%22apl%22%3A%22%5B'sample-http-logs'%5D%20%7C%20project%20_time%2C%20id%2C%20threat%20%3D%20column_ifexists('threat_level'%2C%20status)%22%7D)
132+
133+
**Output**
134+
135+
| _time | id | threat |
136+
|---------------------|--------|--------|
137+
| 2025-04-28T13:22:11Z | u123 | 200 |
138+
| 2025-04-28T13:22:13Z | u456 | 403 |
139+
140+
The function avoids breaking the query if `threat_level` doesn’t exist by defaulting to `status`.
141+
142+
</Tab>
143+
</Tabs>
144+
145+
## List of related functions
146+
147+
- [coalesce](/apl/scalar-functions/string-functions#coalesce): Returns the first non-null value from a list of expressions. Use when you want to handle null values, not missing fields.
148+
- [iff](/apl/scalar-functions/conditional-function#iff): Performs conditional logic based on a boolean expression. Use when you want explicit control over evaluation.
149+
- [isnull](/apl/scalar-functions/string-functions#isnull): Checks if a value is null. Useful when combined with other functions for fine-grained control.
150+
- [case](/apl/scalar-functions/conditional-function#case): Allows multiple conditional branches. Use when fallback logic depends on multiple conditions.
151+
- [project](/apl/tabular-operators/project-operator): Selects and transforms fields. Use with `column_ifexists()` to build resilient field projections.

docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@
421421
{
422422
"group": "Metadata functions",
423423
"pages": [
424+
"apl/scalar-functions/metadata-functions/column-ifexists",
424425
"apl/scalar-functions/metadata-functions/ingestion_time"
425426
]
426427
},

0 commit comments

Comments
 (0)