The difference in fields and display commands is that fields behavior is cumulative and display is not (replace-like behavior).
From the CloudWatch Logs Insights query syntax guideline:
If your query contains multiple fields commands and doesn't include a display command, you'll display all of the fields that are specified in the fields commands.
So a display command would replace the output defined by any preceding display or fields commands (or any other command that defines ephemeral fields), and the fields would add to the currently defined output.
Examples:
- Returns @timestamp, @message, @logStream, @log fields
fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| limit 20
- Returns @message
fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| limit 20
| display @message
- Returns @message, requestId, text, hasRequestId
fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| limit 20
| display @message
| parse @message "(*) *" as requestId, text
| fields !isblank("requestId") as hasRequestId
The last example defines ephemeral fields using parse command (these do not have @ in the beginning) and expression field defined by last fields command