# Oxla Developer Hub

## Docs

- [Key Concepts & Architecture](https://docs.oxla.com/1-introduction/1-1-key-concepts-archi/key-concept-and-architecture)
- [OLTP vs OLAP](https://docs.oxla.com/1-introduction/1-1-key-concepts-archi/oltp-olap)
- [Our Key Features](https://docs.oxla.com/1-introduction/1-1-key-concepts-archi/our-key-features)
- [Oxla vs. Other OLAP Solutions](https://docs.oxla.com/1-introduction/1-1-key-concepts-archi/oxla-vs-other-olap-solutions)
- [C# Dapper - Npgsql](https://docs.oxla.com/11-integrations/dotnet-dapper)
- [JAVA JDBC](https://docs.oxla.com/11-integrations/java-jdbc)
- [PHP PDO](https://docs.oxla.com/11-integrations/php-pdo)
- [Data Task Stability](https://docs.oxla.com/12-system-behaviour/data_task_stability)
- [Multi-node Deployment](https://docs.oxla.com/2-run-oxla/multi-node-deployment)
- [Run Oxla in 2 minutes](https://docs.oxla.com/2-run-oxla/run-oxla-in-2-minutes)
- [Run Oxla on Azure Blob Storage](https://docs.oxla.com/2-run-oxla/run-oxla-on-azure-blob-storage)
- [Run Oxla on Google Cloud Storage](https://docs.oxla.com/2-run-oxla/run-oxla-on-google-cloud-storage)
- [Run Oxla on S3](https://docs.oxla.com/2-run-oxla/run-oxla-on-s3)
- [Run Oxla via AWS](https://docs.oxla.com/2-run-oxla/run-oxla-via-aws)
- [SET/SHOW statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-10-set-show-statement/set-show)
- [COPY FROM](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from)
- [COPY FROM STDIN](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from-stdin)
- [COPY FROM with Delimiter](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from-with-delimiter)
- [COPY FROM with Endpoint](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from-with-endpoint)
- [COPY FROM with HEADER](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from-with-header)
- [COPY FROM with NULL](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from-with-null)
- [COPY TO](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to)
- [COPY TO STDOUT](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to-stdout)
- [COPY TO with Delimiter](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to-with-delimiter)
- [COPY TO with Endpoint](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to-with-endpoint)
- [COPY TO with HEADER](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to-with-header)
- [COPY TO with NULL](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to-with-null)
- [Create Table](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-2-create-table-statement/create-table)
- [Keywords](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-2-create-table-statement/keywords)
- [CREATE INDEX statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-3-create-index-statement/create-index)
- [SELECT statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-4-select-statement/select)
- [INSERT INTO statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-5-insert-into-statement/insert-into)
- [DROP statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-6-drop-statement/drop)
- [SHOW TABLES statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-7-show-tables-statement/show-tables)
- [DESCRIBE statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-8-describe-statement/describe)
- [SHOW NODES statement](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-9-show-nodes-statement/show-nodes)
- [Overview](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/sql-statement-overview)
- [SQL TABLE](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/sql-table)
- [FROM](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/from)
- [JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/join)
- [LEFT JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/left-join)
- [OUTER JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/outer-join)
- [RIGHT JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/right-join)
- [WHERE](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-2-where/where)
- [GROUP BY](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-3-group-by/group-by)
- [HAVING](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-4-having/having)
- [ORDER BY](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-5-order-by/order-by)
- [LIMIT](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-6-limit/limit)
- [OFFSET](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-7-offset/offset)
- [EXCEPT](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/except)
- [INTERSECT](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/intersect)
- [Overview](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/set-operations)
- [UNION](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/union)
- [Overview](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/sql-clauses-overview)
- [Data Type Operators](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-1-operators/data-type-operator)
- [JSON Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-10-json-types/json-type)
- [Bool Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-2-bool-types/bool)
- [Date Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-3-date-types/date)
- [Timestamp Without Time Zone Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-4-timestamp-without-time-zone/timestamp-without-time-zone)
- [Timestamp with Time Zone](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-5-timestamp-with-time-zone/timestamp-with-time-zone)
- [Time Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-6-time-types/time)
- [Time Operators](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-6-time-types/time-operator)
- [Interval Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-7-interval-types/interval)
- [Text Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-8-text-types/text)
- [Numeric Data Type - Aliases](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-9-numeric-types/numeric-data-type-aliases)
- [Numeric Type](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-9-numeric-types/numeric-type)
- [Overview](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/data-types-overview)
- [ABS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/abs)
- [CBRT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/cbrt)
- [CEIL](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/ceil)
- [EXP](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/exp)
- [FLOOR](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/floor)
- [GREATEST](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/greatest)
- [LEAST](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/least)
- [LN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/ln)
- [LOG](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/log)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/numeric-functions)
- [POWER](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/power)
- [RANDOM](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/random)
- [ROUND](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/round)
- [SIGN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/sign)
- [SIN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/sin)
- [SQRT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/sqrt)
- [TO_CHAR from Number](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/to-char-from-number)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/aggregation-functions)
- [AVG](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/avg)
- [BOOL_AND](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/bool-and)
- [BOOL_OR](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/bool-or)
- [COUNT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/count)
- [DISTINCT qualifier](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/distinct)
- [FOR_MAX](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/for-max)
- [FOR_MIN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/for-min)
- [MAX](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/max)
- [MIN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/min)
- [SUM](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/sum)
- [CONCAT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/concat)
- [ENDS_WITH](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/ends-with)
- [LENGTH](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/length)
- [LOWER](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/lower)
- [POSITION](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/position)
- [POSIX Regular Expressions](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/regexp-replace/posix-expression)
- [REGEXP_REPLACE](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/regexp-replace/regexp)
- [REPLACE](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/replace)
- [STARTS_WITH](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/starts-with)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/string-functions)
- [STRPOS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/strpos)
- [SUBSTR](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/substr)
- [SUBSTRING](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/substring)
- [UPPER](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/upper)
- [CURRENT_TIMESTAMP](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/current-timestamp)
- [DATE_TRUNC](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/date-trunc)
- [EXTRACT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/extract)
- [FORMAT_TIMESTAMP](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/format-timestamp)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-functions)
- [TIMESTAMP_MICROS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-micros)
- [TIMESTAMP_MILLIS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-millis)
- [TIMESTAMP_SECONDS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-second)
- [TIMESTAMP_TRUNC](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-trunc)
- [TO_CHAR from Timestamp](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/to-char-from-timestamp)
- [TO_TIMESTAMP](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/to-timestamp)
- [UNIX_MICROS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/unix-macros)
- [UNIX_MILLIS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/unix-millis)
- [UNIX_SECONDS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/unix-seconds)
- [IF Function](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-5-boolean-functions/boolean-functions)
- [IS DISTINCT FROM Operator](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-5-boolean-functions/is-distinct-from-operator)
- [IS NOT DISTINCT FROM Operator](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-5-boolean-functions/is-not-distinct-from-operator)
- [JSON_ARRAY_EXTRACT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-array-extract)
- [JSON_ARRAY_LENGTH](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-array-length)
- [JSON_EXTRACT_PATH](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-extract-path)
- [JSON_EXTRACT_PATH_TEXT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-extract-path-text)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-functions)
- [COALESCE](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/coalesce)
- [CURRENT_DATABASE](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/current-database)
- [CURRENT_SCHEMA](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/current-schema)
- [HAS_SCHEMA_PRIVILEGE](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/has-schema-privillege)
- [NULLIF](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/nullif)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/other-function)
- [PG_GET_EXPR](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/pg-get-expr)
- [PG_TOTAL_RELATION_SIZE](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/pg-total-relation-size)
- [PG_TYPEOF](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/pg-typeof)
- [Overview](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/sql-functions-overview)
- [Trigonometric Functions](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/trigonometric-functions)
- [Comment Support](https://docs.oxla.com/3-sql-reference/comment-support)
- [Schema](https://docs.oxla.com/3-sql-reference/schema)
- [Overview](https://docs.oxla.com/3-sql-reference/sql-reference-overview)
- [Mutation - DELETE](https://docs.oxla.com/4-sql-mutations/del-mutation)
- [Overview](https://docs.oxla.com/4-sql-mutations/sql-mutations)
- [Mutation - UPDATE](https://docs.oxla.com/4-sql-mutations/update-mutations)
- [Error Handling](https://docs.oxla.com/5-error-handling/error-handling)
- [Differences Between Oxla vs. PostgreSQL](https://docs.oxla.com/6-oxla-vs-postgre/differences-between-oxla-vs-postgre)
- [Understanding Transactions](https://docs.oxla.com/7-transactions/understanding-transactions)
- [Public Metrics](https://docs.oxla.com/8-public-metrics/public-metrics)
- [Oxla Configuration File](https://docs.oxla.com/9-oxla-config-file/oxla-configuration-file)
- [Database Files Virtual Table](https://docs.oxla.com/database_files_virtual_table)
- [Handling Oxla Degraded State](https://docs.oxla.com/degraded_state)
- [How to Connect Oxla Cloud with Looker Studio](https://docs.oxla.com/oxla-cloud-saas/how-to-connect-oxla-cloud-with-looker)
- [How to Connect Oxla Cloud with PowerBI](https://docs.oxla.com/oxla-cloud-saas/how-to-connect-oxla-cloud-with-powerbi)
- [How to Connect Oxla Cloud with TablePlus](https://docs.oxla.com/oxla-cloud-saas/how-to-connect-oxla-cloud-with-tableplus)
- [Introduction to Oxla Cloud](https://docs.oxla.com/oxla-cloud-saas/introduction-to-oxla-cloud-saas)
- [Quickstart - Oxla SaaS](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas)
- [eCommerce Dataset](https://docs.oxla.com/oxla-datasets/ecommerce-dataset)
- [Introduction](https://docs.oxla.com/oxla-datasets/introduction-datasets)
- [Social Media Dataset](https://docs.oxla.com/oxla-datasets/socialmedia-dataset)
- [Urban Mobility Dataset](https://docs.oxla.com/oxla-datasets/urbanmobility-dataset)
- [Web Traffic Dataset](https://docs.oxla.com/oxla-datasets/webtraffic-dataset)
- [pg_attrdef](https://docs.oxla.com/pg_attrdef)
- [pg_constraint](https://docs.oxla.com/pg_constraint)
- [pg_depend](https://docs.oxla.com/pg_depend)
- [pg_description](https://docs.oxla.com/pg_description)
- [pg_index](https://docs.oxla.com/pg_index)
- [pg_namespace](https://docs.oxla.com/pg_namespace)
- [pg_settings](https://docs.oxla.com/pg_settings)
- [pg_statio_user_tables](https://docs.oxla.com/pg_statio_user_tables)
- [Welcome](https://docs.oxla.com/welcome): Discover everything you need to know about Oxla right here, right now!


# Key Concepts & Architecture



Oxla enables data processing, analytics, and storage solutions that are easily scalable, highly reliable, cheaper, easier to use, and faster than the other OLAP solutions.&#x20;

We are an advanced distributed analytical database with robust analytical processing. We store data using several file systems, such as AWS S3, Ceph, and GCS.&#x20;

<img className="block dark:hidden" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/key-concept-archi-logo-light.png" alt="Hero Light" />

<img className="hidden dark:block" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/key-concept-archi-logo-dark.png" alt="Hero Dark" />

Oxla is designed to support analytical query workloads, also known as Online Analytical Processing (OLAP). These workloads are complex queries that analyze a stored dataset, such as joins between numerous extensive databases or aggregations across large tables.

The current build of the Oxla database allows users to import data using .csv and run SQL queries using CLI with various supported clauses, data types, and functions.

# Oxla Architecture

Oxla has a uniform architecture that contains the node leader that can distribute workloads equally among replicas and partitions. Data can be processed directly from data warehouses into the OLAP database management system without going through the terminal messaging cluster. Our cutting-edge technology allows users to process data faster with less infrastructure. Users will be able to request data using queries and receive data in real time.&#x20;

Oxla’s unique architecture uses the Dynamic Oxla cluster in the query processing layer. This cluster can expand and shrink dynamically depending on the analytical demand for data processing. Within the cluster, a node leader coordinates activities across Oxla. It performs key activities such as authentication, query parsing, optimization, etc. Our architecture consists of two layers, **query processing**, and a **database storage layer**. We separate the computing layer, *a.k.a* query processing layer, with the database storage layer to provide our customers greater flexibility and cost savings for big data and advanced analytics.

![Architecture](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/Key%20Concepts%20&%20Architecture_architecture.png)

## Example Use Cases Benefits:

Let’s say a large corporation wants to improve the customer journey by driving insights and running more queries/analyses from their existing customer’s data, such as purchase transactions, social data, etc. They need to process and transform a large amount of data in real-time resulting in the need to improve the computing power and not the storage. In this use case, our decoupled storage and compute design will benefit the corporation since they only need to upgrade the query processing and not include the database storage. &#x20;

### 🔑 Our Key Benefits:

1.  No need for external metastore.

2.  No need for a queue for batching insertions.

3.  Simpler deployment and maintenance.

4.  Fewer people are needed to manage and maintain the database, which results in cheaper labor costs.

## Oxla Cluster

Our Dynamic Oxla cluster technology allows you to store and run SQL queries faster with less cost. There are two main components in our cluster:

*   **Node leader:** the component that distributes the workload to run the SQL queries to all the worker nodes and appoints any node to store the data.

*   **Worker node:** the component that executes the SQL queries and stores the data.

<Info>There shall be always a single node per machine.</Info>

![cluster](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/Key%20Concepts%20&%20Architecture_cluster.png)

## Our Main Differentiator

### ⚡️ High Availability (No Single Point of Failure)

If the node leader fails, the cluster can appoint one of the worker leaders to be the new node leader. It allows you to run SQL queries with high availability and redundancy.

### 💨 Fast Query Processing

Oxla performs query execution using our query engine. Our database technology was specifically designed for big data analytics. Four critical aspects within our architecture allow us to run the queries faster than other solutions, they are:

**Self-contained architecture**

Our architecture only needs distributed storage as the external component. It does not require other additional components such as distributed message queue, external metastore, etc. Oxla processes the queries using the worker nodes that the node leader leads. When a client app wants to initiate a query request, it connects to any node within our cluster.

Once connected, it will send an SQL query request containing a string with SQL query. The node leader will parse the string and create an execution plan. This execution plan will then get distributed to all the worker nodes to execute the query.&#x20;

Each worker node is an independent compute node that does not share compute resources with other worker nodes. It allows each worker node to efficiently execute the query without impacting others. It provides high availability and redundancy with no single point of failure.&#x20;

![self contained architecture](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/Key%20Concepts%20&%20Architecture_self-contained-architecture.png)

**The radically vectorized query engine**

Big Data usually contains very complex and high volumes of data. It usually has workloads with queries that touch across a subset of columns but a large number of rows for those columns. Our vectorized query engine can perform complex computations faster than the traditional database.

**"JOIN" and "GROUP BY" improved algorithms**

Oxla is designed explicitly with improved “JOIN“ and “GROUP BY“ algorithms using custom data structures optimized for highly optimized lookups. Our hashmap implementation has better performance in typical SQL query operations. It reduces the lookup time and allows a faster response.

**All-level code optimizations**

We have designed our technology from scratch to provide the best solutions for big data analytics. We performed a holistic improvement and approach to design and develop the entire technology resulting in fast query processing time and fewer data storage for big data analytics.

### 🔋 Efficient Data Storage

Our Oxla cluster technology automatically selects and detects which worker node should be responsible for handling data insertion. Combining it with our unique data insertion algorithm, our users will be able to:

*   Handle large amounts of data insert operations;

*   Store large amounts of data efficiently, which results in lesser data storage and cheaper cost;

*   Provide data resiliency if any node fails.

Oxla stores data in optimized columnar format whenever the users load data into Oxla. The typical data warehouse solutions require users to insert data in large batches. Our technology enables users to insert large amounts of data even with single rows.&#x20;

<Check>We handle all key aspects of data storage, including file organization, compression, structure, and database metastore.</Check>

### 💸 Cheaper Cost

The typical OLAP solutions require terminal messaging clusters such as Kafka to distribute workloads. Each cluster usually comprises more than one Broker to maintain load balance. Maintaining the cluster state requires additional ZooKeeper, another infrastructure to maintain.&#x20;

Our Oxla cluster and data insertion technologies already provide efficient distribution workload technology to distribute workloads among the worker nodes. It eliminates the need for both Kafka clusters and ZooKeeper. Ultimately, you will save the cost of purchasing these infrastructures and reduce the man-hour cost of maintaining them by using our solution.

![database structure comparison](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/Key%20Concepts%20&%20Architecture_database-structure-comparison.png)

### 👩🏻‍💻 Improved Scalability

Our Oxla cluster is also dynamic, allowing you to scale quickly without having the hassle of upgrading the data warehouse whenever you want to store more data or run more queries for your business. Our cluster will automatically expand or shrink depending on the number of queries or data you store.&#x20;

**For example,** from 9 AM to 5 PM, when your data analyst runs a lot of queries, our cluster will expand to cover the needs of more analytical power. After 5 PM, when there are not that many queries to do, our cluster will shrink back to adjust. This flexibility will save you time and cost in managing the database infrastructure

# **Did You Know…?**

Oxla was designed and written from scratch, we explored and analyzed why organized data is important to accelerate business outcomes with rapid comprehension and reach the maximum edge of your potential in data and analytics.&#x20;

At Oxla, we use big data analytics and approach the speed of commercial database management systems while scaling to the size of your business.

> ***Fast, Trustworthy, Cost-Effective… That’s Us!***

🙋🏻‍♂️ Data has never been more important. Get in touch with [us](https://www.oxla.com/contact)


# OLTP vs OLAP



This article explains the differences between OLTP and OLAP technology. It helps you to further understand the use cases of our technology and why we chose OLAP for data analysis.

## What is OLTP?

### Definition

Online Transaction Processing, shortly known as OLTP, supports transaction-oriented applications under a 3-tier architecture (could be a [3NF](https://en.wikipedia.org/wiki/Third_normal_form) approach). OLTP usually administers day-to-day transactions through a relational database.

<Check>The main purpose is data processing and not data analysis. </Check>

### Usage Examples

OLTP usage can be found in every consumer-market approach. Some of the daily use cases for transactional processing are as follows:

*   **Payment:** using a debit or credit card, online or offline payment.

*   **Online Transaction**: any reservation, ticketing, and booking system which requires the OLTP methods.

*   **ATM and Online Banking**: cash withdrawals or online banking operations represent simple day-to-day transactions.

*   **Record Entry**: store data like a student’s score record, products in the warehouse, or customer service ticketing systems requiring fast-paced management.&#x20;

*   and many more…💨

## What is OLAP?

### Definition

OLAP stands for Online Analytical Processing and provides data analysis for business decisions. With OLAP, users can get information on multiple databases and data types with the ability to analyze them at the same time, even with complex queries.

<Check>The main objective is data analysis and not data processing.</Check>

### Usage Examples

OLAP method can be found in every part of business, especially in data analytics. Some of the usage examples are:

*   **Niche:** it can be seen on a personalized homepage, on the e-commerce page, movie streaming app, and on any other platform that fits users' unique needs or preferences.

*   **Sales Analytic:** usually used to compare sales in a different period which is stored in separate databases.

*   **Customer Behavior:** helps in determining customer behavior in some industries.

*   **Trend Analysis:** provide statistical analysis across several sectors to assist in decision-making.

*   and many more…💨

<Note>**Did you know?🧐** <br /> The Microsoft Excel and Microsoft SQL Server's Analysis Services are also using OLAP features!</Note>

## OLTP & OLAP Comparison

The table below outlines the main differences between OLTP & OLAP:

| **Parameters**             | **OLTP**                                                          | **OLAP**                                                                    |
| -------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------- |
| **Stands for**             | Online Transactional Processing                                   | Online Analytical Processing                                                |
| **Process**                | A transactional mechanism for controlling database modifications. | Online analysis and data retrieving process.                                |
| **Characteristic**         | Large numbers of online transactions characterize it.             | A large volume of data characterizes it.                                    |
| **Method**                 | Traditional DBMS.                                                 | Data warehouse.                                                             |
| **Database normalization** | Normalized                                                        | Unnormalized or denormalized                                                |
| **Operation**              | `INSERT`, `DELETE` and `UPDATE` commands.                         | Mostly `SELECT` operations.                                                 |
| **Response Time**          | Milliseconds                                                      | Seconds to minutes (It depends on the data amount that has to be processed) |
| **Storage size**           | Small database                                                    | Large database                                                              |
| **Response**               | It offers quick results for frequently utilized data.             | It offers a consistently faster response to requests.                       |
| **Audience**               | Market-oriented information.                                      | Customer-oriented information.                                              |

### 🆚 OLAP vs. OLTP: Key Differences

*   OLAP analyzes data stored in a database, while OLTP supports transaction-oriented operations.

*   OLAP handles all business and data analysis, while OLTP is usually used to administer daily transactions.&#x20;

*   OLAP can integrate different data sources, while OLTP uses traditional DBMS.

## Conclusion

The OLTP and OLAP, both, deal with information in their discipline. While OLTP is useful for business operations, OLAP is advantageous for analyzing data and providing important information for a business’ growth.&#x20;

We certainly want significant business growth, and OLAP is a system you should consider. One of the finest recommended database management systems which can help is Oxla. Oxla will help you achieve your goal with a fast-distributed analytical database and robust analytical processing! 🚀


# Our Key Features



This article lists our prominent features supported in the current release:

## Data Storage, Import & Export

*   A distributed storage system that provides high availability and redundancy.
*   Support for large data loading and unloading into/out of tables.
*   Exporting/ importing data from .csv files.
*   Decoupled storage and computing.
*   Internal metastore detection to provide information about the database

## Integration

*   Connect Oxla to external data sources with JDBC.
*   Support PostgreSQL library.
*   We are fully integrated with Amazon S3 storage

## Supported SQL

| **Name**           | **Description**                                                                                                                     | **Example**                                                                                                                                                                |
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SELECT`&#xA;&#xA; | The `SELECT` statement is used to select data from a database. The data returned is stored in a result table called the result set. | The following query will select all the columns from the **Products** table:&#xA;`SELECT * FROM Products;`                                                                 |
| `INSERT INTO`      | The `INSERT INTO` query adds new rows to an existing table using a `SELECT` statement or explicitly stating input values.           | `INSERT INTO distance_table (distance, unit) VALUES (2000, 'kilometers'), (1000, 'meters'), (5, 'miles');`                                                                 |
| `DROP`             | The` DROP` statement is used to delete objects like an existing database or table.&#xA;                                             | The following query will delete a table named **testTB**: `DROP TABLE testTB;` <br /> The following query will delete a database named **testTB**: `DROP DATABASE testDB;` |
| `CREATE TABLE`     | The `CREATE TABLE `statement is used to create a table in a database with a defined column and each column's data type.             | `CREATE TABLE book (bookID int, bookTitle text, bookCategory text, bookPublisher text, bookPages int;)`                                                                    |
| `CREATE INDEX`     | The `CREATE INDEX`  is used to create a single index on an empty table.                                                             |                                                                                                                                                                            |
| `SHOW TABLES`      | The `Show` statements allow you to obtain information about existing tables.                                                        | `SHOW TABLES;`                                                                                                                                                             |
| `DESCRIBE`         | The `Describe` statement show columns within a table and tables within a database.                                                  | `DESCRIBE TABLE part;` <br /> `DESCRIBE DATABASE;`                                                                                                                         |
| `SHOW NODES`       | The `SHOW NODES` returns the current state of the cluster.                                                                          | `SHOW NODES;`                                                                                                                                                              |
| `SET/SHOW`         | The `SET` statement lets you set specific options, and the `SHOW` statement helps you see the current values in Oxla.               | `SET extra_float_digits TO 2;``SHOW timezone;`                                                                                                                             |
| `COPY FROM`        | The `COPY FROM` statement copies the data from a file into a table.                                                                 | `COPY table_name FROM 'file_path'`                                                                                                                                         |
| `COPY TO`          | The `COPY TO` statement is used to export tables, specific columns, or results of select queries into .csv files.                   | `COPY salary TO '/path/to/exportsalary.csv';`                                                                                                                              |

## SQL Syntax

### Supported Clauses

| **Name**       | **Description**                                                                                                                                                                                                                                       | **Example**                                                                                                                                   |
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `FROM`         | The `FROM` clause can return a row set, a table, or a function from any ‘join’ statement.                                                                                                                                                             | `SELECT * FROM cars;`                                                                                                                         |
| `JOIN`         | A `JOIN` clause combines records from two or more tables based on a related column between those tables.                                                                                                                                              | `SELECT Orders.OrderID, Customers.CustomerName, Orders.OrderDate FROM Orders JOIN Customers ON Orders.CustomerID=Customers.CustomerID;`       |
| `LEFT JOIN`    | The `LEFT JOIN` joins two or more tables, returns all records from the left table, and matches records from the right table that fulfill the specified join condition. It will return null if there is no matching record from the right table.       | `SELECT Customers.CustomerName, Orders.OrderID FROM Customers LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID`                   |
| `RIGHT JOIN`   | The `RIGHT JOIN` joins two or more tables and returns all records from the right table and the matched records from the left table that fulfill the specified join condition. It will return null if there is no matching record from the left table. | `SELECT Orders.OrderID, Employees.LastName, Employees.FirstName FROM Orders RIGHT JOIN Employees ON Orders.EmployeeID = Employees.EmployeeID` |
| `OUTER JOIN`   | The `OUTER JOIN` joins and returns matched and unmatched values from either one or both tables.                                                                                                                                                       | `SELECT Customers.customerName, Orders.orderID FROM Customers OUTER JOIN Orders ON Customers.customerID=Orders.customerID`                    |
| `WHERE`        | The `WHERE` clause is used to filter records from a single table or by joining with multiple tables that fulfill the specified condition.                                                                                                             | `SELECT * FROM Customers WHERE Country='France';`<br />`SELECT * FROM Customers WHERE CustomerID=1;`                                          |
| `GROUP BY`     | The `GROUP BY` clause groups rows with the same values into summary rows.                                                                                                                                                                             | `SELECT COUNT(CustomerID), Country FROM Customers GROUP BY Country;`                                                                          |
| `HAVING`       | The `HAVING` clause is used to filter data according to the conditions provided. The `HAVING` clause is usually executed with the `GROUP BY` clause.                                                                                                  | `SELECT Department, sum(Salary) as Salary FROM employee GROUP BY department HAVING SUM(Salary) >= 50000; `                                    |
| `ORDER BY`     | The `ORDER BY` sorts the rows of the result set from a SELECT statement.                                                                                                                                                                              | `SELECT emp_name, emp_div FROM salaryemp ORDER BY emp_div;`                                                                                   |
| `LIMIT`        | The `LIMIT` clause is an optional clause of the `SELECT` statement that constrains the number of rows the query returns.                                                                                                                              | `SELECT order_id, prod_name, prod_price FROM comporders ORDER BY order_id LIMIT 4;`                                                           |
| `OFFSET`       | The `OFFSET` is a clause that skips some records from the result set.                                                                                                                                                                                 | `SELECT * FROM oxlafunctions ORDER BY func_name LIMIT 5 OFFSET 2;`                                                                            |
| Set Operations | Set operations are used for comparisons, combinations, and distinctions among sets.                                                                                                                                                                   | It includes the following operations: `UNION`, `EXCEPT`, `INTERSECT`.                                                                         |

### Supported Datatypes

| **Data Types**                | **Definition**                                             | **Format**                                     |
| ----------------------------- | ---------------------------------------------------------- | ---------------------------------------------- |
| `BOOL`                        | Boolean value.                                             | `True` or `False`.                             |
| `TEXT`                        | UTF8 encoded string with Unicode support.                  | 'text'                                         |
| `DATE`                        | Date value.                                                | `YYYY-MM-DD`                                   |
| `TIMESTAMP WITHOUT TIME ZONE` | Time and date values without a time zone.                  | `YYYY-MM-DD [HH:MM:SS[.SSSSSS]]`               |
| `TIMESTAMP WITH TIME ZONE`    | Date and time values, including the time zone information. | `YYYY-MM-DD HH:MM:SS.SSSSSS+TZ`                |
| `TIME`                        | Time values without any date information.                  | `HH:MM:SS[.SSSSSS]`                            |
| `JSON`                        | A value in JSON standard format.                           | `variable_name JSON`                           |
| `INTERVAL`                    | Encodes a span of time                                     | `year-month (YYYY-MM); day-time (DD HH:MM:SS)` |
| `INT`                         | 32-bit signed integer                                      | one or more digits "0" to "9"                  |
| `BIGINT`                      | 64-bit signed integer                                      | large numeric/decimal value                    |
| `REAL`                        | 32-bit floating point number                               | `float(n)`                                     |
| `DOUBLE PRECISION`            | 64-bit floating point number                               | `decimal(p, s)`                                |

## Functions

### Numeric functions

| **Name**              | **Description**                                                                                                  |
| --------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `CEIL`                | This function rounds up to the nearest positive or negative integer value greater than or equal to the argument. |
| `ABS`                 | This function returns the absolute value of an argument, regardless of whether it is positive or negative.       |
| `SQRT`                | This function returns the square root of its argument.                                                           |
| `CBRT`                | The function calculates and returns the cube root of a given number.                                             |
| `RANDOM`              | This function returns a random number between 0 (inclusive) and 1 (exclusive).                                   |
| `FLOOR`               | This function returns a number rounded down that is less than or equal to the specified argument.                |
| `LN`                  | This function returns the exponential value of its argument.                                                     |
| `SIN`                 | This function returns the trigonometric sine value of a specified angle in radians.                              |
| `GREATEST`            | This function extracts the greatest or largest value from a set of values.                                       |
| `LEAST`               | This function returns the least or smallest value in a list of values.                                           |
| `ROUND`               | This function rounds numbers to the nearest integer or to a specified number of decimal places.                  |
| `EXP`                 | This function returns the exponential value of a number specified in the argument.                               |
| `LOG`                 | The function returns the base-10 logarithm or logarithm of the specified base of a given number.                 |
| `POWER`               | This function returns the value of a number raised to the power of another number specified in the arguments.    |
| `TO_CHAR` from number | This function formats a number into a string using a given format.                                               |

### Aggregation functions

| **Name**   | **Description**                                                                                                       |
| ---------- | --------------------------------------------------------------------------------------------------------------------- |
| `SUM`      | Calculates the sum of values. Input must be numeric. If the input type is 32-bit, then the result will be 64-bit.     |
| `MIN`      | Returns the smallest value. Input must be numeric.                                                                    |
| `FOR_MIN`  | Returns a value corresponding to the minimal metric in the same row from a set of values.                             |
| `MAX`      | Returns the largest value. Input must be numeric                                                                      |
| `FOR_MAX`  | Returns a value corresponding to the maximum metric in the same row from a set of values.                             |
| `AVG`      | Calculates the average of values. Input must be numeric. If the input type is 32-bit, then the result will be 64-bit. |
| `COUNT`    | Counts the number of rows.                                                                                            |
| `BOOL_AND` | False if at least one of aggregated rows is False. Input must be bool.                                                |
| `BOOL_OR`  | True if at least one of aggregated rows is True. Input must be bool.                                                  |

### String functions

| **Name**         | **Description**                                                                                                                                                                                                         |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LENGTH`         | Returns the number of characters in the string. The number of characters might be different from the byte length.                                                                                                       |
| `LOWER`          | Makes string lowercase. It supports Unicode, so *ß* is changed into *ss*.                                                                                                                                               |
| `UPPER`          | Makes string upper case. Supports Unicode.                                                                                                                                                                              |
| `STARTS_WITH`    | It returns true if the first argument starts with the second argument. E. g. `STARTS_WITH(“abc,” “ab”)` returns true.                                                                                                   |
| `ENDS_WITH`      | It returns true if the first argument ends with the second argument. E. g. `STARTS_WITH(“abc,” “bc”)` returns true.                                                                                                     |
| `CONCAT`         | Concatenates all inputs e. g. `CONCAT(123, “abc”)` returns “123abc”. Inputs might be of any type.                                                                                                                       |
| `SUBSTR`         | Retrieves substring. E. g. `SUBSTR(“abcd”, 2)` returns “cd”, `SUBSTR(“abcd”, 2, 1)` returns “c”.                                                                                                                        |
| `STRPOS`         | Returns position at which the second argument starts within the first argument or 0 if the first argument does not contain the second argument E. g. `STRPOS(“abcd”, “ab”)` return 2, `STRPOS(“abcd”, “ac”)` returns 0. |
| `REGEXP_REPLACE` | Substitutes new text for substrings that match POSIX regular expression patterns.                                                                                                                                       |
| `REPLACE`        | Finds and replaces a substring with a new one in a string.                                                                                                                                                              |
| `POSITION`       | Returns the position of the first occurrence of a substring in a string.                                                                                                                                                |

### Timestamp functions

| **Name**                 | **Description**                                                                                                                                                                                                                                     |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CURRENT_TIMESTAMP`      | Returns current timestamp.                                                                                                                                                                                                                          |
| `FORMAT_TIMESTAMP`       | Formats timestamp. Format string documentation:&#xD;&#xA;[date](https://howardhinnant.github.io/date/date.html#from_stream_formatting). Example: `FORMAT_TIMESTAMP('the date is: %F', CURRENT_TIMESTAMP())` would produce “the date is: 2022-12-19” |
| `UNIX_SECONDS`           | Converts the given timestamp to Unix timestamp in seconds.                                                                                                                                                                                          |
| `UNIX_MILLIS`            | Converts the given timestamp to Unix timestamp in milliseconds.                                                                                                                                                                                     |
| `UNIX_MICROS`            | Converts the given timestamp to Unix timestamp in microseconds.                                                                                                                                                                                     |
| `TIMESTAMP_SECONDS`      | Converts Unix timestamp in seconds to timestamp.                                                                                                                                                                                                    |
| `TIMESTAMP_MILLIS`       | Converts Unix timestamp in milliseconds to timestamp.                                                                                                                                                                                               |
| `TIMESTAMP_MICROS`       | Converts Unix timestamp in microseconds to timestamp.                                                                                                                                                                                               |
| `TIMESTAMP_TRUNC()`      | Truncates a given timestamp to the nearest time parts. Supported time parts are YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND                                                                                                                          |
| `EXTRACT`                | Extracts are given time part from Timestamp. Supported time parts are YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND. e. g. EXTRACT(YEAR FROM TIMESTAMP '2020-10-15 10:15:23') will return 2020.                                                        |
| `TO_TIMESTAMP`           | Converts a string into a timestamp based on the provided format.                                                                                                                                                                                    |
| `DATE_TRUNC`             | Truncates intervals or timestamps/time zones to a specified field.                                                                                                                                                                                  |
| `TO_CHAR` from timestamp | Formats a timestamp into a string using a given format.                                                                                                                                                                                             |

### Boolean function

| **Name** | **Description**                                                                                                                                                                |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `IF`     | Three arguments function. It expects that the first argument is of type BOOL, 2nd and 3rd has a matching type E. g. `IF(2 < 5, “smaller,” “greater”)` would produce “smaller.” |

### JSON functions

| **Name**                 | **Description**                                                                        |
| ------------------------ | -------------------------------------------------------------------------------------- |
| `JSON_EXTRACT_PATH`      | It extracts JSON sub-object at the specified path.                                     |
| `JSON_EXTRACT_PATH_TEXT` | It returns text referenced by a series of path elements in a JSON string or JSON body. |
| `JSON_ARRAY_LENGTH`      | It returns the number of elements in the outer array of a JSON string or JSON body.    |
| `JSON_ARRAY_EXTRACT`     | It returns the JSON array as a set of JSON values.                                     |

### Other functions

| **Name**                 | **Description**                                                                                                                   |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `CURRENT_SCHEMA`         | It returns the schema's name first in the search path.                                                                            |
| `CURRENT_DATABASE`       | It returns the current database's name.                                                                                           |
| `COALESCE`               | It returns the first argument that is not null, while the remaining arguments from the first non-null argument are not evaluated. |
| `NULLIF`                 | It replaces a given value with null if it matches a specific criterion.                                                           |
| `pg_total_relation_size` | It retrieves the size of a table.                                                                                                 |
| `has_schema_privilege`   | It checks whether the current user has specific privileges on a schema.                                                           |
| `pg_get_expr`            | It retrieves the internal form of an individual expression, such as the default value for a column.                               |
| `pg_typeof`              | It retrieves the data type of any given value.                                                                                    |

### Trigonometric functions

| **Functions** | **Description**                                                                                  |
| ------------- | ------------------------------------------------------------------------------------------------ |
| `acos`        | It calculates the inverse cosine of a given argument, where the output is expressed in radians.  |
| `acosd`       | It calculates the inverse cosine of a given argument, where the output is expressed in degrees.  |
| `asin`        | It calculates the inverse sine of a given argument, where the output is expressed in radians.    |
| `asind`       | It calculates the inverse sine of a given argument, where the output is expressed in degrees.    |
| `atan`        | It calculates the inverse tangent of a given argument, where the output is expressed in radians. |
| `atand`       | It calculates the inverse tangent of a given argument, where the output is expressed in degrees. |
| `atan2`       | It calculates the inverse tangent of y/x, where the output is expressed in radians.              |
| `atan2d`      | It calculates the inverse tangent of y/x, where the output is expressed in degrees.              |
| `cos`         | It calculates the cosine of a given argument, where the argument is in radians.                  |
| `cosd`        | It calculates the cosine of a given argument, where the argument is in degrees.                  |
| `cot`         | It calculates the cotangent of a given argument, where the argument is in radians.               |
| `cotd`        | It calculates the cotangent of a given argument, where the argument is in degrees.               |
| `sin`         | It calculates the sine of a given argument, where the argument is in radians.                    |
| `sind`        | It calculates the sine of a given argument, where the argument is in degrees.                    |
| `tan`         | It calculates the tangent of a given argument, where the argument is in radians.                 |
| `tand`        | It calculates the tangent of a given argument, where the argument is in degrees.                 |

<Check>We still have a long road to go. We will keep you posted with our soon-to-be-released features to boost your experience. Stay tuned!</Check>


# Oxla vs. Other OLAP Solutions



There are several different types of distributed database management systems (DBMS). But there isn't a database system that works for everyone. Each makes different compromises to suit particular situations. In this section, we attempt to explain how Oxla differs from other OLAP-using systems.

## The Comparison

The comparison tests were performed on a single node; using more nodes will significantly improve the results. Below are the detailed prototype test results on AWS between Oxla and selected alternatives *(ClickHouse, Presto, Parquet)*:

### a) Performance

| **Oxla**                                                                                                                                                                                                                                     | **ClickHouse**                                                                                      |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| Supports a lot of Clauses, Data Types, and Functions. Such as `GROUP BY`, `JOIN` (`INNER JOIN`, `LEFT JOIN`, `RIGHT JOIN`, `OUTER JOIN`). We also support uncorrelated subqueries e.g. `SELECT num, COUNT(*) as num FROM user GROUP BY age`. | Non-standard SQL-like query language with several limitations.                                      |
| Oxla has homogeneous architecture: there are no workers, data, or master nodes. One of the nodes is dynamically selected as the leader with no single point of failure.                                                                      | On-premise with dedicated clusters, no elasticity. We need to migrate into bigger/smaller clusters. |

### b) Cost

| **Oxla**             | **ClickHouse**      |
| -------------------- | ------------------- |
| \$0.023 per GB/month | \$0.24 per GB/month |

## Conclusion

Our tests show that Oxla's performance surpasses all other distributed database management systems with the following results:

*   Oxla processes a large number of data at an extremely high data processing speed.

*   Oxla can reduce 80% of data infrastructure costs compared to the others.

*   Oxla will not be affected by the massive data you have. The storage (RAM) needed will stay low with a small cost you pay.

![comparison](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/Oxla%20vs%20Other%20OLAP%20Solution_comparison.png)

## Now What?

Understanding Oxla and then comparing it with other solutions made us realize that there are a lot of choices in today’s database market - but in the end, there will be only one .

We suggest you take a step back and evaluate your products, team talents, market, and needs before deciding what to use for your business. Choosing the right technology today can make a huge difference now and in the future.

<Tip>Choose an architecture that will grow with you rather than one that makes you start over.</Tip>

We, at Oxla, will be super pleased to support you in achieving your goal with our dazzling distributed DBMS ✨

**Are you curious about Oxla? Contact [us](https://www.oxla.com/contact)**


# C# Dapper - Npgsql



## Overview

[Dapper](https://dappertutorial.net/) is a simple object-relational mapper (ORM) for .NET. It provides an easy and efficient way to query databases with minimal setup and overhead, leveraging SQL directly while mapping results to C# objects. This page describes how to use Dapper with [Npgsql](https://www.npgsql.org/) (a PostgreSQL data provider for .NET) to connect to Oxla.

## Establishing connection

There are two ways that can be utilised in order to establish a connection through [Npgsql](https://www.npgsql.org/):

*   **Npgsql's DataSource Class**

```C#
var connectionString = "Server=127.0.0.1:5432;Username=user;Password=password;Database=db;";
var dataSource = NpgsqlDataSource.Create(connectionString);
var connection = dataSource.OpenConnection();
```

*   **Creating Connection Directly**

```C#
var connectionString = "Server=127.0.0.1:5432;Username=user;Password=password;Database=db;";
var connection = new NpgsqlConnection(connectionString);
connection.Open();
```

For more details on connection string options, including SSL configuration, please refer to [Npgsql docs](https://www.npgsql.org/doc/connection-string-parameters.html).

## Example Usage

This example shows basic query execution for the following C# class, once the connection has been established:

```C#
public class Customer
{
    public int ClientId { get; set; }
    public double Height { get; set; }
    public string FirstName { get; set; }
}
```

```C#
connection.Execute("CREATE TABLE Customer (ClientId INTEGER, Height DOUBLE, FirstName TEXT)");

var customer = new Customer{ClientId = 1, Height = 3.14, FirstName = "John"};
connection.Execute("INSERT INTO Customer VALUES (@ClientId, @Height, @FirstName)", customer);

var customers = connection.Query<Customer>("SELECT * FROM Customer");
foreach(var c in customers)
{
    Console.WriteLine($"Customer #{c.ClientId}: {c.FirstName} is {c.Height} tall.");
}
```

<Warning>`INSERT INTO Customer VALUES (@ClientId, @Height, @FirstName)` syntax uses prepared statements under the hood, which are not supported by Oxla. We translate incoming binary input back into string, thus no benefits of such statements apply (no security or performance improvements)</Warning>

## Unsupported Functions & Structures

Here you can find a list of functions and potentially related structures, that we either do not support at all or they work incorrectly when combining Oxla and Dapper-Npgsql:

*   `connection.Execute` - returns improper number of rows for `DELETE`, `UPDATE`, `INSERT INTO ... (SELECT)` and `COPY` statements
*   `connection.BeginTransaction` - [Transactions](https://www.npgsql.org/doc/basic-usage.html#transactions)
*   `CommandType.StoredProcedure` - [Stored Procedures](https://www.npgsql.org/doc/basic-usage.html#stored-functions-and-procedures)
*   [Function in/out parameters](https://www.npgsql.org/doc/basic-usage.html#function-inout-parameters)


# JAVA JDBC



## Overview

[Java Database Connectivity (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) is an application programming interface (API) for the Java programming language which defines how a client may access a database. It is a Java-based data access technology used for Java database connectivity, which supports PostgreSQL protocol implemented in Oxla and provides consistent interface for accessing databases in Java or Kotlin. This page and its sections describe how to use Kotlin JDBC with Oxla and also lists unsupported functions and structures.

## Establishing connection

```Kotlin
    /**
     * @brief Establishes connection to a database at a given address and port.
     * @param address Address at which database is located (Can be in URL, IPv4 or IPv6 format).
     * @param port Port at which database is located (in [0, 65535] range).
     * @param databaseName Name of the database to connect to.
     * @param user (optional) Name of a user to connect as.
     * @param password (optional) Password of the given user.
     * @return Result containing a Connection object if connection was established successfully, otherwise Result(Failure) with an error message.
     */
    fun connect(
        address: String,
        port: Int,
        databaseName: String,
        user: String? = null,
        password: String? = null
    ): Result<Connection> {
        if (port !in 0..65535) {
            return Result.failure(IllegalArgumentException("Port must be in 0 - 65535 range."))
        }
        try {
            return Result.success(DriverManager.getConnection("jdbc:postgresql://$address:$port/$databaseName", user, password))
        } catch (e: SQLException) {
            return Result.failure(SQLException("Failed to establish connection to a database, because: $e"))
        } catch (_: SQLTimeoutException) {
            return Result.failure(SQLTimeoutException("Failed to establish connection to a database. Request timed out."))
        }
    }
```

<Info> Support for SSL/TLS is not mandated in the JDBC specification. So you cannot expect it in every driver. </Info>

## Example usage

This example shows basic query execution, once the connection has been established:

```
val statement: Statement = connection.createStatement()
statement.queryTimeout = QUERY_TIMEOUT
val query: String = "SELECT $columnName FROM $table"
try {
    // Execute the query and...
    val result: ResultSet = statement.executeQuery(query). also {
        // ... print the results.
        while (it.next()) {
            println(it.getString(1))
        }
    }     
} catch (e: SQLException) {
    System.err.println("Failed to execute the following query: $query, error: $e")
}
```

## Unsupported Functions & Structures

Here you can find a list of functions and potentially related structures, that we currently do not support when working with Oxla and Kotlin JDBC:

*   `JDBC.Connection`, [createArrayOf](https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#createArrayOf-java.lang.String-java.lang.Object:A-)
*   `JDBC.Connection`, [getTransactionIsolation](https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#getTransactionIsolation--)
*   `JDBC.Connection`, [prepareStatement with intArray (JDBC does not support)](https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#prepareStatement-java.lang.String-int:A-)
*   `JDBC.Connection`, [setSavepoint](https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#setSavepoint--)
*   `JDBC.Connection`, [setTransactionIsolation](https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#setTransactionIsolation-int-)
*   `JDBC.ResultSet`, [deleteRow](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#deleteRow--)
*   `JDBC.ResultSet`, [insertRow](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#insertRow--)
*   `JDBC.ResultSet`, [refreshRow](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#refreshRow--)
*   `JDBC.ResultSet`, [updateRow](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#updateRow--)
*   `JDBC.ResultSet`, [moveToCurrentRow](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#moveToCurrentRow--)
*   `JDBC.ResultSet`, [moveToInsertRow](https://docs.oracle.com/javase/8/docs/api/java/sql/ResultSet.html#moveToInsertRow--)
*   `JDBC.Statement`, [RETURN\_GENERATED\_KEYS](https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#RETURN_GENERATED_KEYS)
*   `JDBC.Statement`, [invalid autoGeneratedKeys (JDBC does not throw)](https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#executeUpdate-java.lang.String-int-)
*   `JDBC.Statement`, [execute witch intArray (JDBC does not support)](https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#execute-java.lang.String-int:A-)
*   `JDBC.Statement`, [cancel (issues after cancel)](https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#cancel--)
*   `JDBC.PreparedStatement`, [setDate](https://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html#setDate-int-java.sql.Date-)
*   `JDBC.PreparedStatement`, [setObject](https://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html#setObject-int-java.lang.Object-)
*   `JDBC.PreparedStatement`, [setString(1, PGInterval("1 day").toString())](https://docs.oracle.com/javase/8/docs/api/java/sql/PreparedStatement.html#setString-int-java.lang.String-)


# PHP PDO



## Overview

[The PHP Data Objects (PDO)](https://www.php.net/manual/en/book.pdo.php) is an extension, which supports PostgreSQL protocol implemented in Oxla and provides consistent interface for accessing databases in PHP. This page and its sections describe how to use PHP PDO with Oxla and also lists unsupported functions and structures.

## Establishing connection

```PHP
conn = new PDO(
    "pgsql:host={oxla_host};port={oxla_port};dbname=oxla",
    {oxla_user},
    {oxla_password},
    [ 
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => true,
    ]);
```

Note that the `PDO::ATTR_EMULATE_PREPARES` attribute is set to `true`, which is required in Oxla to ensure stability of query execution. Without this attribute setup, you may encounter `prepared statement` errors during queries execution:

```
    ERROR: prepared statement [...]
```

<Info> If you are running Oxla Cloud, you can append <code>`sslmode=verify-full;sslrootcert=\{path to ssl cert from SaaS\}`</code> to the first parameter of <code>PDO</code> to ensure full SSL endpoint verification and encryption. </Info>

## Example usage

This example shows basic query execution, once the connection has been established:

```
$stmt = $conn->prepare("SELECT :number as num;", [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
$stmt->execute(['number' => 1234]);
$res = $stmt->fetchAll();
print_r($res)
```

## Unsupported Functions & Structures

Here you can find a list of functions and potentially related structures, that we currently do not support when working with Oxla and PHP PDO:

*   `PDO::pgsqlLOBCreate`, `pgsqlLOBOpen` - [Large Objects](https://www.postgresql.org/docs/current/largeobjects.html)
*   `PDO::pgsqlGetPid` - [returning processes ID](https://www.php.net/manual/en/function.pg-get-pid.php)
*   `PDO::pgsqlCopytFromFile`, `PDO::pgsqlCopytFromArray` - [copy from STDIN](https://www.postgresql.org/docs/current/sql-copy.html)
*   `PDO::pgsqlCopytToFile` - [copy to STDIN](https://www.postgresql.org/docs/current/sql-copy.html)
*   `PDO::pgsqlCopytToArray` - [copy to STDOUT](https://www.postgresql.org/docs/current/sql-copy.html)
*   `PDO::pgsqlGetNotify` - [`LISTEN`](https://www.postgresql.org/docs/current/sql-listen.html) and [`NOTIFY`](https://www.postgresql.org/docs/current/sql-notify.html) channel commands
*   `PDO::lastInsertId` - [SEQUENCES](https://www.postgresql.org/docs/current/sql-createsequence.html)
*   `PDO::beginTransaction`, `PDO::inTransaction`, `PDO::commit`, `PDO::rollBack` - [Transactions](https://www.postgresql.org/docs/current/tutorial-transactions.html)
*   `PDOStatement::rowCount` - returns improper number of rows for `DELETE`, `UPDATE`, `INSERT INTO ... (SELECT)` and `COPY` statements


# Data Task Stability



## Overview

The `oxla_data_task_stability` table provides information about the stability of data tasks for tables within Oxla.

*   Data tasks are background processes responsible for normalizing and maintaining data layouts.
*   The stability status indicates whether the table's files have been processed and are up-to-date.

## Example

1.  Run the following command:

```sql
SELECT * FROM oxla_internal.oxla_data_task_stability;
```

2.  Here’s an example of the output you might see:

```sql
 table_id | namespace_id | database_id | is_stable 
----------+--------------+-------------+-----------
    16384 |            0 |           0 | t
(1 row)
```

**Table schema**

| Column Name    | Data Type | Constraints | Description                                                                                                                                                                                                                                        |
| -------------- | --------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `table_id`     | `BIGINT`  | `NOT NULL`  | Unique identifier for the table                                                                                                                                                                                                                    |
| `namespace_id` | `BIGINT`  | `NOT NULL`  | Identifier for the namespace that the table belongs to                                                                                                                                                                                             |
| `database_id`  | `BIGINT`  | `NOT NULL`  | Identifier for the database where the table is located                                                                                                                                                                                             |
| `is_stable`    | `BOOL`    | `NOT NULL`  | Indicates the state of the data task. `false` means the files are either being processed or queued for processing. `true` means the files have been processed and are stable, and this state persists until the user updates the data in the table |

<Note>You can join the `table_id`, `namespace_id`, and `database_id` columns with other virtual tables to obtain human-readable names for the table, namespace, and database.</Note>


# Multi-node Deployment



Over the following steps, we'll show you how to set up and deploy Oxla multi-node database. Let’s get started!

<Info>In this tutorial, we will show you how to deploy Oxla with three nodes. If you want to deploy more than that, simply update and adjust the yaml configuration per tutorial below.</Info>

## Prerequisite

⚠️ There shall be always a single node per machine.

⚠️ Install Docker. Please refer to [this page](https://docs.docker.com/engine/install/) for further details.

⚠️ x86 64bit CPU (Intel or AMD).

⚠️ Install PostgresSQL-client-14 for psql connection. Please refer to [this page](https://www.postgresql.org/download/).&#x20;

⚠️ Grab N machines with ssh access to them. The N number refers to the number of nodes that you want to deploy.

⚠️ Configure the networking so that all nodes can connect to each other.

## Installation on Each Node

*   Open your terminal command and execute this command to check if you have installed your docker properly.

```dockerfile
docker ps
```

<Note>If it returns “Bad response from Docker engine”, this means there is an issue with your docker engine. Try re-install your docker.</Note>

*   Execute the following command to create a file that contains docker compose file:

```dockerfile
vim multi_node.yml
```

*   Input the following code into the docker compose file for **each node**:

```dockerfile
version: '3.5'

volumes:
  oxla_data:

services:
  oxla_node:
    image: public.ecr.aws/oxla/release:latest
    security_opt:
      - seccomp:unconfined
    ulimits:
      nofile:
        soft: 40000
        hard: 40000
    ports:
      - 5432:5432
    environment:
      - FORCED_REVOKE_TIMEOUT_MS=1500
      - BUFFER_TIMEOUT=1
      - HOST_NAME=oxla_node_1
      - OXLA_NODES=192.168.0.1;192.168.0.2;192.168.0.3
      - OXLA_HOME=s3://yourdirectoryname
      - AWS_DEFAULT_REGION=AWS_DEFAULT_REGION
      - AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY
```

<Info>Don’t forget to replace the following values with appropriate values: <br /> - 192.168.0.1; 192.168.0.2; 192.168.0.3 <br /> - s3://yourdirectoryname <br /> - AWS\_DEFAULT\_REGION <br /> - AWS\_ACCESS\_KEY\_ID <br /> - AWS\_SECRET\_ACCESS\_KEY</Info>

<Warning>Please ensure you the three machines that you are using to deploy Oxla is connected in a same network.</Warning>

<Check>Depending on your computer's RAM capacity, you may need to adjust the environment variable to optimize performance. You can set `OXLA_MAX_NON_QUERY_MEM` to a custom number. <br /> For example `OXLA_MAX_NON_QUERY_MEM=4194304`</Check>

*   Execute the following command to create and start the docker container:

```dockerfile
docker compose -f multi_node.yml up
```

*   Execute the following command to run Oxla:

```dockerfile
psql -h IP_ADDRESS
```

<Info>Please replace `IP_ADDRESS` with one of the IP addresses that you setup in your yaml file. If you encounter an error response “bash: psql: command not found“, this means that you have not installed PostgreSQL.</Info>

<Warning>Please ensure that you repeat all of the steps above on all of the nodes.</Warning>


# Run Oxla in 2 minutes



## Prerequisites

*   x86 64bit CPU (Intel or AMD)
*   Linux OS
*   Docker
*   PostgreSQL Client

## Installation

In order run Oxla in no time, you need to have Docker and PostgreSQL client installed on your local machine. To do that, you need to follow their installation guides, that you can find below:

*   [Docker](https://docs.docker.com/engine/install/)
*   [PostgreSQL Client](https://www.postgresql.org/download/linux/ubuntu/)

## Docker Setup

Once you're done with installation part, you can open your terminal and execute following command to check if you have installed your Docker instance properly:

```dockerfile
docker ps
```

<Info>If it returns “Bad response from Docker Engine”, it means there is an issue with your Docker instance and you need to try re-installing it.</Info>

Then you need to start Oxla Docker instance and expose PostgreSQL port:

```dockerfile
docker run --rm -it -p 5432:5432 public.ecr.aws/oxla/release:latest
```

<Note>In case of getting an error message about port 5432 being occupied, you need to adjust the above command to utilise a different port (6000 can be used here)</Note>

## Connecting to Oxla

Once that is done, you can now effectively connect to Oxla by executing one of the following commands, depending on the port you used before:

```dockerfile
psql -h localhost
```

```dockerfile
psql -h localhost -p 6000
```

<Note>If you encounter “bash: psql: command not found“ error response, this means that you have not installed PostgreSQL client properly on your machine and you need to try reinstalling it</Note>


# Run Oxla on Azure Blob Storage



Over the following steps, we’ll set you up with an Oxla server using the Azure Blob Storage.

## Prerequisite

⚠️ Install Docker. Please refer to [this page](https://docs.docker.com/engine/install/) for further details.
⚠️ We recommend you use a Linux OS computer to deploy an Oxla server.
⚠️ Install PostgresSQL-client-14 for psql connection. Please refer to [this page](https://www.postgresql.org/download/).&#x20;

## Installation Steps

1.  Open your terminal and execute this command to check if you have installed your docker properly:

```typescript
docker ps
```

<Note>If it returns “Bad response from Docker engine”, this means there is an issue with your docker engine. Try re-install your docker.</Note>

2.  Execute the following command to create a file that contains docker compose file:

```typescript
vim one_node.yml
```

3.  Input the following code into the docker compose file:

```typescript
version: '3.5'
volumes:
  oxla_data:
services:
  oxla_node:
    image: public.ecr.aws/oxla/release:latest
    security_opt:
      - seccomp:unconfined
    ulimits:
      nofile:
        soft: 40000
        hard: 40000
    volumes:
      - oxla_data:/data
    ports:
      - 5432:5432
    environment:
      - AZURE_ACCOUNT_NAME=${AZURE_ACCOUNT_NAME?err}
      - AZURE_TENANT_ID=${AZURE_TENANT_ID?err}
      - AZURE_CLIENT_ID=${AZURE_CLIENT_ID?err}
      - AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET?err}
```

4.  Execute the following command to create and start the docker container:

```typescript
docker compose -f one_node.yml up
```

5.  Execute the following command to run Oxla:

```typescript
psql -h localhost
```

<Note>If you encounter an error response “bash: psql: command not found“, this means that you have not installed PostgreSQL.</Note>

6.  When you get the following result, you are now in the Oxla server✅

```typescript
psql (14.4, server Oxla 1.0)

HP=>
```

<Warning>Encountered an error? We got you! Head over [here](https://docs.oxla.com/5-error-handling/error-handling) to see your troubleshooting resolutions!</Warning>


# Run Oxla on Google Cloud Storage



Over the following steps, we’ll set you up with an Oxla server using the Google Cloud Storage.

## Prerequisite

⚠️ Install Docker. Please refer to [this page](https://docs.docker.com/engine/install/) for further details.
⚠️ We recommend you use a Linux OS computer to deploy an Oxla server.
⚠️ Install PostgresSQL-client-14 for psql connection. Please refer to [this page](https://www.postgresql.org/download/).&#x20;

## Installation Steps

1.  Open your terminal and execute this command to check if you have installed your docker properly:

```typescript
docker ps
```

<Note>If it returns “Bad response from Docker engine”, this means there is an issue with your docker engine. Try re-install your docker.</Note>

2.  Execute the following command to create a file that contains docker compose file:

```typescript
vim one_node.yml
```

3.  Input the following code into the docker compose file:

```typescript
version: '3.5'
volumes:
  oxla_data:
services:
  oxla_node:
    image: public.ecr.aws/oxla/release:latest
    security_opt:
      - seccomp:unconfined
    ulimits:
      nofile:
        soft: 40000
        hard: 40000
    volumes:
      - oxla_data:/data
    ports:
      - 5432:5432
    environment:
      - GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS?err}
```

4.  Execute the following command to create and start the docker container:

```typescript
docker compose -f one_node.yml up
```

5.  Execute the following command to run Oxla:

```typescript
psql -h localhost
```

<Note>If you encounter an error response “bash: psql: command not found“, this means that you have not installed PostgreSQL.</Note>

6.  When you get the following result, you are now in the Oxla server✅

```typescript
psql (14.4, server Oxla 1.0)

HP=>
```

<Warning>Encountered an error? We got you! Head over [here](https://docs.oxla.com/5-error-handling/error-handling) to see your troubleshooting resolutions!</Warning>


# Run Oxla on S3



## Prerequisites

*   Docker
*   Linux OS
*   PostgreSQL Client

## Installation

To run Oxla on S3, you need to have Docker and the PostgreSQL client installed on your local machine.

*   [Docker](https://docs.docker.com/engine/install/)
*   [PostgreSQL Client](https://www.postgresql.org/download/)

## Docker Setup

Once you’re done with installation, you can open your terminal and execute following command to check if you have installed your Docker instance properly:

```typescript
docker ps
```

<Note>If it returns “Bad response from Docker Engine”, it means there is an issue with your Docker instance and you need to re-install it. Refer to our [troubleshooting guide](https://docs.oxla.com/5-error-handling/error-handling) to learn more about common errors and how to resolve them.</Note>

## Docker Compose File

Execute the command below to create a `docker compose` file:

```typescript
vim one_node.yml
```

Then, update the file with the following code:

```typescript
version: '3.5'
volumes:
  oxla_data:
services:
  oxla_node:
    image: public.ecr.aws/oxla/release:latest
    security_opt:
      - seccomp:unconfined
    ulimits:
      nofile:
        soft: 40000
        hard: 40000
    volumes:
      - oxla_data:/data
    ports:
      - 5432:5432
    environment:
      - OXLA_HOME=s3://yourdirectoryname
      - AWS_DEFAULT_REGION=AWS_DEFAULT_REGION
      - AWS_ACCESS_KEY_ID=AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY=AWS_SECRET_ACCESS_KEY
```

<Info>Don't forget to replace environment variable placeholder values with the ones from your AWS instance.</Info>

## Docker Container

Once you successfully followed the steps described above, you can execute the following command to create and start the docker container:

```typescript
docker compose -f one_node.yml up
```

Now you are able to run Oxla server by executing the code below:

```typescript
psql -h localhost
```

<Note>If you encounter an error such as: “bash: psql: command not found“, it means that the PostgreSQL client is not installed correctly and you need to re-install it. Refer to our [troubleshooting guide](https://docs.oxla.com/5-error-handling/error-handling) to learn more about common errors and how to resolve them.</Note>

By now you should have successfully run the Oxla server:

```typescript
psql (14.4, server Oxla 1.0)

HP=>
```


# Run Oxla via AWS



Over the following steps, we’ll guide you on how to deploy and configure Oxla on AWS.

## Prerequisite

⚠️ You need to have an active AWS account. 

⚠️ Ensure that your billing details are up-to-date. AWS Marketplace charges will appear on your AWS bill.

⚠️ Your IAM user account should have permissions to subscribe to and manage software in the AWS Marketplace.

⚠️  Ensure the product is available in the AWS region where you intend to deploy it

## Steps

### Step 1: Subscribe to Oxla

1.  Go to the [AWS Marketplace](https://aws.amazon.com/marketplace) and type **Oxla** in the search field.
2.  Select **Oxla** from the search results.

<img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/oxla-via-aws-1.png" />

3.  Click on the **Subscribe** button.

### Step 2: Manage Subscriptions

After subscribing, you will find Oxla in the Manage Subscriptions page.

<img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/oxla-via-aws-2.png" />

### Step 3: Launch Oxla Cluster

1.  From the Manage Subscriptions page, click on **Launch CloudFormation stack** to configure Oxla.
2.  You will go to the “Configure this software” prompt, where you need to configure the following:
    *   Under the fulfillment option, select **Oxla Cluster Stack**.
    *   Select the latest software version.
    *   Choose a region where you want to deploy Oxla.
3.  Click **Continue to Launch**.
4.  You will go to the “Launch this software” page. Select **Launch CloudFormation**.
5.  Click **Launch** to proceed.

### Step 4: Specify Stack Details

1.  On the “CloudFormation template” page, you don’t need to change anything, so click **Next**.
2.  Fill in the Stack details:

| Fields               | Details                                                                                         |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| Stack name           | The stack name.                                                                                 |
| AvailabilityZone     | Availability zone of your choice. This field is mandatory.                                      |
| ExistingS3BucketName | The S3 bucket name. You can also leave this field empty to allow AWS to create a new S3 bucket. |
| InstanceType         | The instance type. Available options are c5a.2xlarge, c5a.4xlarge, c5a.8xlarge.                 |
| IsPubliclyAccessible | Set to true or false, depending on whether you want the cluster to be publicly accessible.      |
| NodeNumber           | The node number. Minimum value is 1 and maximum value is 16.                                    |
| OxlaVersion          | The default oxla version.                                                                       |
| OxlaWhitelistedCidr  | The CIDR range. Only specified CIDR will have access to the Oxla cluster.                       |

3.  Click **Next** to continue by adjusting the configuration to your personal needs.

### Step 5: Accessing Oxla

1.  Once the stack is successfully deployed, go to **CloudFormation** → **Stacks** →select your stack.
2.  Find the **OxlaEndpoint** in the **Outputs** section.
3.  Connect to your Oxla cluster using PSQL, for example:

```psql
psql -h [OxlaEndpoint] -p 5432
```


# SET/SHOW statement



## **Overview**

The `SET` statement lets you set specific options, and the `SHOW` statement helps you see the current values in Oxla.

## **Syntax**

**SET Syntax**

```sql
SET <option> TO <value>;
```

**SHOW Syntax**

```sql
SHOW <option>;
```

The available options that can be set and shown are:

*   `extra_float_digits`: By default, Oxla displays a limited number of digits, but you can set how many extra digits are displayed after the decimal point in floating-point numbers by using `extra_float_digits`.

*   `application_name`: Sets a custom name for the application.

*   `timezone`: Determines the time zone used for date and time functions.

*   `client_min_messages`: Sets the message levels sent to the client. Valid values are `DEBUG5`, `DEBUG4`, `DEBUG3`, `DEBUG2`, `DEBUG1`, `LOG`, `NOTICE`, `WARNING`, and `ERROR`.

*   `search_path`: Defines namespaces at which Oxla looks for tables.

## **Examples**

### Case #1: SHOW Statement

**Example 1**

To display the current timezone setting, use the following query:

```sql
SHOW timezone;
```

This will display the current timezone setting.

```sql
 timezone 
----------
 Etc/UTC
```

**Example 2**

To display the current search path, use the following query:

```sql
SHOW search_path;
```

This will display the current search path setting.

```sql
 search_path 
-------------
 public
```

### Case #2: SET Statement

**Example 1**

To change the number of digits, use the `SET` statement below:

```sql
SET extra_float_digits TO 2;
```

This will set the number of digits displayed for floating-point values to 2.

```sql
SHOW extra_float_digits;
```

```sql
 extra_float_digits 
--------------------
 2
```

**Example 2**

To change the client message, use the `SET` statement below:

```sql
SET client_min_messages TO 'WARNING';
```

This will set the message level to 'WARNING'.

```sql
SHOW client_min_messages;
```

```sql
 client_min_messages 
---------------------
 warning
```


# COPY FROM



## **Overview**

**COPY FROM** is used to import data from a file into a table by reading from the file directly. When using the COPY FROM, each field in the file is inserted sequentially into the specified column.

<Info>The file must be accessible and able to be read and written to.</Info>

## **Syntax**

The syntax for **COPY FROM** is as follows:&#x20;

```sql
COPY table_name FROM 'file_path';
```

Two parameters need to be specified in the syntax:

*   `table_name`: the table that will receive data from the file.

*   `file_path`: a link to the file location accessible from the server.&#x20;

## **Example**

### Step #1: Create a CSV File

First, you should create a CSV file and store it on your local computer. Here, we make a file called **“feature2.csv”** that stores features with its version.

> create a table, 1.0
> modify a table, 1.2
> drop a table, 2.2
> rename a table, 2.0

### Step #2: Import FIle from Local to Server

You can use the syntax below for importing the file to the server:

```typescript
aws s3 cp ~/[file location on your local computer] s3://[server location]/[file name]
```

Next, import the file to the server using the above syntax as shown below:

```typescript
aws s3 cp ~/Documents/feature2.csv s3://oxla-testdata/cayo/feature2.csv
```

If it’s successfully imported, you will get the following result:

```typescript
upload: Documents/feature2.csv to s3://oxla-testdata/cayo/feature2.csv
```

### Step #3: Connect to Oxla Server

The file has been successfully uploaded to the server ✅. Now, connect to the Oxla server using the command below:

```sql
psql -h buildfarm.oxla.com -p 6000
```

If you get the output below, you are currently in the Oxla environment.

```sql
psql (15.1 (Ubuntu 15.1-1.pgdg22.10+1), server Oxla 1.0)
WARNING: psql major version 15, server major version 0.0.
         Some psql features might not work.
Type "help" for help.
```

### Step #4: Create a Table

Before creating a table, check for duplicate tables with the statement below:

```sql
DESCRIBE DATABASE
```

In return, you will retrieve a list of existing tables in the Oxla.&#x20;

```sql
+----------------------------+
| name                       |
+----------------------------+
| supplier_scale_1_no_index  |
| features                   |
| orders                     |
| features2                  |
| featurestable              |
| featurestable1             |
| featurestable10            |
+----------------------------+
```

<Warning>Ensure you are not creating duplicate tables.</Warning>

We need to create a table to retrieve the data from the CSV file. Here we will create a “**featurelisttable**” table. Using the same data type as described in the file is recommended.

```sql
CREATE TABLE featurelisttable (featurename string, version float);
```

### Step #5: Copy the CSV File Into Table

Now, copy **“feature2.csv”** by executing the COPY FROM query below:

```sql
COPY featurelisttable FROM 's3://oxla-testdata/cayo/feature2.csv';
```

You will get the following successful result:

```sql
--
(0 rows)
```

### Step #6: Retrieve the Table

To verify that the data was imported correctly from the server, retrieve all the data using the SELECT statement:

```sql
SELECT * FROM featurelisttable;
```

You will have the same data in the table as in the CSV file.

```sql
+-----------------+----------+
| featurename     | version  | 
+-----------------+----------+
| create a table  | 1        |
| modify a table  | 1.2      |
| drop a table    | 2.2      |
| rename a table  | 2        |
+-----------------+----------+
```


# COPY FROM STDIN



## Overview

The `COPY FROM STDIN` command imports data directly from the client into a table. It simplifies the copy process by eliminating the need to transfer files to the server.

## Syntax

The basic syntax for using `COPY FROM STDIN` is:

```sql
COPY table_name FROM stdin;
```

Parameters:

*   `table_name`: The table where the data will be imported
*   `stdin`: Indicates that the data comes from the standard input (client application)

<Note>- **Format**: Only .csv is supported <br /> - **Delimiter**: For CSV format, the default delimiter is a comma (,)</Note>

### Additional Options

1.  **Listing Column Names**
    You can specify the columns into which the data should be imported.

```sql
COPY table_name (column1, column2) FROM stdin;
```

2.  **Options**
    You can include additional options following `FROM stdin` to customize the import process.

```sql
COPY table_name FROM STDIN WITH (FORMAT csv, DELIMITER ',');
```

## Examples

### Importing Data Manually

1.  Ensure the table exists in your database. If it doesn’t, create one using the following command:

```sql
CREATE TABLE country (
    code TEXT,
    name TEXT
);
```

2.  You should see the output:

```sql
CREATE
```

3.  Initiate the import operation by running the following command:

```sql
COPY country FROM stdin;
```

4.  You will be prompted to enter your data. There will be a message as shown below:

```sql
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> 
```

5.  Paste the data directly from your CSV file into the prompt:

```sql
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> FR,FRANCE
DE,GERMANY
IT,ITALY
ES,SPAIN
GB,UNITED KINGDOM
NL,NETHERLANDS
BE,BELGIUM
CH,SWITZERLAND
AT,AUSTRIA
SE,SWEDEN
```

6.  To end the import process, enter `\.` or an EOF signal.

```sql
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> FR,FRANCE
DE,GERMANY
IT,ITALY
ES,SPAIN
GB,UNITED KINGDOM
NL,NETHERLANDS
BE,BELGIUM
CH,SWITZERLAND
AT,AUSTRIA
SE,SWEDEN
>> >> >> >> >> >> >> >> >> >> \.
```

<Note>An EOF (End of File) signal is used to indicate the end of input data and to terminate the input process. On Unix-like systems, press `Ctrl + D`.</Note>

7.  If the import is successful, you will see `IMPORT 0` at the end of the line.

```sql
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> FR,FRANCE
DE,GERMANY
IT,ITALY
ES,SPAIN
GB,UNITED KINGDOM
NL,NETHERLANDS
BE,BELGIUM
CH,SWITZERLAND
AT,AUSTRIA
SE,SWEDEN
>> >> >> >> >> >> >> >> >> >> IMPORT 0
```

<Warning>The `IMPORT 0` message doesn't reflect the number of rows imported. This feature is planned for future development.</Warning>

8.  Verify the imported data by querying the table:

```sql
SELECT * FROM country;
```

9.  The output should show that the data has been successfully imported into the table:

```sql
 code |      name      
------+----------------
 FR   | FRANCE
 DE   | GERMANY
 IT   | ITALY
 ES   | SPAIN
 GB   | UNITED KINGDOM
 NL   | NETHERLANDS
 BE   | BELGIUM
 CH   | SWITZERLAND
 AT   | AUSTRIA
 SE   | SWEDEN
(10 rows)
```

### Importing a CSV File Directly

To import a CSV file directly into Oxla, use the following steps. This method bypasses the need to manually enter data by reading the file and importing it directly into Oxla.

1.  Create the Table (if not already created):

```sql
CREATE TABLE country (
    code TEXT,
    name TEXT
);
```

2.  Exit `psql`:

```bash
\q
```

3.  Import the CSV File:

```bash
cat myfile.csv | psql -c "COPY country FROM STDIN WITH (FORMAT csv, DELIMITER ',');"
```

This command reads the contents of **myfile.csv** and passes it directly to the `COPY` command.

4.  Re-enter `psql` and verify the table contents:

```bash
SELECT * FROM country;
```


# COPY FROM with Delimiter



## **Overview**

A delimiter is a character that separates text strings. Common delimiters are:

*   Commas (,)

*   Semicolon (;)

*   Quotes ( ", ' )

*   Dash (-)

*   Pipes (|)

*   Slashes ( / \ ).

**By default, the COPY FROM function accepts commas (,).**

## **Syntax**

The syntax for **COPY FROM** is as follows:

```sql
COPY table_name FROM 'file_path' (DELIMITER 'delimiter');
```

Two parameters need to be specified in the syntax:

*   `table_name`: the table that will receive data from the file.

*   `file_path`: a link to the file location in the server.

*   `DELIMITER 'delimiter'`: the delimiter used in the CSV file.

## **Example**

Let’s have a look at the step-by-step below:

### Step #1: Create a CSV File

First, you should create a CSV file and store it on your local computer. In this case, we use Dash ( - ) character to separate the text.

> create a table - 1.0
> modify a table - 1.2
> drop a table - 2.2
> rename a table - 2.0

### Step #2:  Import FIle from Local to Server

You can use the syntax below for importing the file to the server:

```typescript
aws s3 cp ~/[file location on your local computer] s3://[server location]/[file name]
```

Next, import the file to the server using the above syntax:

```typescript
aws s3 cp ~/Documents/feature2.csv s3://oxla-testdata/cayo/feature2.csv
```

If it’s successfully imported, you will get the following result:

```typescript
upload: Documents/feature2.csv to s3://oxla-testdata/cayo/feature2.csv
```

### Step #3:  Connect to Oxla Server

Connect to the Oxla server using the command below:

```sql
psql -h buildfarm.oxla.com -p 6000
```

You are now in the Oxla environment if you get the output below.

```sql
psql (15.1 (Ubuntu 15.1-1.pgdg22.10+1), server Oxla 1.0)
WARNING: psql major version 15, server major version 0.0.
         Some psql features might not work.
Type "help" for help.
```

### Step #4:  Create a Table

Before creating a table, check for duplicate tables with the statement below:

```sql
DESCRIBE DATABASE
```

In return, you will retrieve a list of existing tables in Oxla.

```sql
+----------------------------+
| name                       |
+----------------------------+
| supplier_scale_1_no_index  |
| features                   |
| orders                     |
| features2                  |
| featurestable              |
| featurestable1             |
| featurestable10            |
+----------------------------+
```

<Warning>Ensure you are not creating duplicate tables.</Warning>

Create a “**featurelisttable**” table using the command below:

```sql
CREATE TABLE featurelisttable (featurename string, version float);
```

### Step #5:  Copy the CSV File Into Table

Because we are using Dash ( - ), we need to add a DELIMITER param with a specified character, as shown below:

```sql
COPY featurelisttable FROM 's3://oxla-testdata/cayo/feature2.csv' (DELIMITER '-');
```

You will get the following successful result:

```sql
--
(0 rows)
```

Otherwise, you will get the error message below:

```sql
ERROR: unexpected data at line: 1 col: 0 position: 108, expected , but got:
```

### Step #6: Retrieve the Table

To verify that the data was imported correctly from the server, retrieve all the data using the SELECT statement:

```sql
SELECT * FROM featurelisttable;
```

You will have the same data in the table as in the CSV file.

```sql
+-----------------+----------+
| featurename     | version  | 
+-----------------+----------+
| create a table  | 1        |
| modify a table  | 1.2      |
| drop a table    | 2.2      |
| rename a table  | 2        |
+-----------------+----------+
```


# COPY FROM with Endpoint



## Overview

When running [COPY FROM](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from) queries, you should have the option to include the **endpoint URL**. This feature is especially useful for scenarios where you need to provide credentials and specific endpoints.

## Syntax

The syntax is as follows:

```sql
COPY table_name FROM 'file_path' (AWS_CRED(AWS_REGION 'aws_region', AWS_KEY_ID "
      "'key_id', AWS_PRIVATE_KEY 'access_key', ENDPOINT 'endpoint_url'));
```

<Info>Replace `AWS_CRED` with `AZURE_CRED` or `GCS_CRED` when copying from the Azure Blob Storage or Google Cloud Storage.</Info>

Here's the breakdown of syntax parameters:

*   **Shared parameters**:
    *   `table_name`: table that will receive data from the file
    *   `file_path`: link to the file location accessible from the server

*   **Parameters in `AWS_CRED`**:
    *   `aws_region`: AWS region associated with the storage service (e.g. 'region1')
    *   `key_id`: key identifier for authentication
    *   `access_key`: access key for authentication
    *   `endpoint_url`: URL endpoint for the storage service

*   **Parameters in `GCS_CRED`**:
    *   `<path_to_credentials>`: path to JSON credentials file

*   **Parameters in `AZURE_CRED`**:
    *   `tenant_id`: tenant identifier representing your organization's identity in Azure
    *   `client_id`: client identifier used for authentication
    *   `client_secret`: secret identifier acting as a password for authentication.

## Examples

### COPY FROM with AWS S3 Bucket

In this example, we are using the COPY FROM statement to import data from a file named `students_file` and the endpoint is `s3.us-east-2.amazonaws.com`.

```sql
COPY students FROM 'students_file' (AWS_CRED(AWS_REGION 'region1', AWS_KEY_ID "
      "'key_id', AWS_PRIVATE_KEY 'access_key', ENDPOINT 's3.us-east-2.amazonaws.com'));
```

**Expected Output**: Data from `students_file` is copied into the `students` table

### COPY FROM with Google Cloud Storage

This example shows how to use the `COPY FROM` statement to import data, but this time, the data is stored on Google Cloud Storage;

```psql
COPY project FROM 'gs://your-bucket/project_file' (GCS_CRED('/path/to/credentials.json'));
```

You can also copy the data using the `AWS_CRED` like below, with the following endpoint `https://storage.googleapis.com`.

```sql
COPY project FROM 'project_file' (AWS_CRED(AWS_REGION 'region1', AWS_KEY_ID "
      "'key_id', AWS_PRIVATE_KEY 'access_key', ENDPOINT 'https://storage.googleapis.com'));
```

**Expected Output**: Data from `project_file` is copied into the `project` table.

<Tip>For Google Cloud Storage, it's recommended to use HMAC keys for authentication. You can find more details about that on the [HMAC keys - Cloud Storage](https://cloud.google.com/storage/docs/authentication/hmackeys) page.</Tip>

### COPY FROM with Azure BlobStorage

It's a similar story for getting the data from Azure Blob Storage.

```pgsql
COPY taxi_data FROM 'wasbs://container-name/your_blob' (AZURE_CRED(TENANT_ID 'your_tenant_id' CLIENT_ID 'your_client_id', CLIENT_SECRET 'your_client_secret'));
```

**Expected Output**: Data from the `your_blob` is copied into the `taxi_data`.


# COPY FROM with HEADER



## **Overview**

When it comes to a table, we deal with its components like rows, columns, and headers. In Oxla, we provide 3 possible options for the header as follows:

*   **HEADER OFF**

This option will not skip the header of the CSV file. Below are the available syntaxes besides HEADER OFF:

```sql
HEADER OFF
HEADER FALSE
HEADER 0
```

<Info>This is a default behavior that will be applied if you do not provide the HEADER option in your query.</Info>

*   **HEADER ON**

This option will skip the header of the CSV file and only follow the columns that have been specified before. Below are the available syntaxes besides HEADER ON:

```sql
HEADER ON
HEADER TRUE
HEADER 1
```

*   **HEADER MATCH**

This option will read the header and verify that the name matches the column names.&#x20;

## **Syntax**

The syntax for **COPY FROM with HEADER** is as follows:

```sql
COPY table_name FROM 'file_path' (Header_Syntax);
```

Two parameters need to be specified in the syntax:

*   `table_name`: the table that will receive data from the file.

*   `file_path`: a link to the file location in the server.

*   `Header_Syntax`: the specified header options.

## **Examples**

Say you have created a CSV file called **idvals.csv,** and the file has been uploaded to the server:

> id,quantity
> 1,5
> 2,2
> 3,1
> 4,8
> 5,4
> 6,3

Then, you create a table by specifying the column with an integer data type:

```sql
CREATE TABLE idqty (id INTEGER, quantity INTEGER);
```

Now, let’s see an example case by case:

### Case #1: HEADER OFF

1.  With reference to the table above, run the following query:

```sql
COPY idqty FROM 's3://oxla-testdata/cayo/idvals.csv';
```

2.  An error output will appear.&#x20;

This happens because we specified the table with an INTEGER column. While in the CSV file, we have STRING value which is **“id”** and **“quantity”**, which are not considered headers.

```sql
Error while parsing f32 from csv at line:0 col:6 position:26, parsing error
```

<Check>To include the headers, use the **HEADER ON** option.</Check>

Another Option

1.  If you don’t want to include the headers (**“id”** and **“quantity”**), you can modify your CSV file by deleting the headers:

> 1,5
> 2,2
> 3,1
> 4,8
> 5,4
> 6,3

2.  Run the COPY FROM statement:

```sql
COPY idqty FROM 's3://oxla-testdata/cayo/idvals.csv';
```

3.  You will get the following output which indicates that the file has successfully imported to the table:

```sql
--
(0 rows)
```

4.  Display the table by using the SELECT statement to retrieve the table records:

```sql
SELECT * FROM idqty;
```

```sql
+----+----------+
| id | quantity | 
+---------------+
| 1  | 5        |
| 2  | 2        |
| 3  | 1        |
| 4  | 8        |
| 5  | 4        |
| 6  | 3        |
+----+----------+
```

### Case #2: HEADER ON

1.  With reference to the **idqty** table above, run the following query:

```sql
COPY idqty FROM 's3://oxla-testdata/cayo/idvals.csv'(HEADER ON);
```

2.  You will get the following output which indicates that the file has successfully imported to the table:

```sql
--
(0 rows)
```

3.  To verify, use the SELECT statement to retrieve the table records:

```sql
SELECT * FROM idqty;
```

We will get the below result, which displays the **idqty** table:

```sql
+----+----------+
| id | quantity | 
+---------------+
| 1  | 5        |
| 2  | 2        |
| 3  | 1        |
| 4  | 8        |
| 5  | 4        |
| 6  | 3        |
+----+----------+
```

<Info>In this case, the header may be anything that has been specified before. It does not need to have column names.</Info>

### Case #3: HEADER MATCH

1.  Based on the **idqty** table above, if we run the following query:

```sql
COPY idqty FROM 's3://oxla-testdata/cayo/idvals.csv' (HEADER MATCH);
```

2.  It will produce a successful output because the specified columns in the **idqty** table are matched with the header of the **idvals.csv** file:

```sql
--
(0 rows)
```

3.  But, you will get a mismatched output when the header isn’t matched. Say that the **idvals.csv** file has **“id”** and “**qty”** header, as shown below:

> id,qty
> 1,5
> 2,2
> 3,1
> 4,8
> 5,4
> 6,3

Then, you will get a mismatched output because it reads **“qty”** from the CSV file when the expected value is **“quantity”** as specified in the table.

```sql
column name mismatch in header line field 1: got "qty", expected "quantity"
```

**Another Option**

1.  Furthermore, you can also define the columns that you want to match as shown below:

```sql
COPY idqty(id, quantity) FROM 's3://oxla-testdata/cayo/idvals.csv' (HEADER MATCH);
```

The following output shows a successful result:

```sql
--
(0 rows)
```

2.  But, if you change the ordering by switching the order of the columns:

```sql
COPY idqty(quantity, id) FROM 's3://oxla-testdata/cayo/idvals.csv' (HEADER MATCH);
```

3.  You will get a mismatch error message.

```sql
column name mismatch in header line field 1: got "id", expected "quantity"
```


# COPY FROM with NULL



## **Overview**

NULL means **no value**. In other words, it does not have any value, not equal to 0, empty string, or spaces. In Oxla, we can specify a different string as the null value in the COPY FROM statement.

## **Syntax**

You can define a string with any strings that will replace the null value, as shown in the syntax below:

```sql
COPY table_name FROM 'file_path' (NULL 'string')
```

## **Examples**

### **Case #1: Show Blank for NULL Value**

1.  To begin with, create a CSV file called **idvals.csv** with a null value:

> null,5
> 2,2
> 3,2

2.  In addition, create a table called **idqty** by specifying the column with an integer data type:

```sql
CREATE TABLE idqty (id INTEGER, quantity INTEGER);
```

3.  Execute the COPY FROM statement with a NULL option:

```sql
COPY idqty FROM idvals (NULL, 'null');
```

4.  A null value from the CSV file will be displayed in a table with an empty row that has no value, as shown below:

```sql
+------+----------+
| id   | quantity | 
+------+----------+
|      | 5        |
| 2    | 2        |
| 3    | 2        |
+------+----------+
```

### **Case #2: Show String for NULL Value**

1.  A string is represented with a double quote. In this case, we create a CSV file called **idvals.csv** with a null value as a string.

> "null",5
> 2,2
> 3,"null"

2.  Create a table called **idqty** by specifying the column with an integer data type:

```sql
CREATE TABLE idqty (id INTEGER, quantity INTEGER);
```

3.  Execute the COPY FROM statement with a NULL option:

```sql
COPY idqty FROM idvals (NULL, 'null');
```

4.  You can see that a null value from the CSV file will be displayed in a table with **“null”:**

```sql
+------+----------+
| id   | quantity | 
+------+----------+
| null | 5        |
| 2    | 2        |
| 3    | null     |
+------+----------+
```

<Info>You can specify another string to replace the null value. Such as blank, empty, invalid, etc. </Info>


# COPY TO



## **Overview**

The `COPY TO` statement is used to export tables, specific columns, or results of select queries into .csv files. It allows you to copy data from a table or query result and save it to a specified file.

## **Syntax**

The syntax for `COPY TO` is as follows:

```sql
COPY { table_name [ ( column_name [, ...] ) ] | ( query ) } TO 'filename' [( option [, ...] ) ];
```

Parameters in the syntax include:

*   `table_name`: Table with the data to export.

*   `column_name`: Optional. Specify columns for export.

*   `query`: A `SELECT` statement for exporting specific results.

*   `filename`: File name for saving the exported data.

*   `option`: Optional parameters for customization.

## **Example**

### **Step #1: Create a Table**

1.  Before creating The table, check for duplicate tables using the following statement:&#x20;

```sql
DESCRIBE DATABASE
```

2.  You will receive a list of existing tables in Oxla:

```sql
 namespace_name |      name      
----------------+----------------
 public         | client
 public         | distance_table
 public         | weight
 public         | product
```

<Warning>Ensure you are not creating duplicate tables.</Warning>

3.  Now, let's create a table for exporting data to a CSV file. Here, we'll create a "**salary**" table:

```sql
CREATE TABLE salary (
  empid int,
  empname string,
  empdept string,
  empaddress string,
  empsalary int
);
INSERT INTO salary 
    (empid, empname, empdept, empaddress, empsalary) 
VALUES 
    (2001,'Paul','HR', 'California', null ),
    (2002,'Brandon','Product', 'Norway', 15000),
    (2003,'Bradley','Marketing', 'Texas', null),
    (2004,'Lisa','Marketing', 'Houston', 10000),
    (2005,'Emily','Marketing', 'Texas', 20000),
    (2006,'Bobby','Finance', 'Seattle', 20000),
    (2007,'Parker','Project', 'Texas', 45000);
```

4.  The table and data were created successfully.

```sql
COMPLETE
INSERT 0 7
```

### **Step #2: Copy the Table into the CSV File**

<Warning>**Important Notes:** <br /> - By default, the `COPY TO` command overwrites the CSV file if it already exists. <br /> - Please ensure that the directory where you save the file has the necessary write permissions.</Warning>

**Option 1: Exporting all columns from a table**

Copy all columns in the table to the specified CSV file:

```sql
COPY salary TO '/path/to/exportsalary.csv';
```

You will get the following successful result:

```sql
--
(0 rows)
```

The data from the table will be exported to the CSV file.

**Option 2: Exporting specific columns from a table**

Copy only specific columns by specifying the column names in the query:

```sql
COPY salary (empid, empname, empsalary) TO 'exportsalary.csv';
```

You will get the following successful result:

```sql
--
(0 rows)
```

The data from the specified columns will be exported to the CSV file.

**Option 3: Exporting results of a SELECT statement**

In the example below, copy data only from the **Marketing department** using the `SELECT` statement and `WHERE` clause:

```sql
COPY (SELECT * FROM salary WHERE empdept = 'Marketing') TO 'exportsalary.csv';
```

You will get the following successful result:

```sql
--
(0 rows)
```

Data exported to CSV file is only from the Marketing department.


# COPY TO STDOUT



## Overview

The `COPY TO STDOUT` command is used to export data directly from a table to the client. This approach allows for data transfer by sending the data directly to the client, eliminating the need for server-side file operations.

## Syntax

The basic syntax for using `COPY TO STDOUT` is:

```sql
COPY table_name TO STDOUT;
```

Parameters:

*   `table_name`: The table from which the data will be exported.
*   `stdout`: Indicates that the data will be sent to the standard output (client application).

<Note>- **Format**: Only .csv is supported <br /> - **Delimiter**: For CSV format, the default delimiter is a comma (,)</Note>

## Example

### Step 1. Create the Table

1.  Create the table and insert some data into it.

```sql
CREATE TABLE book_inventory (
    title TEXT,
    copies_available INT
);
INSERT INTO book_inventory (title, copies_available) VALUES
('To Kill a Mockingbird', 5),
('1984', 8),
('The Great Gatsby', 3),
('Moby Dick', 2),
('War and Peace', 4);
```

2.  Upon successful creation, you should see the output below:

```sql
CREATE
INSERT 0 5
```

### Step 2. Start the Export Operation

1.  Run the `COPY TO STDOUT` command to export the data from the `book_inventory` table:

```sql
COPY book_inventory TO STDOUT;
```

2.  You will get the output with the table values, which you can use to create or copy into a CSV file:

```sql
"To Kill a Mockingbird",5
1984,8
"The Great Gatsby",3
"Moby Dick",2
"War and Peace",4
```


# COPY TO with Delimiter



## **Overview**

A delimiter is a character that separates text strings. Common delimiters include:

*   Commas (,)

*   Semicolon (;)

*   Quotes ( ", ' )

*   Dash (-)

*   Pipes (|)

*   Slashes ( / \ ).

## **Syntax**

The syntax for `COPY TO` with a delimiter is as follows:

```sql
COPY table_name TO 'file_path' (DELIMITER 'delimiter');
```

Parameters in the syntax include:

*   `table_name`: The table containing the data to be exported.

*   `file_path`: The CSV file location where the data will be saved.

*   `DELIMITER ‘delimiter'`: The Delimiter used in the exported CSV file.

<Info>**Default delimiter is a comma (**`,`**).**</Info>

## **Example**

### **Step #1: Create a Table**

1.  Before creating a table, check for duplicate tables using the following statement:

```sql
DESCRIBE DATABASE
```

2.  You will receive a list of existing tables in Oxla:

```sql
 namespace_name |      name      
----------------+----------------
 public         | client
 public         | distance_table
 public         | weight
 public         | product
 public         | salary
```

<Warning>Ensure you are not creating duplicate tables.</Warning>

3.  Create a "**customer**" table.

```sql
CREATE TABLE customer (
  cust_id int,
  cust_name string
);
INSERT INTO customer 
    (cust_id, cust_name) 
VALUES 
    (11001, 'Maya'),
    (11003, 'Ricky'),
    (11009, 'Sean'),
    (11008, 'Chris'),
    (11002, 'Emily'),
    (11005, 'Rue'),
    (11007, 'Tom'),
    (11006, 'Casey');
```

4.  The table and data were created successfully.

```sql
COMPLETE
INSERT 0 8
```

### **Step #2: Export Data to a CSV File using Delimiter**

<Warning>**Important Notes:** <br /> - By default, the `COPY TO` command overwrites the CSV file if it already exists. <br /> - Please ensure that the directory where you save the file has a write permissions.</Warning>

In the example below, we are using a Comma ( `,` ).

```sql
COPY salary TO '/home/acer/Documents/customerexport.csv' (DELIMITER ',');
```

You will get the successful output below.

```sql
--
(0 rows)
```

Using the comma ( `,` ) as the delimiter for the `customer` table, the expected output would be:

```sql
cust_id,cust_name
11001,Maya
11003,Ricky
11009,Sean
11008,Chris
11002,Emily
11005,Rue
11007,Tom
11006,Casey
```


# COPY TO with Endpoint



## Overview

When running [COPY TO](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to) queries, you should have the option to include the **endpoint URL**. This feature is especially useful for scenarios where you need to provide credentials and specific endpoints.

## Syntax

The syntax for using `COPY TO` statement is as follows:

```sql
COPY table_name TO 'file_path' (AWS_CRED(AWS_REGION 'aws_region', AWS_KEY_ID 
      'key_id', AWS_PRIVATE_KEY 'access_key', ENDPOINT 'endpoint_url'));
```

<Info>Replace `AWS_CRED` with `AZURE_CRED` or `GCS_CRED` when copying to the Azure Blob Storage or Google Cloud Storage.</Info>

Here's the breakdown of parameters syntax:

*   **Shared parameters**:
    *   `table_name`: table containing the data to be exported
    *   `file_path`: CSV file location accessible from the server

*   **Parameters in `AWS_CRED`**:
    *   `aws_region`: AWS region associated with the storage service (e.g. 'region1')
    *   `key_id`: key identifier used for authentication
    *   `access_key`: access key used for authentication
    *   `endpoint_url`: URL endpoint for the storage service

*   **Parameters in `GCS_CRED`**:
    *   `<path_to_credentials>`: path to JSON credentials file.

*   **Parameters in `AZURE_CRED`**:
    *   `tenant_id`: tenant identifier representing your organization's identity in Azure
    *   `client_id`: client identifier used for authentication.
    *   `client_secret`: secret identifier acting as a password when authenticating

## Examples

### COPY TO with AWS S3 Bucket

In this example, we use the `COPY TO` statement to export data from the `students` table to a CSV file named `students_file`.

```sql
COPY students TO 's3://oxla-testdata/cayo/students_file' (AWS_CRED(AWS_REGION 'region1', AWS_KEY_ID 
      'key_id', AWS_PRIVATE_KEY 'access_key', ENDPOINT 's3.us-east-2.amazonaws.com'));
```

**Expected Output**: `student` table data is copied to the `students_file` on AWS S3

### COPY TO with Google Cloud Storage

This example shows how to use the `COPY TO` statement to export data, but this time, the data is stored on Google Cloud Storage.

```sql
COPY project TO 'gs://your-bucket/project_file' (GCS_CRED('/path/to/credentials.json'));
```

You can also copy the data using the `AWS_CRED` like below:

```sql
COPY project TO 'gs://your-bucket/project_file' (AWS_CRED(AWS_REGION 'region1', AWS_KEY_ID 
      'key_id', AWS_PRIVATE_KEY 'access_key', ENDPOINT 'https://storage.googleapis.com'));
```

**Expected Output**: Data from the `project` table is copied to the `project_file` on Google Cloud Storage

### COPY TO with Azure BlobStorage

It's a similar story for storing data in Azure Blob Storage.

```sql
COPY taxi_data TO 'wasbs://container-name/your_blob' (AZURE_CRED(TENANT_ID 'your_tenant_id' CLIENT_ID 'your_client_id', CLIENT_SECRET 'your_client_secret'));
```

**Expected Output**: Data from the `taxi_data` table is copied to `your_blob` on Azure Blob Storage


# COPY TO with HEADER



## **Overview**

When you export data from a table to a CSV file using the `COPY TO` command, you can include or skip the header. Oxla provides three options for handling headers: `HEADER OFF`, `HEADER ON`, and `HEADER MATCH`.

## **Syntax**

The syntax for `COPY TO` with `HEADER` is as follows:

```sql
COPY table_name TO 'file_path' (Header_Syntax);
```

Parameters in the syntax include:

*   `table_name`: The table containing the data to be exported.

*   `file_path`: The CSV file location where the data will be saved.

*   `Header_Syntax`: The specified header options.

## **Header Options**

*   **HEADER OFF**

This option will not skip the header of the CSV file. The available syntax is:&#x20;

```none
HEADER OFF
HEADER FALSE
HEADER 0
```

<Info>This option is a default behaviour if `HEADER` is not provided.</Info>

*   **HEADER ON**

This option skips the header of the CSV file and follows only the previously specified columns. The available syntax is:&#x20;

```none
HEADER ON
HEADER TRUE
HEADER 1
```

## **Examples**

First, create a **"personal\_details"** table.

```sql
CREATE TABLE personal_details (
  id int,
  first_name string,
  last_name string,
  gender string
);
INSERT INTO personal_details 
    (id, first_name, last_name, gender) 
VALUES 
    (1,'Mark','Wheeler','M'),
    (2,'Tom','Hanks','M'),
    (3,'Jane','Hopper','F'),
    (4,'Emily','Byers','F'),
    (5,'Lucas','Sinclair','M');
```

The table and data were created successfully.

```sql
COMPLETE
INSERT 0 5
```

Now, let’s explore some cases of `COPY TO` with different header options:

### **Case 1: HEADER OFF**

<Info>Please ensure that the directory where you save the file has a write permissions.</Info>

1.  Run the query below to export the table.

```sql
COPY personal_details TO '/home/acer/Documents/personalinfo.csv';
```

2.  You will get the following output, indicating that the table has successfully exported to the CSV file.

```sql
--
(0 rows)
```

3.  The data in the table is copied directly to the `personalinfo` file without considering the first row as a header.

```sql
1,'Mark','Wheeler','M'
2,'Tom','Hanks','M'
3,'Jane','Hopper','F'
4,'Emily','Byers','F'
5,'Lucas','Sinclair','M'
```

<Check>To include headers, use the `HEADER ON` option.</Check>

### **Case 2: HEADER ON**

1.  Run the query below to export the table.

```sql
COPY personal_details TO '/home/acer/Documents/personalinfo.csv' (HEADER ON);
```

2.  You will get a successful output below.

```sql
--
(0 rows)
```

3.  In this case, the header from the table will be included in the CSV file.&#x20;

```none
id,first_name,last_name,gender
1,'Mark','Wheeler','M'
2,'Tom','Hanks','M'
3,'Jane','Hopper','F'
4,'Emily','Byers','F'
5,'Lucas','Sinclair','M'
```


# COPY TO with NULL



## **Overview**

A `NULL` value indicates that the value does not exist in the database. In Oxla, you can use the `NULL` option in the `COPY TO` state to specify a string that will replace `NULL` values ​​when copying data from the table to a CSV file.

## **Syntax**

The syntax for using the `NULL` option in the `COPY TO` is as follows:

```sql
COPY table_name TO 'file_path' (NULL 'replacement_string');
```

Parameters in the syntax include:

*   `table_name`: The table containing the data to be exported.

*   `file_path`: A CSV file location where the data will be saved.

*   `NULL ‘replacement_string'`: The specified string that will replace NULL values in the exported CSV file. The default value is `' '`.

## **Example**

1.  Create a table with a `NULL` value.

```sql
CREATE TABLE example_table (
  id serial,
  name varchar(50),
  age int,
  city varchar(50)
);

INSERT INTO example_table (name, age, city) VALUES
  ('John', 25, 'New York'),
  ('Alice', NULL, 'Chicago'),
  ('Bob', 30, NULL);
```

2.  Now, let's use `COPY TO` with an empty string:

```sql
COPY example_table TO '/path/to/exampleexport.csv' (NULL '');
```

3.  The `NULL` values in the table are replaced with the empty string in the CSV file.

```none
1,John,25,"New York"
2,Alice,null,"Chicago"
3,Bob,30,""
```

<Tip>You can specify another string to replace the null value, such as blank, empty, invalid, etc.</Tip>


# Create Table



## Overview

The `CREATE TABLE` statement creates a new table in a database. Each table has columns with specific data types like numbers, strings, or dates.

## Syntax

To create a table, you should name and define the columns with their data types.

```sql
CREATE TABLE [ IF NOT EXISTS ] table_name(
  column_1 datatype,
  column_2 datatype,
  column_3 datatype,
  .....
);
```

From the syntax above:

*   `table_name`: Name of the table
*   `column_1, column_2, column_n`: Names of the columns
*   `datatype`: Data type for each column
*   `IF NOT EXISTS` (Optional): Use this to avoid errors if the table already exists

<Info> SQL keywords cannot be used for table and column names unless they are quoted. Keep in mind that unquoted names are case-sensitive. For the full list of keywords, please refer to our [doc](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-2-create-table-statement/keywords).</Info>

## Constraints

When creating a table, we can add the **NOT NULL** constraint to ensure that values in a column cannot be NULL and will always contain a value. In other words, if you don't define **NOT NULL**, the column can be empty.

```sql
CREATE TABLE table_name(
column1 datatype NOT NULL,
column2 datatype NOT NULL,
column3 datatype NOT NULL,
.....
);
```

## Table index

You can add indexes to the table. See [here](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-3-create-index-statement/create-index) for more details.

<Note>By default, tables are created in the `public` schema, but you can specify a different schema. For more information, click [here](https://docs.oxla.com/3-sql-reference/schema).</Note>

## Examples

### Creating a Table

Create a sample table with the query below:

```sql
CREATE TABLE employees (
    employeeID INT,
    lastName TEXT,
    firstName TEXT NOT NULL,
    address TEXT
);
```

Once the table is created successfully, you will get the following output

```sql
CREATE
```

### Creating a Table with Values

Below is an example of creating a **client** table with values:

```sql
CREATE TABLE products (
  product_id INT,         
  product_name TEXT NOT NULL, 
  product_description TEXT
);
INSERT INTO products (product_id, product_name, product_description) 
VALUES 
    (101, 'Laptop', 'A high-performance laptop for professionals.'),
    (102, 'Smartphone', 'A latest model smartphone with excellent features.'),
    (103, 'Headphones', 'Noise-cancelling headphones for immersive audio experience.');
```

You can run the following command to verify the completed request:

```sql
SELECT * FROM products;
```

As a result, we''ll receive a table show below:

```sql
 product_id | product_name |                     product_description                     
------------+--------------+-------------------------------------------------------------
        101 | Laptop       | A high-performance laptop for professionals.
        102 | Smartphone   | A latest model smartphone with excellent features.
        103 | Headphones   | Noise-cancelling headphones for immersive audio experience.
(3 rows)
```

### Using Quoted names

1.  Creating a table using the query below:

```sql
CREATE TABLE preferences (module TEXT);
```

2.  This will fail with an error message:

```sql
ERROR:  syntax error, unexpected MODULE
ERROR:  syntax error at or near "module"
LINE 1: CREATE TABLE preferences (module TEXT);
                                 ^
```

3.  It happens because "module" is a keyword. To use a keyword as a column name, you need to enclose it in double quotes.

```sql
CREATE TABLE preferences ("module" TEXT);
```

4.  When querying the table, remember to use quotes around the column name:

```sql
SELECT "module" FROM preferences;
```

Note that names enclosed in quotes are case-sensitive. Therefore, this query will fail:

```sql
SELECT "Module" FROM preferences;
```

### Creating a Table with IF NOT EXISTS

To prevent errors when a table already exists, use the `IF NOT EXISTS` clause. See the following examples:

#### Example without IF NOT EXISTS

1.  First, create the table without using the `IF NOT EXISTS` option:

```sql
CREATE TABLE products (
  productID INT,
  productName TEXT,
  category TEXT NOT NULL,
  price REAL
);
```

Output:

```sql
CREATE
```

2.  Then, create the same table:

```sql
CREATE TABLE products (
  productID INT,
  productName TEXT,
  category TEXT NOT NULL,
  price REAL
);
```

Because you attempt to create the table without using `IF NOT EXISTS`, you will get the following error:

```sql
ERROR:  relation "products" already exists
```

#### Example with IF NOT EXISTS

Now, create the table using the `IF NOT EXISTS` option to avoid the error:

```sql
CREATE TABLE IF NOT EXISTS products (
  productID int,
  productName string,
  category string NOT NULL,
  price real
);
```

Using `IF NOT EXISTS` allows the query to succeed even if the table already exists.

```sql
CREATE
```


# Keywords



Below is the list of keywords that you can use in the statement:

*   ABSOLUTE
*   ACTION
*   ADD
*   AFTER
*   ALL
*   ALLOCATE
*   ALTER
*   ANALYSE
*   ANALYZE
*   AND
*   ANY
*   ARE
*   ARRAY
*   ARRAY\_MAX\_CARDINALITY
*   AS
*   ASC
*   ASENSITIVE
*   ASSERTION
*   ASYMMETRIC
*   AT
*   ATOMIC
*   AUTHORIZATION
*   BEFORE
*   BEGIN
*   BEGIN
*   BEGIN\_FRAME
*   BEGIN\_PARTITION
*   BETWEEN
*   BIGINT
*   BIT
*   BIT\_LENGTH
*   BLOB
*   BOOL
*   BOOLEAN
*   BOTH
*   BY
*   CACHE
*   CALL
*   CALLED
*   CARDINALITY
*   CASCADE
*   CASCADED
*   CASE
*   CAST
*   CATALOG
*   CEILING
*   CHAR
*   CHAR\_LENGTH
*   CHARACTER
*   CHARACTER\_LENGTH
*   CHECK
*   CLASSIFIER
*   CLOB
*   CLOSE
*   COALESCE
*   COLLATE
*   COLLATION
*   COLLECT
*   COLUMN
*   COLUMN
*   COLUMNS
*   COMMIT
*   CONDITION
*   CONNECT
*   CONNECTION
*   CONSTRAINT
*   CONSTRAINTS
*   CONTAINS
*   CONTINUE
*   CONTROL
*   CONVERT
*   COPY
*   CORR
*   CORRESPONDING
*   COVAR\_POP
*   COVAR\_SAMP
*   CREATE
*   CROSS
*   CUBE
*   CUME\_DIST
*   CURRENT
*   CURRENT\_USER
*   CURSOR
*   CYCLE
*   DATABASE
*   DATABASES
*   DATALINK
*   DATE
*   DATETIME
*   DAY
*   DEALLOCATE
*   DEC
*   DECFLOAT
*   DECIMAL
*   DECLARE
*   DEFAULT
*   DEFERRABLE
*   DEFERRED
*   DEFINE
*   DELETE
*   DELETE
*   DELTA
*   DENSE\_RANK
*   DEREF
*   DESC
*   DESCRIBE
*   DESCRIPTOR
*   DETERMINISTIC
*   DIAGNOSTICS
*   DIRECT
*   DISCONNECT
*   DISTINCT
*   DLNEWCOPY
*   DLPREVIOUSCOPY
*   DLURLCOMPLETE
*   DLURLCOMPLETEONLY
*   DLURLCOMPLETEWRITE
*   DLURLPATH
*   DLURLPATHONLY
*   DLURLPATHWRITE
*   DLURLSCHEME
*   DLURLSERVER
*   DLVALUE
*   DO
*   DOMAIN
*   DOUBLE
*   DROP
*   DYNAMIC
*   EACH
*   ELEMENT
*   ELSE
*   EMPTY
*   END
*   END\_FRAME
*   END\_PARTITION
*   EQUALS
*   ESCAPE
*   EVERY
*   EXCEPT
*   EXCEPTION
*   EXEC
*   EXECUTE
*   EXISTS
*   EXP
*   EXPLAIN
*   EXTERNAL
*   EXTRACT
*   FALSE
*   FETCH
*   FILE
*   FILTER
*   FIRST
*   FIRST\_VALUE
*   FLOAT
*   FLOOR
*   FOR
*   FOREIGN
*   FORMAT
*   FOUND
*   FRAME\_ROW
*   FREE
*   FROM
*   FULL
*   FUNCTION
*   FUSION
*   GET
*   GLOBAL
*   GO
*   GOTO
*   GRANT
*   GROUP
*   GROUPING
*   GROUPS
*   HASH
*   HAVING
*   HINT
*   HOLD
*   HOUR
*   IDENTITY
*   IF
*   ILIKE
*   IMMEDIATE
*   IMPORT
*   IN
*   INDEX
*   INDEX
*   INDICATOR
*   INITIAL
*   INITIALLY
*   INNER
*   INOUT
*   INPUT
*   INSENSITIVE
*   INSERT
*   INT
*   INTEGER
*   INTERSECT
*   INTERSECTION
*   INTERVAL
*   INTO
*   IS
*   ISNULL
*   ISOLATION
*   JOIN
*   JSON
*   JSON\_ARRAY
*   JSON\_ARRAYAGG
*   JSON\_EXISTS
*   JSON\_OBJECT
*   JSON\_OBJECTAGG
*   JSON\_QUERY
*   JSON\_TABLE
*   JSON\_TABLE\_PRIMITIVE
*   JSON\_VALUE
*   JSONB
*   KEY
*   LAG
*   LANGUAGE
*   LARGE
*   LAST
*   LAST\_VALUE
*   LATERAL
*   LEAD
*   LEADING
*   LEFT
*   LEVEL
*   LIKE
*   LIKE\_REGEX
*   LIMIT
*   LISTAGG
*   LN
*   LOAD
*   LOCAL
*   LOCALTIME
*   LOCALTIMESTAMP
*   LONG
*   MEASURES
*   MEMBER
*   MERGE
*   METHOD
*   MINUS
*   MINUTE
*   MODIFIES
*   MODULE
*   MONTH
*   MULTISET
*   NAMES
*   NATIONAL
*   NATURAL
*   NCHAR
*   NCLOB
*   NEW
*   NEXT
*   NO
*   NONE
*   NOT
*   NOT
*   NTILE
*   NULL
*   NULLIF
*   NULLS
*   NVARCHAR
*   OCCURRENCES\_REGEX
*   OCTET\_LENGTH
*   OF
*   OFF
*   OFFSET
*   OLD
*   OMIT
*   ON
*   ON
*   ON
*   ONE
*   ONLY
*   OPEN
*   OPTION
*   OR
*   ORDER
*   OUT
*   OUTER
*   OUTPUT
*   OVER
*   OVERLAPS
*   OVERLAY
*   PAD
*   PARAMETER
*   PARAMETERS
*   PARTIAL
*   PARTITION
*   PATTERN
*   PER
*   PERCENT
*   PERCENT\_RANK
*   PERCENTILE\_CONT
*   PERCENTILE\_DISC
*   PERIOD
*   PERMUTE
*   PLACING
*   PLAN
*   PORTION
*   PRECEDES
*   PRECISION
*   PREPARE
*   PRESERVE
*   PRIMARY
*   PRIOR
*   PRIVILEGES
*   PROCEDURE
*   PTF
*   PUBLIC
*   RANGE
*   READ
*   READS
*   REAL
*   RECURSIVE
*   REF
*   REFERENCES
*   REFERENCING
*   REGR\_AVGX
*   REGR\_AVGY
*   REGR\_COUNT
*   REGR\_INTERCEPT
*   REGR\_R2
*   REGR\_SLOPE
*   REGR\_SXX
*   REGR\_SXY
*   REGR\_SYY
*   RELATIVE
*   RELEASE
*   RENAME
*   RESTRICT
*   RESULT
*   RETURN
*   RETURNS
*   REVOKE
*   RIGHT
*   ROLLBACK
*   ROLLUP
*   ROW
*   ROW\_NUMBER
*   ROWS
*   RUNNING
*   SAVEPOINT
*   SCHEMA
*   SCHEMA
*   SCHEMAS
*   SCOPE
*   SCROLL
*   SEARCH
*   SECOND
*   SECTION
*   SEEK
*   SELECT
*   SENSITIVE
*   SESSION
*   SESSION\_USER
*   SET
*   SET
*   SHOW
*   SIMILAR
*   SIZE
*   SKIP
*   SMALLINT
*   SOME
*   SORTED
*   SPACE
*   SPATIAL
*   SPECIFIC
*   SPECIFICTYPE
*   SQL
*   SQLCODE
*   SQLERROR
*   SQLEXCEPTION
*   SQLSTATE
*   SQLWARNING
*   START
*   STATIC
*   STDDEV\_POP
*   STDDEV\_SAMP
*   STRING
*   SUBMULTISET
*   SUBSET
*   SUCCEEDS
*   SYMMETRIC
*   SYSTEM
*   SYSTEM\_TIME
*   SYSTEM\_USER
*   TABLE
*   TABLE
*   TABLES
*   TABLESAMPLE
*   TEMPORARY
*   TEXT
*   THEN
*   TIME
*   TIMESTAMP
*   TIMESTAMP\_TRUNC
*   TO
*   TOP
*   TRAILING
*   TRANSACTION
*   TRANSLATE
*   TRANSLATE\_REGEX
*   TRANSLATION
*   TREAT
*   TRIGGER
*   TRUE
*   TRUNCATE
*   UESCAPE
*   UNION
*   UNIQUE
*   UNIQUE
*   UNKNOWN
*   UNLOAD
*   UNMATCHED
*   UNNEST
*   UPDATE
*   UPPER
*   USAGE
*   USER
*   USING
*   VALUES
*   VAR\_POP
*   VAR\_SAMP
*   VARBINARY
*   VARCHAR
*   VARIADIC
*   VARYING
*   VERSIONING
*   VIEW
*   VIRTUAL
*   WHEN
*   WHENEVER
*   WHERE
*   WIDTH\_BUCKET
*   WINDOW
*   WITH
*   WITHIN
*   WITHOUT
*   WORK
*   WRITE
*   XML
*   XMLAGG
*   XMLATTRIBUTES
*   XMLBINARY
*   XMLCAST
*   XMLCOMMENT
*   XMLCONCAT
*   XMLDOCUMENT
*   XMLELEMENT
*   XMLEXISTS
*   XMLFOREST
*   XMLITERATE
*   XMLNAMESPACES
*   XMLPARSE
*   XMLPI
*   XMLQUERY
*   XMLSERIALIZE
*   XMLTABLE
*   XMLTEXT
*   XMLVALIDATE
*   YEAR
*   ZONE


# CREATE INDEX statement



## Overview

Oxla allows creating a single index on an empty table (before any row is added to the table). This index is used to sort data on storage, ordering it using indexed columns. This greatly speeds up the scanning table, reducing the scan just to the relevant portion of data.

## Syntax

While creating an index one should define the index name, the table for which the index is created, list of columns for which the index was created.

```sql
CREATE INDEX index_name ON table_name(column_name_1, ...);
```

## Using index

The index is used when a query uses a range of values from a given index. To do that user must compare the index column with the literal.

## Performance impact

### Single column index

Let's consider the given table:

```sql
CREATE TABLE lineorder (
    customer_id              INTEGER NOT NULL,
    part_key_id              INTEGER NOT NULL,
    quantity                 INTEGER NOT NULL,
    unit_price               FLOAT NOT NULL,
    commit_date              DATE NOT NULL
);
```

Let's say we want to calculate the value of orders for 5th November 2019:

```sql
SELECT SUM(unit_price * quantity) AS revenue FROM lineorder WHERE commit_date = '2019-11-05';
```

This query will scan all data for columns unit\_price, quantity, and commit\_date for table lineorder. To speed this query up we can use the index:

```sql
CREATE INDEX lineorder_index ON lineorder(commit_date);
```

If the table was created with this index then the query mentioned above will scan just over rows for which `commit_date` is equal to 2019-11-05.

Unfortunately, expressions like the one shown below will not take advantage of the index.

```sql
SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE EXTRACT(YEAR FROM commit_date) = 2019;
```

### Multi-column index

The index might contain multiple columns. Let's consider a different index for the table line order mentioned above:

```sql
CREATE INDEX lineorder_index ON lineorder(part_key_id, commit_date);
```

Thanks to this index, extracting orders related to a given part or orders for a given part and given time range will be very fast. Example of queries taking advantage of index:

```sql
SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE part_key_id = 5;

SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE part_key_id = 5 OR part_key_id = 7;

SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE part_key_id >= 5 AND part_key_id <= 7;

SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE
    part_key_id = 5 AND
    commit_date BETWEEN '2019-11-01' AND '2019-11-15';

SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE
    part_key_id >= 5 AND part_key_id <= 7 AND
    commit_date BETWEEN '2019-11-01' AND '2019-11-15';
```

A query that will not take advantage of the index:

```sql
SELECT SUM(unit_price * quantity) AS revenue
FROM lineorder
WHERE commit_date BETWEEN '2019-11-01' AND '2019-11-15';
```


# SELECT statement



## Overview

The `SELECT` statement helps you obtain the data you need from one or more tables.&#x20;

The application of this statement will be helpful in several cases listed below:

*   Evaluating data from only particular fields in a table.

*   Reviewing data from several tables at the same time.

*   Retrieving the data based on specific criteria.

## Syntax

To request data from a table using the `SELECT` statement, you can use the following syntax:

```sql
SELECT * FROM table_name;
```

You are allowed to filter the table by column. Refer to the syntax below.

```sql
SELECT column1, column2, ...
FROM table_name;
```

We will define each syntax as follows.

*   `SELECT` determines the data we need from the database or a table.

*   `*` referred to as ***select star*** or ***asterisk*** or represents ***all***. It defines that the query should return all columns of the queried tables.

*   `FROM` clause indicates the table(s) to retrieve data from.

*   `table_name` represents the table(s) name.

*   `column1, column2, ...` these are used to specify the columns from where we want to retrieve the data.

<Info>The `SELECT` statement is case insensitive, which means `select` **or** `SELECT` has the same result.</Info>

## Examples

We have a table named **student\_data** that stores the id, name, and where the student lives.

```sql
CREATE TABLE student_data (
  id int,
  name string,
  domicile string
);
INSERT INTO student_data 
    (id, name, domicile) 
VALUES 
    (119291,'Jordan','Los Angeles'),
    (119292,'Mike','Melbourne'),
    (119293,'Will','Sydney');
```

<Check>All the examples below are executed in the `public` schema. You can also display table from another specific schema. Click [here](https://docs.oxla.com/3-sql-reference/schema) for more info.</Check>

### #Case 1: Query data from all columns

1.  In the first case, we want to display all the data from the **student\_data** table. Please refer to the syntax below:

```sql
SELECT * FROM table_name;
```

2.  Use the `SELECT` statement within the table name to get all the data:

```sql
SELECT * FROM student_data;
```

3.  If you have successfully run the query, you will get all the data from the **student\_data** table.

```sql
+--------+----------+----------------+
| id     | name     | domicile       |
+--------+----------+----------------+
| 119291 | Jordan   | Los Angeles    | 
| 119292 | Mike     | Melbourne      |
| 119293 | Will     | Sydney         |
+--------+----------+----------------+
```

### #Case 2: Query data from specific columns

1.  We want to get the list of students' names with their IDs. Please refer to the syntax below:

```sql
SELECT column_1, column_2 FROM table_name;
```

2.  Run the following query:

```sql
SELECT id, name FROM student_data;
```

3.  If you have successfully run the query, you will get a list of students' IDs & names from the **student\_data** table.

```sql
+--------+----------+
| id     | name     | 
+--------+----------+
| 119291 | Jordan   | 
| 119292 | Mike     |
| 119293 | Will     | 
+--------+----------+
```

### #Case 3: Query data from a specific column with the condition

1.  If we have a large number of data, skimming for the desired data will require a long time. We can apply some conditions to the `SELECT` statement. Please refer to the syntax below:

```sql
SELECT column_1 FROM table_name WHERE condition;
```

2.  Let's say we want to know the student's name who lives in Sydney, have a look and run the query below:

```sql
SELECT name FROM student_data WHERE domicile='Sydney';
```

3.  If you have successfully run the query, we now know that Will lives in Sydney.

```sql
+----------+ 
| name     | 
+----------+
| Will     | 
+----------+
```


# INSERT INTO statement



## **Overview**

The `INSERT INTO` statement adds new rows to an existing table using a `SELECT` statement or explicitly stating input values.

## **Syntax**

The basic syntax for `INSERT INTO` is as follows:

```sql
INSERT INTO table_name[(columns_order)] VALUES (value 1), (value 2), ... (value n);
```

or

```sql
INSERT INTO table_name[(columns_order)] select_statement; 
```

Where:

*   `table_name`: The table name.

*   `(columns_order)`: Optional column order in the table.

*   `select_statement`: A `SELECT` statement that provides the data to insert. For example, `SELECT (value 1), (value 2), ... (value n);`.

## **Examples**

### **Case #1: Basic Usage**

Let's create a distance table.&#x20;

```sql
CREATE TABLE distance_table (distance INT, unit TEXT);
```

We'll then insert values representing different distance measurements.

```sql
INSERT INTO distance_table (distance, unit) VALUES
    (2000, 'kilometers'),
    (1000, 'meters'),
    (5, 'miles');
```

Display the table using the query below.

```sql
SELECT * FROM distance_table;
```

You’ll get the following output.

```sql
 distance |    unit    
----------+------------
     2000 | kilometers
     1000 | meters
        5 | miles
```

### **Case #2: Switching Column Orders**

In this example, we create a `weight` table with columns `kilo` and `gram`. Then, we add data using the default column order (`kilo`, `gram`).

```sql
CREATE TABLE weight(kilo INT, gram INT);
INSERT INTO weight SELECT 45, 52;
```

Next, we insert data with a switched column order (`gram`, `kilo`).

```sql
INSERT INTO weight(gram, kilo) SELECT 45, 52;
```

Let’s see what’s on the table.

```sql
SELECT * FROM weight;
```

The output displays the first row with data from the default column order and the second row with reversed data from the switched column order.

```sql
 kilo | gram 
------+------
   45 |   52
   52 |   45
```

### **Case #3: Inserting with a NULL Column**

In this case, we only insert data into a `gram` column while leaving the `kilo` column as NULL.

```sql
CREATE TABLE weight(kilo INT, gram INT);
INSERT INTO weight(gram) SELECT 45;
```

Display the table.

```sql
SELECT * FROM weight;
```

The output shows the first column (`kilo`) as NULL.

```sql
kilo  | gram 
------+------
      |  45 
```

### **Case #4: Error Handling - Too Many Values**

In this case, an error occurs when attempting to insert more values than the specified columns in the table.

```sql
CREATE TABLE weight(kilo INT, gram INT);
INSERT INTO weight SELECT 45, 52, 30;
```

The error result indicates that the table `weight` has only 2 columns.

```sql
ERROR:  INSERT has more expressions than target columns
```

### **Case #5: Error Handling - Inserting NULL into a Not-Nullable Column**

In this example, you insert data into a `gram` column and a NULL value into a `kilo` column.

```sql
CREATE TABLE weight(kilo INT, gram INT);
INSERT INTO weight(gram) SELECT 30;
```

You will get an error result as you try to input data only in the `gram` column, leaving the `kilo` column empty, where there is a NOT NULL constraint.

```sql
ERROR:  null value in column "kilo" of relation "weight" violates not-null constraint
```


# DROP statement



# Overview

In this section, we will learn how to delete the data from a table using the `DROP` statement.

<Warning>Running a `DROP` statement will also delete all existing records from the table.</Warning>

# Syntax

The basic syntax for the `DROP` statement is as follows:

```sql
DROP TABLE [IF EXISTS] table_name;
```

In this syntax:

*   `table_name` defines which table you want to remove.
*   `IF EXISTS` is an optional parameter used to ensure no error occurs if the table does not exist.

<Tip>The `DROP` example below is executed in the `public` schema. You can also drop a table from another specific schema. Click [here](https://docs.oxla.com/3-sql-reference/schema) for more info.</Tip>

# Examples

## Case #1: Dropping the Table

1.  Use the following query to create the table.

```sql
CREATE TABLE warehouse (
  id int,
  product string,
  qty int
);
INSERT INTO warehouse 
    (id, product, qty) 
VALUES 
    (889771,'Shirt',22),
    (777821,'Hat',99),
    (103829,'Bed Cover',12);
```

2.  We can then use the SELECT statement to view the data in the table:

```sql
 SELECT * FROM warehouse;
```

It will generate the following result:

```sql
+---------+------------+---------+
| id      | product    | qty     | 
+---------+------------+---------+
| 889771  | Shirt      | 22      |
| 777821  | Hat        | 99      |
| 103829  | Bed Cover  | 12      |
+---------+------------+---------+
```

3.  To delete the **warehouse** table and all its data, we can use the following query:

```sql
DROP TABLE warehouse;
```

4.  If the query is executed successfully, we will get the following output:

```sql
DROP TABLE

Query returned successfully in 284 msec.
```

<Note>If you attempt to use the table for any operation, you will find that the table no longer exists.</Note>

## Case #2: Dropping the Table using IF EXISTS

IF EXISTS can be used to prevent errors when dropping the table if the table does not exist.

### Example without IF EXISTS

1.  First, drop the table without using the `IF EXISTS` option.

```sql
DROP TABLE warehouse;
```

Output:

```sql
DROP
```

2.  If you attempt to drop the table again without using IF EXISTS, it will result in an error.

```sql
DROP TABLE warehouse;
```

Output:

```sql
ERROR:  relation "warehouse" does not exist
```

### Example with IF EXISTS

Now, drop the table using the IF EXISTS.

```sql
DROP TABLE IF EXISTS warehouse;
```

The drop operation proceeds without errors even if the table doesn't exist.

```sql
DROP
```


# SHOW TABLES statement



## Overview

`Show` statements allow you to obtain information about existing tables.

## Example

Execute the following query to list all available tables:

```sql
SHOW TABLES;
```

This might produce an output with a list of all existing tables as shown below:

```sql
+------------+
| name       |  
+------------+
| lineorder  |
| part       | 
| customer   | 
| supplier   | 
+------------+
```


# DESCRIBE statement



## Overview

`Describe` statement show columns within a table and tables within a database.&#x20;

<Check>The `Describe` statement is recommended to use before creating a new table to avoid duplicate tables.</Check>

## **Syntax**

### Describe Database

Below is the basic syntax for describing tables within a database:

```sql
DESCRIBE DATABASE;
```

### Describe Table

Below is the basic syntax for describing columns within a table:

```sql
DESCRIBE TABLE table_name;
```

`table_name` is the name of the table that you want to show.

## Examples

To get a better understanding of a `DESCRIBE` statement, take a look at some examples below:

### Case #1: Describe Table

1.  In this example, we will figure out the columns of a **part** table. Run the query below:

```sql
DESCRIBE TABLE part;
```

2.  As a result, you will get a list of column names, column types, and nullable options from the **part** table.

```sql
+----------------+------------+-------------+-------+----------+ 
| database_name  | table_name |    name     | type  | nullable |
+----------------+------------+-------------+-------+----------+
| public         | part       | p_partkey   | INT   | f        |
| public         | part       | p_name      | TEXT  | f        |
| public         | part       | p_mfgr      | TEXT  | f        |
| public         | part       | p_category  | TEXT  | f        |
| public         | part       | p_brand     | TEXT  | f        |
| public         | part       | p_color     | TEXT  | f        |
| public         | part       | p_type      | TEXT  | f        |
| public         | part       | p_size      | INT   | f        |
| public         | part       | p_container | TEXT  | f        |
+----------------+------------+-------------+-------+----------+

```

<Check>The example above shows that the tables reside in the `public` schema, the default schema in Oxla. You can also have a table from other schemas - click [here](https://oxla.mintlify.app/3-sql-reference/schema) for more info.</Check>

### Case #2: Describe Database

1.  Execute the following query to describe the database:

```sql
DESCRIBE DATABASE;
```

2.  You will retrieve a list of the existing tables in the database as shown below:

```sql
+-----------------------------+
| name                        | 
+-----------------------------+
| supplier_scale_1_no_index   | 
| features                    | 
| orders                      | 
| features2                   | 
| featurestable               | 
| featurestable1              | 
| featurestable10             | 
+-----------------------------+
```


# SHOW NODES statement



## **Overview**

The `SHOW NODES` returns the current state of the cluster.&#x20;

<Info>The `SHOW NODES` statement is not case-sensitive. So, `show nodes`, `Show Nodes`, and `SHOW NODES` all do the same thing.</Info>

## **Example**

To view the current cluster state, execute the following statement:

```sql
SHOW NODES;
```

You'll see a table with information about each node in the cluster like this:

```sql
     name      | election_state  | followers_count | connected_nodes_count | degradation_error 
---------------+-----------------+-----------------+-----------------------+-------------------
 n_oxla_node_1 | LEADER_FOLLOWER |               0 |                     3 | 
 n_oxla_node_3 | LEADER          |               3 |                     3 | 
 n_oxla_node_2 | LEADER_FOLLOWER |               0 |                     3 | 
(3 rows)
```

Each row represents the state of an individual node within the cluster.

*   `name`: The name of the node.

*   `election_state`:  The current state of the node (e.g., LEADER). Leader node oversees whole cluster.

*   `followers_count`: Number of nodes following the leader which applies to the leader node.

*   `connected_nodes_count`: Total nodes connected, including itself.

*   `degradation_error`: Shows an error message if the node is not working correctly; otherwise, it shows NULL.


# Overview



## What is a Statement? 🤨

A statement refers to a single SQL operation or a set of operations that are performed together. Statements include queries, but also a broader set of operations, such as: Retrieve, Add, Update, or Delete Data.

## How does a Statement work? 🧐

A statement is like a command or request you give someone, such as "Find all the details about my favorite book." In Oxla, this would be a `SELECT` statement.&#x20;

When you run a statement in Oxla, the command is processed and the requested operation is performed. This statement can affect the data stored in the table or change the database structure.

***

The following articles will explain the statements that we support, with examples:

<CardGroup cols={4}>
  <Card title="CREATE TABLE Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-2-create-table-statement/create-table">
    Learn more
  </Card>

  <Card title="CREATE INDEX Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-3-create-index-statement/create-index">
    Learn more
  </Card>

  <Card title="DROP Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-6-drop-statement/drop">
    Learn more
  </Card>

  <Card title="SELECT Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-4-select-statement/select">
    Learn more
  </Card>

  <Card title="INSERT INTO Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-5-insert-into-statement/insert-into">
    Learn more
  </Card>

  <Card title="SHOW TABLES Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-7-show-tables-statement/show-tables">
    Learn more
  </Card>

  <Card title="DESCRIBE Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-8-describe-statement/describe">
    Learn more
  </Card>

  <Card title="SHOW NODES Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-9-show-nodes-statement/show-nodes">
    Learn more
  </Card>

  <Card title="SET/SHOW Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-10-set-show-statement/set-show">
    Learn more
  </Card>

  <Card title="COPY FROM Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-11-copy-from-statement/copy-from">
    Learn more
  </Card>

  <Card title="COPY TO Statement" href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-12-copy-to-statement/copy-to">
    Learn more
  </Card>
</CardGroup>


# SQL TABLE



## What is a TABLE?

A table is a collection of data organized in rows and columns.

<Note>A table has a specified number of columns but can have any number of rows.</Note>

## How does a TABLE work?

You may easily create data for real-time analysis and reporting by using the statement TABLE. It can connect datasets, filter datasets, apply SQL functions, batch together datasets (union), and more.

In tables, data is systematically arranged in a row-and-column structure like a spreadsheet. Each column represents a record field, and each row represents a detailed record.&#x20;

Let's see an example of a **library** table:

| **book\_ID** | **book\_Name**         | **book\_Author** |
| ------------ | ---------------------- | ---------------- |
| 00001        | The Catcher in the Rye | J. D. Salinger   |
| 00002        | Anna Karenina          | Leo Tolstoy      |

In the above table:

*   "**library**" is the table's name.

*   "**book\_ID**", "**book\_Name**" and "**book\_Author**" are the names of columns.&#x20;

*   The combination of data from multiple columns creates a row, e.g. (00002, "Anna Karenina,” and “Leo Tolstoy").

## What can we do with the TABLE?

You can perform various operations using a table. We do support some of the table operations, such as:

1.  [Create a new table.](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-2-create-table-statement/create-table)

2.  [Delete an existing table.](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-6-drop-statement/drop)

3.  [Display a list of data from an existing table.](https://docs.oxla.com/3-sql-reference/3-1-sql-statements/3-1-4-select-statement/select)

4.  Display a list of data from tables using 'join'.
    And many more…💨

<Info>By default, the table will be created in the `public` schema. Furthermore, you can also create and specify tables to other specific schemas. Click [here](https://docs.oxla.com/3-sql-reference/schema) for more info.</Info>


# FROM



## Overview

The `FROM` clause is used to specify which table or joins are required for the query/statement (e.g., `SELECT `statement) to return or obtain data.

## Syntax

There must be at least one table listed in the `FROM` clause. See the following syntax:

```sql
query FROM table_name;
```

If two or more tables are listed in the `FROM` clause, these tables are joined using [JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/join), [RIGHT JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/right-join), [LEFT JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/left-join), or [OUTER JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/outer-join), depending on the operations to be queried as seen in the syntax below:

```sql
FROM table1_name
[ { JOIN
  | LEFT JOIN
  | RIGHT JOIN
  | OUTER JOIN } table2_name
ON table1_name.column1 = table2_name.column1 ]
```

<Note>The examples below are executed in the `public` schema, the default schema in Oxla. You can also create, insert, and display a table from other schemas - click [here](https://docs.oxla.com/3-sql-reference/schema) for more info.</Note>

## Example

We'll start by looking at how to use the `FROM` clause with only a single table.

There is a **client** table, and we want to know the client’s name and the city where the company is based.

```sql
CREATE TABLE client (
  client_id int,
  client_name string,
  client_origin string
);
INSERT INTO client 
    (client_id, client_name, client_origin) 
VALUES 
    (181891,'Oxla','Poland'),
    (181892,'Google','USA'),
    (181893,'Samsung','South Korea');
```

```sql
SELECT * FROM client;
```

It will create a table as shown below:

```sql
+------------+--------------+------------------+
| client_id  | client_name  | client_origin    |
+------------+--------------+------------------+
| 181891     | Oxla         | Poland           |
| 181892     | Google       | USA              | 
| 181893     | Samsung      | South Korea      |
+------------+--------------+------------------+
```

1.  Run the following query:

```sql
SELECT client_name, client_origin FROM client;
```

2.  You will get a list of the client’s data for a successful result:

```sql
+--------------+------------------+
| client_name  | client_origin    |
+--------------+------------------+
| Oxla         | Poland           |
| Google       | USA              | 
| Samsung      | South Korea      |
+--------------+------------------+
```

<Check>If two or more tables are listed in the FROM clause, please refer to these sections for more examples related to this: [JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/join), [RIGHT JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/right-join), [LEFT JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/left-join), or [OUTER JOIN](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/outer-join).</Check>

## FROM - Sub Queries

FROM clause is also used to specify a sub-query expression. The relation created from the sub-query is then used as a new relation on the other query.&#x20;

<Info>More than one table can be defined by separating it with a comma **(,)**.</Info>

### Syntax

Here is an example of the sub-query syntax that uses a FROM clause:

```sql
SELECT X.column1, X.column2, X.column3 
FROM table_2 as X, table_1 as Y
WHERE conditions (X.column, Y.column);
```

1.  The sub-query in the first `FROM` clause will select the columns from the specific table using a new temporary relation (`SELECT X.column1, X.column2, X.column3 FROM` ).

2.  Set the tables into a new temporary relation (`table_2 as X, table_1 as Y`).

3.  Next, the query is evaluated, selecting only those rows from the temporary relation that fulfill the conditions stated in the `WHERE` clause.

### Example

We want to find a product whose price exceeds all categories' average budget. 

&#x20;                                                                        **product table**

```sql
CREATE TABLE product (
  id int,
  product string,
  category string,
  price int
);
INSERT INTO product 
    (id, product, category, price) 
VALUES 
    (445747,'Court vision women’s shoes nike','Shoes', 8000),
    (445641,'Disney kids h&m','Shirt', 6500),
    (477278,'Defacto adidas','Hat', 8500),
    (481427,'Sophie shopping bag','Bag', 6500),
    (411547,'Candy skirt zara','Skirt', 6500),
    (488198,'Slim cut skirt hush puppies','Skirt', 7600);
```

```sql
SELECT * FROM product;
```

It will create a table as shown below:

```sql
+---------+----------------------------------+-----------+--------+
| id      | product                          | category  | price  |
+---------+----------------------------------+-----------+--------+
| 445747  | Court vision women’s shoes nike  | Shoes     | 8000   |
| 445641  | Disney kids h&m                  | Shirt     | 6500   |
| 477278  | Defacto adidas                   | Hat       | 8500   |
| 481427  | Sophie shopping bag              | Bag       | 6500   |
| 411547  | Candy skirt zara                 | Skirt     | 6500   |
| 488198  | Slim cut skirt hush puppies      | Skirt     | 7600   |
+---------+----------------------------------+-----------+--------+
```

&#x20;                                                                     **category table**

```sql
CREATE TABLE category (
  categoryName string,
  budget int
);
INSERT INTO category 
    (categoryName, budget) 
VALUES 
    ('Shoes', 7000),
    ('Shirt', 9000),
    ('Bag', 8000),
    ('Skirt', 7500),
    ('Hat', 7000);
```

```sql
SELECT * FROM category;
```

It will create a table as shown below:

```sql
+---------------+----------+
| categoryName  | budget   |
+---------------+----------+
| Shoes         | 7000     |
| Shirt         | 9000     |
| Bag           | 8000     |
| Skirt         | 7500     |
| Hat           | 7000     |
+---------------+----------+
```

***

1.  Run the following query to know and ensure the average value of all category’s budgets:

```sql
select avg(budget) as avgBudget from category;
```

2.  The average budget of all categories from the **category** table is 7700.&#x20;

```sql
+--------------------+
| avgbudget          |
+--------------------+
| 7700.000000000000  |
+--------------------+
```

3.  Now, run the following query:

*   We specify the **product** table as **P** and the budget's average value from the **category** table as C.

*   We will display the product's name, category, and price.

*   We set the conditions where the product's price exceeds the budget's average value.

```sql
select P.product, P.category, P.price from
(select avg(budget) as avgBudget from category) as C, product as P
where P.price > C.avgBudget;
```

➡️ The output will display “court vision women's shoes nike” and "Defacto adidas” as the products with a price of more than 7700.

```sql
+------------------------------------+-----------+----------+
| product                            | category  | price    |
+------------------------------------+-----------+----------+
| court vision women`s shoes nike    | shoes     | 8000     |
| Defacto adidas                     | hat       | 8500     |
+------------------------------------+-----------+----------+
```


# JOIN



## Overview

`JOIN` clause is used to create a new table by combining records and using common fields between two tables in a database.

<Check>We support table aliasing used in the `JOIN` clause.</Check>

## Syntax

### a) Basic Syntax

The following is the syntax of the `JOIN` clause:

```sql
SELECT table_1.column_1, table_2.column_2...
FROM table_1
JOIN table_2
ON table_1.common_filed = table_2.common_field
```

1.  `SELECT table_1.column_1, table_2.column_2...` will select the columns to be displayed from both tables.

2.  `FROM table_1 JOIN table_2` represents the joined tables.

3.  `ON table_1.common_filed = table_2.common_field` compares each row of table\_1 with each row of table\_2 to find all pairs of rows that meet the join-common field.

4.  When the join-common field is met, column values for each matched pair of rows from table\_1 and table\_2 are combined into a result row.

### b) Syntax with an Alias

You can use table aliasing to refer to the table’s name. An alias is a temporary name given to a table, column, or expression in a query.&#x20;

The results will stay the same, but it can help you to write the query easier.&#x20;

```sql
SELECT left.column_1, right.column_2...
FROM table_1 as left
JOIN table_2 as right
ON left.common_filed = right.common_field
```

## Examples

Before we move on, let us assume two tables:&#x20;

**movies table**

```sql
CREATE TABLE movies (
  movie_id int,
  movie_name string,
  category_id int
);
INSERT INTO movies
    (movie_id, movie_name, category_id)
VALUES
    (201011, 'The Avengers', 181893),
    (200914, 'Avatar', 181894),
    (201029, 'Shutter Island', 181891),
    (201925, 'Tune in Your Love', 181892);
```

```sql
SELECT * FROM movies;
```

It will create a table as shown below: &#x20;

```sql
+------------+-----------------------+--------------+
| movie_id   | movie_name            | category_id  |
+------------+-----------------------+--------------+
| 201011     | The Avengers          | 181893       |
| 200914     | Avatar                | 181894       |
| 201029     | Shutter Island        | 181891       |
| 201925     | Tune in Your Love     | 181892       |
+------------+-----------------------+--------------+
```

**categories table**

```sql
CREATE TABLE categories (
  id int,
  category_name string
);
INSERT INTO categories
    (id, category_name)
VALUES
    (181891, 'Psychological Thriller'),
    (181892, 'Romance'),
    (181893, 'Fantasy'),
    (181894, 'Science Fiction'),
    (181895, 'Action');
```

```sql
SELECT * FROM categories;
```

It will create a table as shown below:

```sql
+--------------+-----------------------+
| id        | category_name            |
+-----------+--------------------------+
| 181891    | Psychological Thriller   |
| 181892    | Romance                  |
| 181893    | Fantasy                  |
| 181894    | Science Fiction          |
| 181895    | Action                   |
+-----------+--------------------------+
```

***

1.  Based on the above tables, we can write a `JOIN` query as follows:

```sql
SELECT a.movie_name, c.category_name
FROM movies AS a
JOIN categories AS c
ON a.category_id = c.id;
```

2.  The above query will give the following result:

```sql
+-----------------------+---------------------------+
| movie_name            | category_name             |
+-----------------------+---------------------------+
| Shutter Island        | Psychological Thriller    |
| Tune in Your Love     | Romance                   |
| The Avengers          | Fantasy                   |
| Avatar                | Science Fiction           |
+-----------------------+---------------------------+
```

The JOIN checks each row of the **category\_id** column in the first table (**movies**) with the value in the **id** column of each row in the second table (**categories**).&#x20;

If the values are equal, it will create a new row that contains columns from both tables (**category\_name)** and adds the new row **(movie\_name)** to the result set.

Below is the Venn diagram based on the example:

![join](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/join.png)


# LEFT JOIN



## Overview

The `LEFT JOIN`returns **all** matching records from the left table combined with the right table. Even if there are no matching records in the right table, the `LEFT JOIN` will still return a row in the result, but with NULL in each column from the right table.&#x20;

<Note>`LEFT JOIN` is also known as `LEFT OUTER JOIN`.</Note>

## Syntax

<Tip>We support table aliasing used in the `LEFT JOIN` clause.</Tip>

### a) Basic Syntax

```sql
SELECT column_1, column_2...
FROM table_1
LEFT JOIN table_2
ON table_1.matching_field = table2.matching_field;
```

In the above syntax:

1.  `SELECT column_1, column_2...` defines the **columns** from both tables where we want the data to be selected.

2.  &#x20;`FROM table_1` defines the **left table** as the main table in the FORM clause.

3.  `RIGHT JOIN table_2` defines the **right table** as the table the main table joins.

4.  `ON table_1.matching_field = table2.matching_field` sets the join condition after the **ON** keyword with the matching field between the two tables.&#x20;

### b) Syntax with an Alias

You can use an alias to refer to the table’s name. The results will stay the same. It only helps to write the query easier.

```sql
SELECT A.column_1, B.column_2...
FROM table_1 A //table_1 as A
LEFT JOIN table_2 B //table_2 as B
ON A.matching_field = B.matching_field;
```

## Example

**item table**

```sql
CREATE TABLE item (
  item_no int NOT NULL,
  item_name string
);

INSERT INTO item
    (item_no,item_name)
VALUES
    (111,'Butter'),
    (113,'Tea'),
    (116,'Bread'),
    (119,'Coffee');
```

```sql
SELECT * FROM item;
```

It will create a table as shown below:

```sql
+-----------+----------------+
| item_no   | item_name      |
+-----------+----------------+
| 111       | Butter         |
| 113       | Tea            |
| 116       | Bread          |
| 119       | Coffee         |
+-----------+----------------+
```

**invoice table**

```sql
CREATE TABLE invoice (
  inv_no int NOT NULL,
  item int,
  sold_qty int,
  sold_price int
);

INSERT INTO invoice
    (inv_no, item, sold_qty, sold_price)
VALUES
    (020219,111,3,9000),
    (020220,116,6,30000),
    (020221,116,2,10000),
    (020222,116,1,5000),
    (020223,119,5,20000),
    (020224,119,4,16000);
```

```sql
SELECT * FROM invoice;
```

It will create a table as shown below:

```sql
+----------+---------+-----------+-------------+
| inv_no   | item    | sold_qty  | sold_price  |
+----------+---------+-----------+-------------+
| 20219    | 111     | 3         | 9000        |
| 20220    | 116     | 6         | 30000       |
| 20221    | 116     | 2         | 10000       |
| 20222    | 116     | 1         | 5000        |
| 20223    | 119     | 5         | 20000       |
| 20224    | 119     | 4         | 16000       |
+----------+---------+-----------+-------------+
```

***

1\) Based on the above tables, we can write a `LEFT JOIN` query as follows:

```sql
SELECT item_no, item_name, sold_qty, sold_price
FROM item
LEFT JOIN invoice
ON item.item_no = invoice.item;
```

*   The **item** = left table, and the **invoice** = right table.

*   Then it combines the values from the **item** table using the **item\_no** and matches the records using the **item** column of each row from the **invoice** table.

*   If the records are equal, a new row will be created with `item_no`, **`item_name`**, and `sold_qty`, `sold_price` columns as defined in the `SELECT` clause.

*   **ELSE** it will create a new row with a `NULL` value from the right table **(invoice)**.&#x20;

2\) The above query will give the following result:

```sql
+-----------+-------------+------------+---------------+
| item_no   | item_name   | sold_qty   | sold_price    |
+-----------+-------------+------------+---------------+
| 111       | Butter      | 3          | 9000          |
| 113       | Tea         | null       | null          |
| 116       | Bread       | 6          | 30000         |
| 116       | Bread       | 2          | 10000         |
| 116       | Bread       | 1          | 5000          |
| 119       | Coffee      | 5          | 20000         |
| 119       | Coffee      | 4          | 16000         |
+-----------+-------------+------------+---------------+
```

Based on the data from the **item** and **invoice** tables:

*   The result matches the total item stored in the **item** table: **4 items.**

*   The result will display all the item's data from the **left table (item table)**, even if there is 1 item that hasn’t been sold.

*   The item id: `111` matches the item `butter` and has been sold for 3pcs/9000.

*   The item id: `113` matches the item `tea` but has never been sold. Thus the sold\_qty & sold\_price columns are filled with: null.

*   The item id: `116` matches the item `Bread` and has been sold three times, for 6pcs/3000, 2pcs/10000, and 1pc/5000.

*   The item id: `119` matches the item `Coffee` and has been sold two times, for 5pcs/20000 and 4pcs/16000.

<Check>An **item** can have zero or many invoices. An **invoice** belongs to zero or one **item**.</Check>

The following Venn diagram illustrates the `LEFT JOIN`:

![left join](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/left-join.png)


# OUTER JOIN



## Overview

The `OUTER JOIN` **or** `FULL OUTER JOIN` returns all the records from the selected fields between the two tables (left table & right table) whether the join condition is met or not.

### **Inner Join 🆚 Outer Join**

The most significant difference between an `INNER JOIN` and an `OUTER JOIN` is that the `INNER JOIN` only returns the information from both tables which are common and related to each other. The OUTER JOIN will return all rows (matched/unmatched) from both tables.&#x20;

<Tip>We support table aliasing used in the OUTER JOIN clause.</Tip>

## Syntax

### a) Basic Syntax

```sql
SELECT column_1, column_2...
FROM table_1
FULL OUTER JOIN table_2
ON table_1.matching_field = table2.matching_field;
```

In the above syntax:

1.  `SELECT column_1, column_2...` defines the **columns** from both tables where we want to display data.

2.  `FROM table_1` represents the **left table** with table\_1 in the FROM clause.

3.  &#x20;`FULL OUTER JOIN table_2` represents the **right table** with table\_2 in the FULL OUTER JOIN condition.

4.  `ON table_1.matching_field = table2.matching_field` sets the join condition after the **ON** keyword with the matching field between the two tables.&#x20;

### b) Syntax with an Alias

You can use an alias to refer to the table’s name. The results will stay the same. It only helps to write the query easier.

```sql
SELECT A.column_1, B.column_2...
FROM table_1 A //table_1 as A
FULL OUTER JOIN table_2 B //table_2 as B
ON A.matching_field = B.matching_field;
```

<Note>If there are no matched records from the joined tables, the `NULL` values will return in every column of the table that doesn’t have the matching record.</Note>

## Example

**departments table**

```sql
CREATE TABLE departments (
	department_id int,
	department_name string
);
INSERT INTO departments (department_id,department_name)
VALUES
	(1001, 'Sales'),
	(1002, 'Marketing'),
	(1003, 'HR'),
	(1004, 'Project'),
	(1005, 'Product');
```

```sql
SELECT * FROM departments;
```

It will create a **departments** table as shown below:

```sql
+----------------+------------------+
| department_id  | department_name  |
+----------------+------------------+
| 1001           | Sales            |
| 1002           | Marketing        |
| 1003           | HR               |
| 1004           | Project          |
| 1005           | Product          |
+----------------+------------------+
```

**employee table**

```sql
CREATE TABLE employee (
	employee_id int,
	employee_name string,
	dept_id int
);
INSERT INTO employee (
	employee_id,
	employee_name,
    dept_id
)
VALUES
	(2001,'Tony Stark', 1002),
	(2002,'Christian Bale', 1002),
	(2003,'Anne Hailey', 1003),
	(2004,'Wilson Cliff', 1004),
	(2005,'Susan Oh', 1001),
	(2006,'Julian Robert', 1001),
    (2007,'Gilbert Tom', null);
```

```sql
SELECT * FROM employee;
```

It will create an **employee** table as shown below:

```sql
+--------------+-------------------+------------+
| employee_id  | employee_name     | dept_id    |
+--------------+-------------------+------------+
| 2001         | Tony Stark        | 1002       |
| 2002         | Christian Bale    | 1002       |
| 2003         | Anne Hailey       | 1003       |
| 2004         | Wilson Cliff      | 1004       |
| 2005         | Susan Oh          | 1001       |
| 2006         | Julian Robert     | 1001       |
| 2007         | Gilbert Tom       | null       |
+--------------+-------------------+------------+
```

***

### Case 1: FULL OUTER JOIN

1\) Based on the above tables, we can write an `OUTER JOIN` query as follows:

```sql
SELECT employee_name, department_name
FROM departments
FULL OUTER JOIN employee
ON departments.department_id = employee.dept_id;
```

2\) The result will show every department with an employee and the employee who works under a specific department.

3\) It also includes every department that does not have any employees and the employees who do not belong to a specific department.

```sql
+-------------------+-------------------+
| employee_name     | department_name   |
+-------------------+-------------------+
| Julian Robert     | Sales             |
| Susan Oh          | Sales             |
| Christian Bale    | Marketing         |
| Tony Stark        | Marketing         |
| Anne Hailey       | HR                |
| Wilson Cliff      | Project           |
| Gilbert Tom       | null              |
| null              | Product           |
+-------------------+-------------------+
```

The following Venn diagram illustrates the FULL OUTER JOIN:

![outer join](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/outer-join_1.png)

***

### Case 2: `FULL OUTER JOIN` with `WHERE` Clause

**a) Employee**

1.  We can look up the department that does not have any employees by adding a `WHERE` clause and `NULL` as the following query:

```sql
SELECT employee_name, department_name
FROM departments
FULL OUTER JOIN employee
ON departments.department_id = employee.dept_id
WHERE employee_name IS NULL;
```

2.  The result will indicate that the **Product** department doesn’t have any employees 👨🏻‍💼

```sql
+------------------+--------------------+
| employee_name    | department_name    |
+------------------+--------------------+
| null             | Product            |
+------------------+--------------------+
```

**b) Department**

1\) Let’s find out the employee who doesn’t belong to any department by adding a WHERE clause and NULL as the following query:&#x20;

```sql
SELECT employee_name, department_name
FROM employee
FULL OUTER JOIN departments
ON employee.dept_id = departments.department_id
WHERE department_name IS NULL;
```

2\) The result will show that **Gilbert Tom** doesn’t belong to any department 👨🏻‍💼

```sql
+------------------+--------------------+
| employee_name    | department_name    |
+------------------+--------------------+
| Gilbert Tom      | null               |
+------------------+--------------------+
```

The following Venn diagram illustrates how the FULL OUTER JOIN works for the department and employee with a null value:

![full outer join](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/full-outer-join.png)


# RIGHT JOIN



## Overview

The `RIGHT JOIN` returns **all** matching records from the right table combined with the left table. Even if there are no match records in the left table, the `RIGHT JOIN` will still return a row in the result, but with `NULL` in each column from the left table.

<Tip>We support table aliasing used in the `RIGHT JOIN` clause.</Tip>

## Syntax

### a) Basic Syntax

```sql
SELECT column_1, column_2...
FROM table_1
RIGHT JOIN table_2
ON table_1.matching_field = table2.matching_field;
```

In the above syntax:

1.  `SELECT column_1, column_2...` defines the **columns** from both tables where we want to display data.

2.  `FROM table_1`, defines the **left table** with table\_1 in the FORM clause.

3.  `RIGHT JOIN table_2` defines the **right table** with table\_2 in the RIGHT JOIN condition.

4.  `ON table_1.matching_field = table2.matching_field` sets the join condition after the **ON** keyword with the matching field between the two tables.

### b) Syntax with an Alias

You can use an alias to refer to the table’s name. The results will stay the same. It only helps to write the query easier.

```sql
SELECT A.column_1, B.column_2...
FROM table_1 A //table_1 as A
RIGHT JOIN table_2 B //table_2 as B
ON A.matching_field = B.matching_field;
```

## Example

**customer table**

```sql
CREATE TABLE customer (
  id int NOT NULL,
  customer_name string
);

INSERT INTO customer
    (id, customer_name)
VALUES
    (201011,'James'),
    (200914,'Harry'),
    (201029,'Ellie'),
    (201925,'Mary');
```

```sql
SELECT * FROM customer;
```

It will create a table as shown below:

```sql
+-----------+----------------+
| id        | customer_name  |
+-----------+----------------+
| 201011    | James          |
| 200914    | Harry          |
| 201029    | Ellie          |
| 201925    | Mary           |
+-----------+----------------+
```

**orders table**

```sql
CREATE TABLE orders (
  order_id int NOT NULL,
  order_date date,
  order_amount int,
  customer_id int
);

INSERT INTO orders
    (order_id, order_date, order_amount, customer_id)
VALUES
    (181893,'2021-10-08',3000,201029),
    (181894,'2021-11-18',2000,201029),
    (181891,'2021-10-08',9000,201011),
    (181892,'2021-10-08',7000,201925),
    (181897,'2021-10-08',6000,null),
    (181899,'2021-10-08',4500,201011);
```

```sql
SELECT * FROM orders;
```

It will create a table as shown below:

```sql
+------------+------------------+---------------+-------------+
| order_id   | order_date       | order_amount  | customer_id |
+------------+------------------+---------------+-------------+
| 181893     | 2021-10-08       | 3000          | 201029      |
| 181894     | 2021-11-18       | 2000          | 201029      |
| 181891     | 2021-09-10       | 9000          | 201011      |
| 181892     | 2021-10-10       | 7000          | 201925      |
| 181897     | 2022-05-27       | 6700          | null        |
| 181899     | 2021-07-22       | 4500          | 201011      |
+------------+------------------+---------------+-------------+
```

***

1.  Based on the above tables, we can write a `RIGHT JOIN` query as follows:

```sql
SELECT customer_name, order_date, order_amount
FROM customer
RIGHT JOIN orders
ON customer.id = orders.customer_id;
```

*   The **customer**= left table and the **orders** = right table.

*   Then it combines the values from the **orders** table using the **customer\_id** and matches the records using the **id** column from the \*\*customer \*\*table.

*   If the records are equal, a new row will be created with `customer_name` and `order_amount` columns as defined in the `SELECT` clause.

*   **ELSE** will still create a new row with a `NULL` value from the left table (**customer**).&#x20;

2.  The above query will give the following result:

```sql
+------------------+----------------+-----------------+
| customer_name    | order_date     | order_amount    |
+------------------+----------------+-----------------+
| James            | 2021-09-10     | 9000            |
| James            | 2021-07-22     | 4500            |
| Ellie            | 2021-10-08     | 3000            |
| Ellie            | 2021-11-18     | 2000            |
| Mary             | 2021-10-10     | 7000            |
| null             | 2022-05-27     | 6700            |
+------------------+----------------+-----------------+
```

Based on the data from the **customer** and **orders** tables:

*   The order id: `181893` matches the customer: `Ellie.`

*   The order id: `181894` matches the customer: `Ellie`.

*   The order id: `181891` matches the customer: `James`.

*   The order id: `181899` matches the customer: `James`.

*   The order id: `181892` matches the customer: `Mary`.

*   The order id: `181897` doesn’t match with any customer. Thus the customer\_name column is filled with: `null`.

<Info>A **customer** can have zero or many **orders**. An item from **orders** belongs to zero or one **customer**.</Info>

The following Venn diagram illustrates the `RIGHT JOIN`:

![right join](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/right-join.png)


# WHERE



## Overview

The `WHERE` clause returns a specific value from a table or multiple tables based on specified conditions. It will filter out records you do not want to be included and only returns the exact result when the condition is fulfilled.

## Syntax

The basic syntax of the WHERE clause is as follows −

```sql
SELECT column1, column2, ...
FROM table_name
WHERE [condition]
```

Let’s explore the above syntax:

*   `SELECT column1, column2, ...` defines the columns where the records will be displayed.

*   `FROM table_name` sets the table name where the records will be taken from.

*   `WHERE [condition]`specifies the search condition using comparison or logical operators (e.g., `>`, `=`, `LIKE`)

<Check>It starts with the `FROM` clause **->** then it executes the `WHERE` condition **->** after that, it will `SELECT` the specified columns.</Check>

## Examples

Let’s assume that we have a table salary with records as follows:

```sql
CREATE TABLE salary (
  empid int,
  empname string,
  empdept string,
  empaddress string,
  empsalary int
);
INSERT INTO salary 
    (empid, empname, empdept, empaddress, empsalary) 
VALUES 
    (2001,'Paul','HR', 'California', null ),
    (2002,'Brandon','Product', 'Norway', 15000),
    (2003,'Bradley','Marketing', 'Texas', null),
    (2004,'Lisa','Marketing', 'Houston', 10000),
    (2005,'Emily','Marketing', 'Texas', 20000),
    (2006,'Bobby','Finance', 'Seattle', 20000),
    (2007,'Parker','Project', 'Texas', 45000);
```

```sql
SELECT * FROM salary;
```

It will create a table as shown below:

```sql
+--------+-----------+------------+-------------+------------+
| empid  | empname   |  empdept   | empaddress  | empsalary  |
+--------+-----------+------------+-------------+------------+
| 2001   | Paul      | HR         | California  | null       |  
| 2002   | Brandon   | Product    | Norway      | 15000      |
| 2003   | Bradley   | Marketing  | Texas       | null       |
| 2004   | Lisa      | Marketing  | Houston     | 10000      |
| 2005   | Emily     | Marketing  | Texas       | 20000      |
| 2006   | Bobby     | Finance    | Seattle     | 20000      |
| 2007   | Parker    | Project    | Texas       | 45000      |
+--------+-----------+------------+-------------+------------+
```

### #Case 1: WHERE clause with `=` Operator

Here we will be using the “equal” operator to look up the employee who works in the Marketing department:

```sql
SELECT empname, empdept
FROM salary
WHERE empdept = 'Marketing';
```

The above command will create the following result:

```sql
+------------+-------------+
| empname    | empdept     |
+------------+-------------+
| Bradley    | Marketing   |
| Emily      | Marketing   | 
| Lisa       | Marketing   |
+------------+-------------+
```

<Warning>The value defined in the `WHERE` clause’s condition is **case-sensitive**, so ensure that you specify the correct and precise value.</Warning>

### #Case 2: WHERE clause with `!=` Operator

Here we will be using the “not equal” operator to look up the employee who doesn’t live in Texas:

```sql
SELECT empname, empdept, empaddress
FROM salary
WHERE empaddress != 'Texas';
```

<Info>We can use the `<>` operator for another “not equal” operator.</Info>

The above query will give the following result:

```sql
+------------+------------+--------------+
| empname    | empdept    | empaddress   |
+------------+------------+--------------+
| Paul       | HR         | California   | 
| Brandon    | Product    | Norway       | 
| Lisa       | Marketing  | Houston      |
| Bobby      | Finance    | Seattle      |
+------------+------------+--------------+
```

<Warning>The value defined in the `WHERE` clause's condition is **case-sensitive**. If you set `texas` it will return all records from the salary table. </Warning>

### #Case 3: WHERE clause with `>` Operator

Here we will be using the “greater than” operator to figure out who has a salary above 20000:

```sql
SELECT empname, empdept, empsalary
FROM salary
WHERE empsalary > 20000;
```

<Info>We can use the `<` operator for a “less than” condition.</Info>

The output will let us know that Parker has a salary greater than 20000:

```sql
+------------+------------+-------------+
| empname    | empdept    | empsalary   |
+------------+------------+-------------+
| Parker     | Project    | 45000       | 
+------------+------------+-------------+
```

### #Case 4: WHERE clause with `<=` Operator

Here we will be using the “less than or equal to” operator to see who has a salary less than or equal to 15000:

```sql
SELECT empname, empdept, empsalary
FROM salary
WHERE empsalary <= '15000';
```

<Info>We can use the `>=` operator for a “greater than or equal to” condition.</Info>

The output will let us know that Brandon has a salary equal to 15000 and Lisa has a salary of less than 15000:

```sql
+------------+------------+-------------+
| empname    | empdept    | empsalary   |
+------------+------------+-------------+
| Brandon    | Product    | 15000       | 
| Lisa       | Marketing  | 10000       |
+------------+------------+-------------+
```

### #Case 5: WHERE clause with `LIKE` Operator

Here we will use the “like” operator to retrieve the employee whose first name starts with **Br**.

```sql
SELECT * FROM salary
WHERE empname LIKE 'Br%';
```

<Info>Do the reverse to get the result based on the last string, `%string`.</Info>

We will get an output where the above query fetches **Br**andon & **Br**adley.

```sql
+---------+------------+--------------+--------------+-----------+
| empid   | empname    | empdept     | empaddress   | empsalary  |
+---------+------------+-------------+--------------+------------+
| 2002    | Brandon    | Product     | Norway       | null       |
| 2003    | Bradley    | Marketing   | Texas        | 45000      |
+---------+------------+-------------+--------------+------------+
```

### #Case 6: WHERE clause with `IS NULL` Operator

Here we will use the “is null” operator to search for the employee who doesn’t have a salary value. It will return `true` and display the result set if a value is `NULL`; otherwise, it will return `false` with no result set.

```sql
SELECT * FROM salary
WHERE empsalary IS NULL;
```

The above command will create the following result:

```sql
+---------+------------+-------------+--------------+------------+
| empid   | empname    | empdept     | empaddress   | empsalary  |
+---------+------------+-------------+--------------+------------+
| 2001    | Paul       | HR          | California   | null       |
| 2003    | Brandon    | Product     | Norway       | null       |
+---------+------------+-------------+--------------+------------+
```


# GROUP BY



## Overview

The `GROUP BY` clause returns a group of records from a table or multiple tables with the same values as the specified columns.&#x20;

The result of the `GROUP BY` clause returns a single row for each value of the column.

<Note>You can use [aggregate functions](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/aggregation-functions) such as `COUNT()`, `MAX()`, `MIN()`, `SUM()`, etc., to perform the operations on the grouped values in the `SELECT` statement.</Note>

## Syntax

<Warning>Ensure the column you are using to group is available in the column list.</Warning>

### a) Basic syntax

The basic syntax of the `GROUP BY` clause is as follows −

```sql
SELECT
column_1, column_2, aggregate_function(column_3)
FROM
table_name
GROUP BY
column_1, column_2,...;
```

Let’s explore the above syntax:

*   `SELECT column_1, column_2, aggregate_function(column_3)` defines the columns you want to group (`column_1, column_2`) and the column that you want to apply an aggregate function to (`column_3`).

*   `FROM table_name` defines the table where the data comes from.

*   `GROUP BY column_1, column_2,...;` lists the columns that you want to group in the `GROUP BY` clause.

<Info>The column specified in the `SELECT` command must also appear in the `GROUP BY` clause.</Info>

### b) Syntax with `WHERE` clause

Please take note that the `GROUP BY` clause must precisely appear after the `WHERE` clause, as shown below:

```sql
SELECT
column_1, column_2, aggregate_function(column_3)
FROM
table_name
WHERE
conditions
GROUP BY
column_1, column_2,...;
```

## Examples

Let’s assume that we have two tables here, the customer table and the orders table:

**customer table**

```sql
CREATE TABLE customer (
  cust_id int,
  cust_name string
);
INSERT INTO customer 
    (cust_id, cust_name) 
VALUES 
    (11001, 'Maya'),
    (11003, 'Ricky'),
    (11009, 'Sean'),
    (11008, 'Chris'),
    (11002, 'Emily'),
    (11005, 'Rue'),
    (11007, 'Tom'),
    (11006, 'Casey');
```

```sql
SELECT * FROM customer;
```

It will create a table as shown below:

```sql
+-----------+------------+
| cust_id   | cust_name  |
+-----------+------------+
| 11001     | Maya       |
| 11003     | Ricky      |
| 11009     | Sean       |
| 11008     | Chris      |
| 11002     | Emily      |
| 11005     | Rue        |
| 11007     | Tom        |
| 11006     | Casey      |
+-----------+------------+
```

| orders table |
| ------------ |

```sql
CREATE TABLE orders (
  order_id int,
  order_date date,
  order_prod string,
  order_qty int,
  order_price int,
  cust_id int
);
INSERT INTO orders 
    (order_id, order_date, order_prod, order_qty, order_price, cust_id) 
VALUES 
    (999191, '2021-01-08','Butter', 1, 4000, 11001),
    (999192, '2021-09-30','Sugar', 1, 10000, 11002),
    (999193, '2021-04-17','Sugar', 1, 10000, 11009),
    (999194, '2021-08-29','Flour', 4, 20000, 11006),
    (999195, '2021-05-04','Sugar', 2, 20000, 11008),
    (999196, '2021-07-27','Butter', 2, 8000, 11006),
    (999197, '2021-10-30','Flour', 2, 10000, 11001),
    (999198, '2021-12-18','Flour', 2, 10000, 11007);
```

```sql
SELECT * FROM orders;
```

It will create a table as shown below:

```sql
+------------+--------------+--------------+-------------+---------------+-----------+
| order_id   | order_date   | order_prod   | order_qty   | order_price   | cust_id   |
+------------+--------------+--------------+-------------+---------------+-----------+
| 999191     | 2021-01-08   | Butter       | 1           |  4000         | 11001     |
| 999192     | 2021-09-30   | Sugar        | 1           | 10000         | 11002     |
| 999193     | 2021-04-17   | Sugar        | 1           | 10000         | 11009     |
| 999194     | 2021-08-29   | Flour        | 4           | 20000         | 11006     |
| 999195     | 2021-05-04   | Sugar        | 2           | 20000         | 11008     |
| 999196     | 2021-07-27   | Butter       | 2           | 8000          | 11006     |
| 999197     | 2021-10-30   | Flour        | 2           | 10000         | 11001     |
| 999198     | 2021-12-18   | Flour        | 2           | 10000         | 11007     |
+------------+--------------+--------------+-------------+---------------+-----------+
```

### #Case 1: Basic `GROUP BY`

Here we will get all product names by grouping them using the products ordered from the **orders** table:

```sql
SELECT order_prod
FROM orders
GROUP BY order_prod;
```

The query above will return the output as below:

```sql
+--------------+
| order_prod   |
+--------------+
| flour        |
| sugar        |
| butter       |
+--------------+
```

### #Case 2: `GROUP BY` on Multiple Columns

The following example uses multiple columns in the `GROUP BY` clause:

```sql
SELECT order_id, order_prod
FROM orders
GROUP BY order_id, order_prod;
```

The above query will create the following result:

```sql
+-----------+--------------+
| order_id  | order_prod   |
+-----------+--------------+
| 999194    | flour        |
| 999191    | butter       |
| 999196    | flour        |
| 999192    | sugar        |
| 999195    | butter       |
| 999198    | sugar        |
| 999193    | flour        |
| 999197    | sugar        |
+-----------+--------------+
```

### #Case 3: `GROUP BY` with Aggregate Functions

For this example, we will calculate the total amount each customer has paid for their orders. We will use one of the aggregate functions, i.e., the `SUM()` function.

```sql
SELECT cust_id, SUM (order_price)
FROM orders
GROUP BY cust_id;
```

The query above will return the output as shown below:

```sql
+-----------+----------+
| cust_id   | sum      |
+-----------+----------+
| 11009     | 10000    |
| 11007     | 10000    |
| 11006     | 28000    |
| 11002     | 10000    |
| 11001     | 14000    |
| 11008     | 20000    |
+-----------+----------+
```

### #Case 4: `GROUP BY` with `JOIN` Condition

Unlike the previous example, the following query joins the orders table with the customer table and groups customers by their names. Here we will use `COUNT()` as the aggregate function to count the number of products each customer has purchased.

```sql
SELECT C.cust_name, COUNT (order_prod)
FROM orders O
JOIN customer C ON O.cust_id = C.cust_id
GROUP BY C.cust_name;
```

The above command will create the following result:

```sql
+------------+---------+
| cust_name  | count   |
+------------+---------+
| Tom        | 1       |
| Chris      | 1       |
| Casey      | 2       |
| Maya       | 2       |
| Sean       | 1       |
| Emily      | 1       |
+------------+---------+
```

### #Case 5: `GROUP BY` with Date Data Type

The `order_date` column uses a `DATE` data type. In this example, we will group the order’s quantity and total price by dates using the `DATE()` function.

```sql
SELECT DATE(order_date), order_qty, SUM(order_price)
FROM orders
GROUP BY order_qty, DATE(order_date);
```

The above query will generate the following result:

```sql
+---------------+------------+---------+
| date          | order_qty  | sum     |
+---------------+------------+---------+
| 2021-07-27    | 2          | 8000    |
| 2021-08-29    | 4          | 20000   |
| 2021-04-17    | 1          | 10000   |
| 2021-09-30    | 1          | 10000   |
| 2021-05-04    | 2          | 20000   |
| 2021-01-08    | 1          | 4000    |
| 2021-12-18    | 2          | 10000   |
| 2021-10-30    | 2          | 10000   |
+---------------+------------+---------+
```


# HAVING



## Overview

The `HAVING` clause specifies a search condition by using an [aggregate function](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/aggregation-functions). It will filter out the records returned from a `GROUP BY` clause that do not fulfill a specified condition.

### Differences Between WHERE and HAVING Clause

The following table will illustrate the differences between the `HAVING` and `WHERE` clause:

| **WHERE**                                                 | **HAVING**                                               |
| --------------------------------------------------------- | -------------------------------------------------------- |
| The `GROUP BY` clause appears after the WHERE clause.     | The `GROUP BY` clause appears before the HAVING clause.  |
| The `WHERE` clause can’t work with an aggregate function. | The `HAVING` clause can work with an aggregate function. |
| The `WHERE` clause filters particular records.            | The `HAVING` clause filters the group of records.        |

## Syntax

The basic syntax of the `GROUP BY` clause is as follows:

```sql
SELECT column_1, column_2,...
FROM table_name
GROUP BY column_name(s)
HAVING condition_aggregate_function
```

Let’s explore the above syntax:

*   `SELECT column_1, column_2,...` selects the columns you want to display.

*   `FROM table_name` selects the table where the data comes from.

*   `GROUP BY column_name(s) ` lists the columns you want to group in the GROUP BY clause.

*   `HAVING condition_aggregate_function` provides the condition for filtering rows, which the `GROUP BY` clause forms. The condition can use an aggregate function, such as `SUM()`, `COUNT()`, `MIN()`, and so on.

## Examples

Let’s assume that we have two tables here, the student table and the score table:

**student table**

```sql
CREATE TABLE student (
  stud_id int,
  stud_name string
);
INSERT INTO student 
    (stud_id, stud_name) 
VALUES 
    (992831192, 'Mary'),
    (992811191, 'Bobby'),
    (992311195, 'Sean'),
    (998311193, 'Harry'),
    (998311194, 'William'),
    (928311197, 'Kate'),
    (928311190, 'Tom'),
    (928311199, 'Sully'),
    (998311196, 'Susan');
```

```sql
SELECT * FROM student;
```

It will create a table as shown below:

```sql
+------------+------------+
| stud_id    | stud_name  |
+------------+------------+
| 992831192  | Mary       |
| 992811191  | Bobby      |
| 992311195  | Sean       |
| 998311193  | Harry      |
| 998311194  | William    |
| 928311197  | Kate       |
| 928311190  | Tom        |
| 928311199  | Sully      |
| 998311196  | Susan      |
+------------+------------+
```

**score table**

```sql
CREATE TABLE score (
  score_id int,
  subject string,
  score_val int,
  stud_id int,
  score_stat string
);
INSERT INTO score 
    (score_id, subject, score_val, stud_id, score_stat) 
VALUES 
    (12221, 'Math', 90, 992811191, 'PASSED'),
    (12222, 'Biology', 90, 992811191, 'PASSED'),
    (12223, 'Art', 80, 992831192, 'PASSED'),
    (12224, 'History', 70, 928311197, 'FAILED'),
    (12225, 'Pyshics', 75, 928311190, 'FAILED'),
    (12226, 'Art', 85, 928311197, 'PASSED'),
    (12227, 'Biology', 90, 998311196, 'PASSED'),
    (12228, 'Biology', 70, 928311199, 'FAILED'),
    (12229, 'Pyshics', 80, 998311194, 'PASSED'),
    (12231, 'Math', 80, 998311193, 'PASSED'),
    (12232, 'History', 90, 992811191, 'PASSED'),
    (12233, 'Math', 70, 998311194, 'FAILED'),
    (12234, 'Math', 80, 928311190, 'PASSED');
```

```sql
SELECT * FROM score;
```

It will create a table as shown below:

```sql
+-----------+----------+------------+------------+-------------+
| score_id  | subject  | score_val  |  stud_id   | score_stat  |
+-----------+----------+------------+------------+-------------+
| 12221     | Math     | 90         | 992811191  | PASSED      |
| 12222     | Biology  | 90         | 992811191  | PASSED      |
| 12223     | Art      | 80         | 992831192  | PASSED      |
| 12224     | History  | 70         | 928311197  | FAILED      |
| 12225     | Pyshics  | 75         | 928311190  | FAILED      |
| 12226     | Art      | 85         | 928311197  | PASSED      |
| 12227     | Biology  | 90         | 998311196  | PASSED      |
| 12228     | Biology  | 70         | 928311199  | FAILED      |
| 12229     | Pyshics  | 80         | 998311194  | PASSED      |
| 12231     | Math     | 80         | 998311193  | PASSED      |
| 12232     | History  | 90         | 992811191  | PASSED      |
| 12233     | Math     | 70         | 998311194  | FAILED      |
| 12234     | Math     | 80         | 928311190  | PASSED      |
+-----------+----------+------------+------------+-------------+
```

### #Case 1: `HAVING` Clause with `AVG` Function

The following example uses an `AVG` aggregate function to filter the student ID with the subject which has an average score of more than 80:

```sql
SELECT subject
FROM score
GROUP BY subject
HAVING AVG (score_val) > 80;
```

The above query will give the following result:

```sql
+-----------+
| subject   |
+-----------+
| Art       |
| Biology   |
+-----------+
```

### #Case 2: `HAVING` Clause with `COUNT` Function

The following query lists the number of score statuses that have more than 2 “**PASSED**” values:

```sql
SELECT COUNT(score_id), subject
FROM score
GROUP BY subject
HAVING COUNT(score_stat = 'PASSED') > 2;
```

The above query will show that **Math** and **Biology** have more than 2 “**PASSED**” values:

```sql
+--------+--------------+
| count  | subject      |
+--------+--------------+
| 4      | Math         |
| 3      | Biology      |
+--------+--------------+
```

### #Case 3: `HAVING` Clause with `MAX` Function

Let’s assume that the minimum score criteria is **75**.
Here we will find the maximum score of each subject with the condition that it should be more than **75**.

```sql
SELECT subject, MAX(score_val)
FROM score
GROUP BY subject
HAVING MAX(score_val)>75;
```

The returned result will have the maximum score of each subject, as shown below:

```sql
+-----------+--------+
| subject   | max    |
+-----------+--------+
| Math      | 90     |
| History   | 90     |
| Physics   | 80     |
| Art       | 85     |
| Biology   | 90     |
+-----------+--------+
```

### #Case 4: `HAVING` with `JOIN` Condition

Assume that you want to know which students have failed in their subject.

You can combine the **student** table with the **score** table using the `JOIN` clause and apply a condition on the `score_stat` column where the values should be equal to **FAILED**, as shown in the following query:

```sql
SELECT stud_name, subject, score_val, score_stat
FROM student A
JOIN score C ON A.stud_id = C.stud_id
GROUP BY stud_name, subject, score_val, score_stat
HAVING score_stat = 'FAILED';
```

*   The `JOIN` clause will combine the two tables.

*   Then, the `GROUP BY` clause will filter all records from both tables based on the specified columns.

*   The `HAVING` clause, then, will filter the records returned from the `GROUP BY` clause according to the specified condition.

It will deliver the successful result as shown below:

```sql
+------------+------------+------------+--------------+
| stud_name  | subject    | score_val  | score_stat   |
+------------+------------+------------+--------------+
| Kate       | History    | 70         | FAILED       |
| Sully      | Biology    | 70         | FAILED       |
| Tom        | Physics    | 75         | FAILED       |
| William    | Math       | 70         | FAILED       |
+------------+------------+------------+--------------+
```


# ORDER BY



## Overview

The `ORDER BY` clause is used to sort rows of the result received from a `SELECT` statement, which retrieves records from one or more tables.

## Syntax

The following illustrates the syntax of the `ORDER BY` clause:

```sql
SELECT columns
FROM table_name
ORDER BY sort_expression1 [ASC | DESC];
```

### Parameters

*   `columns`: columns that you wish to retrieve
*   `table_name`: table that you want to retrieve records from.
*   `ORDER BY`: expression used to order the results
*   `ASC` or `DESC`: optional parameter to specify the order in which the results should be returned, either ascending or descending. Default is set to `ASC`

## Examples

We will use the table called **salaryemp** as an example. In order to create the table, please run the query below:

```sql
CREATE TABLE salaryemp  
(  
    emp_id int,
    emp_name string,   
    emp_div string,   
    emp_sal int
);  

INSERT INTO salaryemp   
VALUES
(1002, 'Mike', 'Marketing', 6000),  
(1003, 'Sean', 'Marketing', 6500),  
(1004, 'Victor', 'Finance', 7000),  
(1005, 'Lewis', 'Sales', 5500),  
(1006, 'David', 'Marketing', 8000),
(1007, 'Omar', 'Finance', 8000),
(1008, 'Meghan', 'Finance', 7500),  
(1009, 'Harry', 'Operations', 4500),  
(1010, 'Steve', 'Marketing', 6800),   
(1011, 'David', 'Sales', 8200);
```

To verify that the values have been inserted successfully, retrieve the results by executing the following code:

```sql
SELECT * FROM salaryemp;
```

```sql
+-----------+------------+----------------+-------------+
| emp_id    | emp_name   | emp_div        | emp_sal     |
+-----------+------------+----------------+-------------+
| 1002      | Mike       | Marketing      | 6000        | 
| 1003      | Sean       | Marketing      | 6500        |
| 1004      | Victor     | Finance        | 7000        |
| 1005      | Lewis      | Sales          | 5500        |
| 1006      | David      | Marketing      | 8000        |
| 1007      | Meghan     | Finance        | 7500        |
| 1008      | Harry      | Operations     | 4500        |
| 1009      | Steve      | Marketing      | 6800        |
| 1010      | Omar       | Finance        | 8000        |
| 1011      | David      | Sales          | 8200        |
+-----------+------------+----------------+-------------+
```

### Using `ORDER BY` in ascending order

This example uses the `ORDER BY` clause to sort employees by their division:

```sql
SELECT emp_name, emp_div
FROM salaryemp
ORDER BY emp_div;
```

The above query will provide you with the following output:

```sql
+------------+----------------+
| emp_name   | emp_div        |
+------------+----------------+
| Victor     | Finance        |
| Omar       | Finance        |
| Meghan     | Finance        |
| Mike       | Marketing      |
| Sean       | Marketing      |
| David      | Marketing      |
| Steve      | Marketing      |
| Harry      | Operations     |
| Lewis      | Sales          |
| David      | Sales          |
+------------+----------------+
```

### Using `ORDER BY` in descending order

The following statement selects the employee name and employee salary from the **salaryemp** table and sorts the records in the `emp_sal` column in descending order:

```sql
SELECT * FROM salaryemp
ORDER BY emp_sal DESC;
```

The result of the query is as follows:

```sql
+-----------+------------+----------------+-------------+
| emp_id    | emp_name   | emp_div        | emp_sal     |
+-----------+------------+----------------+-------------+
| 1011      | David      | Sales          | 8200        |
| 1006      | David      | Marketing      | 8000        |
| 1010      | Omar       | Finance        | 8000        |
| 1007      | Meghan     | Finance        | 7500        |
| 1004      | Victor     | Finance        | 7000        |
| 1009      | Steve      | Marketing      | 6800        |
| 1003      | Sean       | Marketing      | 6500        |
| 1002      | Mike       | Marketing      | 6000        | 
| 1005      | Lewis      | Sales          | 5500        |
| 1008      | Harry      | Operations     | 4500        |
+-----------+------------+----------------+-------------+
```

### Using `ORDER BY` with both ASC & DESC parameters

The following statement selects all records from the **salaryemp** table and sorts the rows by employee salary in ascending order and employee division in descending order:

```sql
SELECT * FROM salaryemp
ORDER BY emp_sal ASC, emp_div DESC;
```

After implementing the above command, we will get the following output:

```sql
+-----------+------------+----------------+-------------+
| emp_id    | emp_name   | emp_div        | emp_sal     |
+-----------+------------+----------------+-------------+
| 1009      | Harry      | Operations     | 4500        |
| 1005      | Lewis      | Sales          | 5500        |
| 1002      | Mike       | Marketing      | 6000        |
| 1003      | Sean       | Marketing      | 6500        |
| 1009      | Steve      | Marketing      | 6800        |
| 1004      | Victor     | Finance        | 7000        |
| 1007      | Meghan     | Finance        | 7500        |
| 1006      | David      | Marketing      | 8000        |
| 1010      | Omar       | Finance        | 8000        |
| 1011      | David      | Sales          | 8200        |
+-----------+------------+----------------+-------------+
```

### Using `ORDER BY` with `STRING` or `TEXT` data types

In this example we are going to create to small tables with above mentioned data types:

```sql
CREATE TABLE strings  
(  
    column1 STRING
);  

INSERT INTO strings   
VALUES ('A'), ('B'), ('a'), ('b');

CREATE TABLE texts  
(  
    column1 TEXT
);  

INSERT INTO texts   
VALUES ('A'), ('B'), ('a'), ('b');
```

When using the `ORDER BY` clause with these types of data, records with uppercase letters will be sorted lexicographically first, followed by records with lowercase letters.

```sql
SELECT * FROM strings ORDER BY column1;
SELECT * FROM texts ORDER BY column1;
```

```sql
 column1 
---------
 A
 B
 a
 b
```

### Using `ORDER BY` with `INTERVAL` data type

For this example, we'll create a new table called `interval_data`:

```sql
CREATE TABLE interval_data (
    duration INTERVAL
);

INSERT INTO interval_data (duration)
VALUES 
    (INTERVAL '1 month 30 days 20 hours'),
    (INTERVAL '2 months 20 hours'),
    (INTERVAL '1 month 30 days 19 hours'),
    (INTERVAL '2 months 1 hours');
```

`ORDER BY` on `INTERVAL` column will sort the values by their leading most significant time unit.
In this case `months`. First are all `1 month` values, then all `2 months` values.

```sql
SELECT * FROM interval_data ORDER BY duration;
```

```sql
        duration        
------------------------
 1 mon 30 days 19:00:00
 1 mon 30 days 20:00:00
 2 mons 01:00:00
 2 mons 20:00:00
```

It works the same for other time units, such as `hours` and `days`.

```sql
INSERT INTO interval_data (duration)
VALUES 
    (INTERVAL '24 hours 5 minutes'),
    (INTERVAL '1 day 5 minutes'),
    (INTERVAL '1 day 2 minutes');
```

```sql
SELECT * FROM interval_data ORDER BY duration;
```

```sql
        duration        
------------------------
 24:05:00
 1 day 00:02:00
 1 day 00:05:00
 1 mon 30 days 19:00:00
 1 mon 30 days 20:00:00
 2 mons 01:00:00
 2 mons 20:00:00
```


# LIMIT



## Overview

`LIMIT` is an optional clause that can be combined with `SELECT` statements used for retrieving records from one or more tables. It basically specifies the number of records a query should return after filtering the data.

## Syntax

There are two versions available for the `LIMIT` clause syntax:

<CodeGroup>
  ```sql Version 1
  SELECT column_list
  FROM table_name
  ORDER BY sort_expression
  LIMIT row_count
  ```

  ```sql Version 2
  SELECT column_list
  FROM table_name
  ORDER BY sort_expression
  FETCH NEXT row_count ROWS ONLY
  ```
</CodeGroup>

The parameters and arguments for specific version of the syntax are described below:

*   `column_list`: The columns or calculations that you wish to retrieve.
*   `table_name`: The tables that you want to retrieve records from.

<Info>It is possible to have more than one table in the `FROM` clause.</Info>

*   `ORDER BY`: It is an expression used to order the results as you wish to return. The expression could be ascending **(ASC)** or descending **(DESC)**
*   `LIMIT row_count`: It specifies a limited number of rows to be returned based on **row\_count**.

### 💡 Special Case

1.  If the `row_count` value is **NULL,** the query will produce a similar outcome because it does not contain the `LIMIT` clause.
2.  If `row_count` is **zero**, the statement will return an empty set.

## Examples

Let’s take some examples of the `LIMIT` clause.

Here we are creating one new table called **comporders** using the `CREATE TABLE` command and inserting some values into the table using the `INSERT` command:

```sql
CREATE TABLE comporders  
(  
    order_id int,
    cust_name string,   
    prod_name string,   
    prod_price float,  
    status string  
);  

INSERT INTO comporders   
VALUES
(1002, 'Mike', 'Lenovo IdeaPad Flex 5', 600, 'PAID'),  
(1003, 'Sean', 'Acer Aspire 3', 450, 'PAID'),  
(1004, 'Victor', 'Microsoft Surface Laptop Go 2', 500, 'PENDING'),  
(1005, 'Lewis', 'Lenovo Duet 5i', 700, 'PAID'),  
(1006, 'David', 'Acer Swift 3', 640, 'PAID'),  
(1007, 'Meghan', 'Lenovo IdeaPad Duet 5 Chromebook', 750, 'PAID'),  
(1008, 'Harry', 'Apple iPad Air', 449, 'PENDING'),  
(1009, 'Steve', 'Microsoft Surface Go 3', 680, 'PENDING'),  
(1010, 'Omar', 'HP Victus 16', 800,'PAID');
```

To verify that the values have been inserted successfully, retrieve the result set using the command below:

```sql
SELECT * FROM comporders;
```

```sql
+-----------+------------+----------------------------------+-------------+----------+
| order_id  | cust_name  | prod_name                        | prod_price  | status   |
+-----------+------------+----------------------------------+-------------+----------+
| 1002      | Mike       | Lenovo IdeaPad Flex 5            | 600         | PAID     |  
| 1003      | Sean       | Acer Aspire 3                    | 450         | PAID     |
| 1004      | Victor     | Microsoft Surface Laptop Go 2    | 500         | PENDING  |
| 1005      | Lewis      | Lenovo Duet 5i                   | 700         | PENDING  |
| 1006      | David      | Acer Swift 3                     | 640         | PAID     |
| 1007      | Meghan     | Lenovo IdeaPad Duet 5 Chromebook | 750         | PAID     |
| 1008      | Harry      | Apple iPad Air                   | 449         | PENDING  |
| 1009      | Steve      | Microsoft Surface Go 3           | 680         | PENDING  |
| 1010      | Omar       | HP Victus 16                     | 800         | PAID     |
+-----------+------------+----------------------------------+-------------+----------+
```

### Case #1: Using `LIMIT` with the `ORDER BY` Expression

This example uses the `LIMIT` clause to get the first four orders sorted by `order_id`:

```sql
SELECT order_id, prod_name, prod_price
FROM comporders
ORDER BY order_id
LIMIT 4;
```

The above query will give the following result:

```sql
+-----------+-------------------------------+-------------+
| order_id  | prod_name                     | prod_price  |
+-----------+-------------------------------+-------------+
| 1002      | Lenovo IdeaPad Flex 5         | 600         | 
| 1003      | Acer Aspire 3                 | 450         |
| 1004      | Microsoft Surface Laptop Go 2 | 500         |
| 1005      | Lenovo Duet 5i                | 700         |
+-----------+-------------------------------+-------------+
```

### Case #2: Using `LIMIT` with ASC/DESC

You can use the `LIMIT` clause to select rows with the highest or lowest values from a table.

1.  To get the top 5 most expensive orders, you sort orders by the product price in descending order **(DESC)** and use the `LIMIT` clause to get the first 5 orders.

The following query depicts the idea:

```sql
SELECT * FROM comporders
ORDER BY prod_price DESC
LIMIT 5;
```

The result of the query is as follows:

```sql
+-----------+------------+----------------------------------+-------------+----------+
| order_id  | cust_name  | prod_name                        | prod_price  | status   |
+-----------+------------+----------------------------------+-------------+----------+
| 1010      | Omar       | HP Victus 16                     | 800         | PAID     |  
| 1007      | Meghan     | Lenovo IdeaPad Duet 5 Chromebook | 750         | PAID     |
| 1005      | Lewis      | Lenovo Duet 5i                   | 700         | PENDING  |
| 1009      | Steve      | Microsoft Surface Go 3           | 680         | PENDING  |
| 1006      | David      | Acer Swift 3                     | 640         | PAID     |
+-----------+------------+----------------------------------+-------------+----------+
```

2.  We will fetch the top 5 cheapest orders this time. You sort orders by the product price in ascending order **(ASC)** and use the `LIMIT` clause to get the first 5 orders.

The following query depicts the idea:

```sql
SELECT * FROM comporders
ORDER BY prod_price ASC
LIMIT 5;
```

We will get the below output:

```sql
+-----------+------------+----------------------------------+-------------+----------+
| order_id  | cust_name  | prod_name                        | prod_price  | status   |
+-----------+------------+----------------------------------+-------------+----------+
| 1008      | Harry      | Apple iPad Air                   | 449         | PENDING  |
| 1003      | Sean       | Acer Aspire 3                    | 450         | PAID     |
| 1004      | Victor     | Microsoft Surface Laptop Go 2    | 500         | PENDING  |
| 1002      | Mike       | Lenovo IdeaPad Flex 5            | 600         | PAID     |  
| 1006      | David      | Acer Swift 3                     | 640         | PAID     |
+-----------+------------+----------------------------------+-------------+----------+
```

### #Case 3:  Using `LIMIT` with `OFFSET`

In this example, we will use `LIMIT` and `OFFSET` clauses to get 5 orders using the below query:

```sql
SELECT * FROM comporders
LIMIT 5 OFFSET 2;
```

After implementing the above command, we will get the below output:

```sql
+-----------+------------+----------------------------------+-------------+----------+
| order_id  | cust_name  | prod_name                        | prod_price  | status   |
+-----------+------------+----------------------------------+-------------+----------+
| 1004      | Victor     | Microsoft Surface Laptop Go 2    | 500         | PENDING  |
| 1005      | Lewis      | Lenovo Duet 5i                   | 700         | PENDING  |
| 1006      | David      | Acer Swift 3                     | 640         | PAID     |
| 1007      | Meghan     | Lenovo IdeaPad Duet 5 Chromebook | 750         | PAID     |
| 1008      | Harry      | Apple iPad Air                   | 449         | PENDING  |
+-----------+------------+----------------------------------+-------------+----------+
```

The result above shows that:

*   The orders with `order_id`= **1002 & 1003** aren't displayed because we put the `OFFSET` value with 2. So the first 2 lines are ignored.
*   The orders with `order_id`= **1009 & 1010** aren't displayed because the `LIMIT` value is 5, which will display only 5 rows.


# OFFSET



## **Overview**

The `OFFSET` is a clause that skips some records from the result set.

## **Syntax**

The basic syntax of the `OFFSET` clause is shown below:

```sql
SELECT columns
FROM table_name
OFFSET num;
```

The parameters and arguments from the syntax are:

*   `columns`: the columns to be fetched.

*   `table_name`: a table from which the records will be fetched.

*   `OFFSET`: a clause that will skip a subset of records.
    *   `num`: the number of records to be skipped.

## **Example**

**1.** Here, we are creating one new table called **oxlafunctions** using the `CREATE TABLE` command and inserting some values into the table using the `INSERT` command:

```sql
CREATE TABLE oxlafunctions  
(  
    func_name string,   
    func_sub string   
);  

INSERT INTO oxlafunctions   
VALUES
('Numeric', 'ABS'),  
('Numeric', 'CEIL'),  
('String', 'LENGTH'),  
('Numeric', 'SQRT'),  
('Boolean', 'IF'),  
('String', 'STRPOS'),  
('Numeric', 'FLOOR'),  
('String', 'CONCAT'),  
('String', 'LOWER');  
```

**2.** To verify that the values have been inserted successfully, retrieve the result set using the command below:&#x20;

```sql
SELECT * FROM oxlafunctions;
```

```sql
+------------+------------+
| func_name  | func_sub   |
+------------+------------+
| Numeric    | ABS        |
| Numeric    | CEIL       |
| String     | LENGTH     |
| Numeric    | SQRT       |
| Boolean    | IF         |
| String     | STRPOS     |
| Numeric    | FLOOR      | 
| String     | CONCAT     |
| String     | LOWER      |
+------------+------------+
```

**3.** Use the **LIMIT** clause in conjunction with the **OFFSET** clause to skip a subset of records:

```sql
SELECT * FROM oxlafunctions
ORDER BY func_name
LIMIT 5 OFFSET 2;
```

In the above query:

*   The **“LIMIT 5”** clause is used to fetch only five records.

*   The **“OFFSET 2”** clause is used to skip the first two records before retrieving the result set of the limit clause.

**4.** You will get the following output:

```sql
+------------+------------+
| func_name  | func_sub   |
+------------+------------+
| Boolean    | IF         |
| Numeric    | SQRT       |
| Numeric    | CEIL       |
| Numeric    | ABS        | 
| Numeric    | FLOOR      |
+------------+------------+
```


# EXCEPT



## EXCEPT

### Overview

The `EXCEPT` combines the result sets of two or more tables and retrieves rows specific to the first `SELECT` statement but not present in the subsequent ones.

### Syntax

The syntax for the `EXCEPT` is as follows:

```sql
SELECT value1, value2, ... value_n
FROM table1
EXCEPT
SELECT value1, value2, ... value_n
FROM table2;
```

The parameters from the syntax are explained below:

*   `value1, value2, ... value_n`: The columns you want to retrieve.

*   `table1, table2`: The tables from which you wish to retrieve records.

### Example

Let's assume you have two tables: `vehicles` and `vehicles1`. You want to find the vehicle which was present in 2021 but is not present in 2022:

```sql
CREATE TABLE vehicles (
    vhc_id INT,
    vhc_name TEXT
);

CREATE TABLE vehicles1 (
    vhc_id INT,
    vhc_name TEXT
);

INSERT INTO vehicles VALUES
(1, 'Truck'),
(2, 'Car'),
(3, 'Motorcycle');

INSERT INTO vehicles1 VALUES
(2, 'Car'),
(3, 'Bus'),
(4, 'Motorcycle');
```

Display the tables with the query below:

```sql
SELECT * FROM vehicles;
SELECT * FROM vehicles1;
```

```sql
vhc_id |  vhc_name
--------+------------
      1 | Truck
      2 | Car
      3 | Motorcycle

 vhc_id |  vhc_name
--------+------------
      2 | Car
      3 | Bus
      4 | Motorcycle
```

Using the `EXCEPT` to find employees present in 2021 but not in 2022:

```sql
SELECT vhc_name FROM vehicles
EXCEPT
SELECT vhc_name FROM vehicles1;
```

The result will include the names of employees who were present in 2021 but are not present in 2022:

```sql
vhc_name
----------
 Truck
```

From the diagram below, we learn that the result is a list of vehicle names present in the first table (`vehicles`) but not found in the second table (`vehicles1`). In this case, the result is the vehicle name "Truck."

![except](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/except.png)

## EXCEPT ALL

### Overview

The `EXCEPT ALL` allows you to find rows specific to the first `SELECT` statement while preserving duplicate entries.

### Syntax

The syntax for the `EXCEPT ALL` is similar to `EXCEPT`:

```sql
SELECT value1, value2, ... value_n
FROM table1
EXCEPT ALL
SELECT value1, value2, ... value_n
FROM table2;
```

The parameters from the syntax are explained below:

*   `value1, value2, ... value_n`: The columns you want to retrieve.

*   `table1, table2`: The tables from which you wish to retrieve records.

<Note>The data types of corresponding columns in the `SELECT` queries must be compatible.</Note>

### Example #1

You aim to identify customers who have bought products from one marketplace but have not purchased from another. Start by creating the tables and populating them with relevant data.

```sql
CREATE TABLE marketplace1_transactions (
    customer_id INT,
    product_id INT,
    amount FLOAT
);

CREATE TABLE marketplace2_transactions (
    customer_id INT,
    product_id INT,
    amount FLOAT
);

INSERT INTO marketplace1_transactions VALUES
(101, 1, 100.00),
(102, 2, 150.00),
(103, 3, 200.00),
(104, 1, 120.00);

INSERT INTO marketplace2_transactions VALUES
(102, 3, 180.00),
(103, 2, 160.00),
(105, 4, 90.00),
(106, 1, 110.00);
```

Display the tables using the query below:

```sql
SELECT * FROM marketplace1_transactions;
SELECT * FROM marketplace2_transactions;
```

```sql
customer_id | product_id | amount
-------------+------------+--------
         101 |          1 |    100
         102 |          2 |    150
         103 |          3 |    200
         104 |          1 |    120

 customer_id | product_id | amount
-------------+------------+--------
         102 |          3 |    180
         103 |          2 |    160
         105 |          4 |     90
         106 |          1 |    110
```

Using the `EXCEPT ALL` to find customers who have purchased products from one marketplace but not from the other:

```sql
SELECT customer_id FROM marketplace1_transactions
EXCEPT ALL
SELECT customer_id FROM marketplace2_transactions;
```

This result will show a `customer_id` who has only transacted in the first marketplace and has not engaged in any corresponding transactions in the second marketplace.

```sql
customer_id
-------------
         104
         101
```

The diagram below shows a list of customer-product pairs found in the first marketplace (`marketplace1_transactions`) but missing in the second marketplace (`marketplace2_transactions`).&#x20;

![except result](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/except-2.png)

### Example #2

Let’s create two tables, `left_array_values` and `right_array_values`, to hold sets of values.

```sql
CREATE TABLE left_array_values (
    value INT
);

CREATE TABLE right_array_values (
    value INT
);

INSERT INTO left_array_values VALUES (1), (1), (3);
INSERT INTO right_array_values VALUES (1), (2);
```

View the contents of the two arrays before performing the comparison.

```sql
SELECT * FROM left_array_values;
SELECT * FROM right_array_values;
```

Upon execution, the tables will appear as follows:

```sql
value
-------
     1
     1
     3

 value
-------
     1
     2
```

We will now use the `EXCEPT ALL` operation to compare the values within the arrays, focusing on unique elements while retaining duplicate entries.

```sql
SELECT value
FROM left_array_values
EXCEPT ALL
SELECT value
FROM right_array_values;
```

The `EXCEPT ALL` operation processes each element individually from both inputs at a time. The comparison occurs element-wise, leading to the inclusion of both 1 and 3 in the final result.&#x20;

```sql
value
-------
     3
     1
```


# INTERSECT



## INTERSECT

### Overview

The `INTERSECT` combines the result sets of two or more `SELECT` statements, retrieving only the common rows between them.&#x20;

Unlike `UNION`, which combines all rows and removes duplicates, `INTERSECT` focuses on returning rows that appear in all `SELECT` statements.

### Syntax

The syntax for the `INTERSECT` is as follows:

```sql
SELECT value1, value2, ... value_n
FROM table1
INTERSECT
SELECT value1, value2, ... value_n
FROM table2;
```

The parameters from the syntax are explained below:

*   `value1, value2, ... value_n`: The columns you want to retrieve. You can also use `SELECT * FROM` to retrieve all columns.

*   `table1, table2`: The tables from which you wish to retrieve records.

<Note>The data types of corresponding columns must be compatible.</Note>

### Example

Suppose you have two tables: `customers_old` and `customers_new`, containing customer data for different periods. You want to find the customers who are present in both tables:

```sql
CREATE TABLE customers_old (
    customer_id INT,
    customer_name TEXT
);

CREATE TABLE customers_new (
    customer_id INT,
    customer_name TEXT
);

INSERT INTO customers_old VALUES
(1, 'Alice'),
(2, 'Bob'),
(3, 'Charlie');

INSERT INTO customers_new VALUES
(2, 'Bob'),
(3, 'Charlie'),
(4, 'David');
```

Viewing the inserted values:

```sql
SELECT * FROM customers_old;
SELECT * FROM customers_new;
```

```sql
customer_id | customer_name
-------------+---------------
           1 | Alice
           2 | Bob
           3 | Charlie

 customer_id | customer_name
-------------+---------------
           2 | Bob
           3 | Charlie
           4 | David
```

Now, let’s combine common customers using the `INTERSECT`:

```sql
SELECT customer_name FROM customers_old
INTERSECT
SELECT customer_name FROM customers_new;
```

The result will include only the names that appear in both tables:&#x20;

```sql
customer_name
---------------
 Bob
 Charlie
```

The picture displays a list of customer names that appear in both tables. Only "Bob" and "Charlie" are found in both tables and shown as INTERSECT's final result.

![intersect](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/intersect.png)

## INTERSECT ALL

### Overview

The `INTERSECT ALL` retrieves all common rows between two or more tables, including duplicates.&#x20;

This means that if a row appears multiple times in any of the `SELECT` statements, it will be included in the final result set multiple times.

### Syntax

The syntax for `INTERSECT ALL` is similar to `INTERSECT`:

```sql
SELECT value1, value2, ... value_n
FROM tables
INTERSECT ALL
SELECT value1, value2, ... value_n
FROM tables;
```

The parameters from the syntax are explained below:

*   `value1, value2, ... value_n`: The columns you wish to retrieve. You can also retrieve all the values using the `SELECT * FROM` query.

*   `table1, table2`: The tables from which you want to retrieve records.

<Note>The data types of corresponding columns in the `SELECT` queries must be compatible.</Note>

### Example

Let’s create three tables of products from different years. You want to find the common products among all three categories, including duplicates.

```sql
CREATE TABLE products_electronics2021 (
    product_id INT,
    product_name TEXT
);

CREATE TABLE products_electronics2022 (
    product_id INT,
    product_name TEXT
);

CREATE TABLE products_electronics2023 (
    product_id INT,
    product_name TEXT
);

INSERT INTO products_electronics2021 VALUES
(1, 'Laptop'),
(2, 'Phone'),
(3, 'Tablet'),
(4, 'Headphones');

INSERT INTO products_electronics2022 VALUES
(2, 'TV'),
(3, 'Printer'),
(4, 'Monitor'),
(5, 'Phone');

INSERT INTO products_electronics2023 VALUES
(3, 'Laptop'),
(4, 'Phone'),
(5, 'Oven'),
(6, 'AC');
```

Display the tables using the query below:

```sql
SELECT * FROM products_electronics2021;
SELECT * FROM products_electronics2022;
SELECT * FROM products_electronics2023;
```

```sql
product_id | product_name
------------+--------------
          1 | Laptop
          2 | Phone
          3 | Tablet
          4 | Headphones

 product_id | product_name
------------+--------------
          2 | TV
          3 | Printer
          4 | Monitor
          5 | Phone

 product_id | product_name
------------+--------------
          3 | Laptop
          4 | Phone
          5 | Oven
          6 | AC
```

Then, combine common products from all three categories using the `INTERSECT ALL`:

```sql
SELECT product_name FROM products_electronics2021
INTERSECT ALL
SELECT product_name FROM products_electronics2022
INTERSECT ALL
SELECT product_name FROM products_electronics2023;
```

The result will include the products that are common among all three categories, including duplicates:

```sql
product_name
--------------
 Phone
```

The illustration shows a list of product names common to all three years, including duplicates. In this case, the result is the product name "Phone," which appears across all three tables.

![intersect result](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/intersect-2.png)


# Overview



Set operations are operations used to manipulate and analyze sets. It includes the following operations:

1.  [**Union**](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/union): Combines two or more sets to create a new set containing all unique elements from the input sets.

2.  [**Intersect**](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/intersect): Yields a new set with elements common to all input sets.

3.  [**Except**](https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/except): Generates a set containing elements from the first set that are not present in the second set.

These operations allow for comparisons, combinations, and distinctions among sets in various contexts.


# UNION



## UNION

### Overview

The `UNION` combines the result sets of 2 or more select statements, removing duplicate rows between the tables.

### Syntax

Below is the syntax of the `UNION`:

```sql
SELECT value1, value2, ... value_n
FROM table1
UNION
SELECT value1, value2, ... value_n
FROM table2;
```

The parameters from the syntax are explained below:

*   `value1, value2, ... value_n`: The columns you wish to retrieve. You can also retrieve all the values using the `SELECT * FROM` query.

*   `table1, table2`: The tables that you wish to retrieve records from.&#x20;

<Tip>**Things to consider:**<br /> 1.  The data types of corresponding columns in the `SELECT` queries must be compatible. <br /> 2.  The order of columns is flexible as long as the columns in consecutive places are pairwise compatible. For example, you can do `SELECT col1, col2 FROM table1 UNION SELECT col2, col1 FROM table2`.</Tip>

### Example

Let's consider an example of the `UNION`. Assume we have a table called `employees` and another table called `contractors`. We want to retrieve a combined list of names from both tables, excluding duplicates:

```sql
CREATE TABLE employees (
    emp_id INT,
    emp_name TEXT
);

CREATE TABLE contractors (
    contractor_id INT,
    contractor_name TEXT
);

INSERT INTO employees VALUES
(1, 'John'),
(2, 'Alice'),
(3, 'Bob');

INSERT INTO contractors VALUES
(101, 'Alice'),
(102, 'Eve'),
(103, 'Tom');
```

Verifying inserted values by using the `SELECT` statement:

```sql
SELECT * FROM employees;
SELECT * FROM contractors;
```

```sql
emp_id | emp_name
--------+----------
      1 | John
      2 | Alice
      3 | Bob

 contractor_id | contractor_name
---------------+-----------------
           101 | Alice
           102 | Eve
           103 | Tom
```

Let’s combine the values from the tables:

```sql
SELECT emp_name FROM employees
UNION
SELECT contractor_name FROM contractors;
```

You will get the values of both tables, and there won’t be any duplicate values.

```sql
emp_name
----------
 Alice
 Bob
 Eve
 John
 Tom
```

The diagram below shows that the duplicate name "Alice" is represented only once in the output, fulfilling the requirement to avoid duplicate entries.

![union](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/union.png)

## UNION ALL

### Overview

The `UNION ALL` combines the result sets of 2 or more select statements, returning all rows from the query and not removing duplicate rows between the tables.

### Syntax

Below is the syntax of the `UNION ALL`:

```sql
SELECT value1, value2, ... value_n
FROM tables
UNION ALL
SELECT value1, value2, ... value_n
FROM tables;
```

The parameters from the syntax are explained below:

*   `value1, value2, ... value_n`: The columns you wish to retrieve. You can also retrieve all the values using the `SELECT * FROM` query.

*   `table1, table2`: The tables that you wish to retrieve records from.&#x20;

<Tip>**Things to consider:**<br /> 1. The data types of corresponding columns in the `SELECT` queries must be compatible. <br /> 2. The order of columns is flexible as long as the columns in consecutive places are pairwise compatible.</Tip>

### Example

Suppose you have two separate tables, `sales_2022` and `sales_2023`, containing sales data for different years. You want to combine the sales data from both tables to get a complete list of sales transactions without removing duplicates.

```sql
CREATE TABLE sales_2022 (
    transaction_id INT,
    product_name TEXT,
    sale_amount INT
);

CREATE TABLE sales_2023 (
    transaction_id INT,
    product_name TEXT,
    sale_amount INT
);

INSERT INTO sales_2022 VALUES
(1, 'Product A', 1000),
(2, 'Product B', 500),
(3, 'Product C', 750);

INSERT INTO sales_2023 VALUES
(4, 'Product A', 1200),
(5, 'Product D', 800),
(6, 'Product E', 950);
```

Verifying inserted values by using the `SELECT` statement:

```sql
SELECT * FROM sales_2022;
SELECT * FROM sales_2023;
```

```sql
transaction_id | product_name | sale_amount
----------------+--------------+-------------
              1 | Product A    |        1000
              2 | Product B    |         500
              3 | Product C    |         750

 transaction_id | product_name | sale_amount
----------------+--------------+-------------
              4 | Product A    |        1200
              5 | Product D    |         800
              6 | Product E    |         950
```

Let’s combine all values from the tables by using the `UNION ALL`:&#x20;

```sql
SELECT product_name, sale_amount FROM sales_2022 UNION ALL SELECT product_name, sale_amount FROM sales_2023;
```

In this case, it will display all the values of the first table followed by all the contents of the second table.

```sql
product_name | sale_amount
--------------+-------------
 Product A    |        1000
 Product B    |         500
 Product C    |         750
 Product A    |        1200
 Product D    |         800
 Product E    |         950
```

The diagram illustrates that with the `UNION ALL`, all values are displayed, including the duplicate ones.&#x20;

![union all](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/union-2.png)


# Overview



## What are Clauses? 🤔

A clause in SQL is part of a query that lets you:

*   filter and analyze large amounts of data stored in the database with the customization query you prefer.&#x20;

*   retrieve a set of records from the table.

*   specify a condition on a table’s columns or records.

***

Currently, Oxla supports SQL queries with the following clauses:

<CardGroup cols={4}>
  <Card title="FROM" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-1-from/from">
    Learn more
  </Card>

  <Card title="WHERE" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-2-where/where">
    Learn more
  </Card>

  <Card title="GROUP BY" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-3-group-by/group-by">
    Learn more
  </Card>

  <Card title="HAVING" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-4-having/having">
    Learn more
  </Card>

  <Card title="ORDER BY" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-5-order-by/order-by">
    Learn more
  </Card>

  <Card title="LIMIT" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-6-limit/limit">
    Learn more
  </Card>

  <Card title="OFFSET" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-7-offset/offset">
    Learn more
  </Card>

  <Card title="Set Operations" href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/3-2-8-set-operations/set-operations">
    Learn more
  </Card>
</CardGroup>


# Data Type Operators



The Operator data type is any parsed expression that returns a value. An operator is used in the form of a special symbol or function.

The following table shows a list of logical operators that Oxla supports:

| **Type**   | **Name**                 | **Operator** | **Description**                                                                              | **Example**                |
| ---------- | ------------------------ | ------------ | -------------------------------------------------------------------------------------------- | -------------------------- |
| Relational | Equal to                 | `=`          | This shows that the value of one item is **equal** to another item’s value.                  | `cust_name = 'Mike'`       |
| Relational | Greater than             | `>`          | This shows that the value of one item is **greater** than another item’s value.              | `stock_value > 10`         |
| Relational | Less than                | `<`          | This shows that the value of one item is **less** than another item’s value.                 | `stock_value < 20`         |
| Relational | Not equal to             | `<>` or `!=` | Indicates that the value of one item is **not equal** to the other item’s value.             | `subj_score != 'FAILED'`   |
| Relational | Greater than or equal to | `>=`         | Indicates that the value of one item is **greater than or equal to** the other item’s value. | `prod_price >= 3000`       |
| Relational | Less than or equal to    | `<=`         | Indicates that the value of one item is **less than or equal to** the other item’s value.    | `prod_price <= 9000`       |
| Logical    | Not                      | `NOT`        | It shows a record if the condition(s) is NOT TRUE.                                           | `NOT true = false`         |
| Logical    | Is null                  | `IS NULL`    | Used to check for empty values (`NULL` values).                                              | `WHERE empsalary IS NULL;` |


# JSON Type



## **Overview**

JSON stands for **JavaScript Object Notation**. It is an open standard format with key-value pairs to transport data between a server and a web application.&#x20;

## **Syntax**

The JSON data type in Oxla has the following syntax:

```sql
variable_name JSON  
```

## **Examples**

### 1. Create a Table

First, create the **orders table** using the below command:

```sql
CREATE TABLE orders (  
    orders_Detail JSON  
);  
```

This will create a table with the `orders_Detail`column to store key-value pairs of data.

### 2. Insert Data

Next, insert data into the orders table as follows:

```sql
INSERT INTO orders (orders_Detail)  
VALUES
('{ "customer": "Dean Smith", "items": {"product": "cup","qty": 2}}'),
('{ "customer": "Sissy Kate", "items": {"product": "knife","qty": 1}}'),
('{ "customer": "Emma Stone", "items": {"product": "spoon","qty": 4}}'),
('{ "customer": "Chris Bale", "items": {"product": "fork","qty": 5}}'),
('{ "customer": "Mike Stuart", "items": {"product": "spatula","qty": 2}}');
```

This will insert data values where `orders_Detail`has the following keys:

*   `customer`: it will store a customer’s data who purchased the product.

*   `items`: it will store the order details, `product` & `qty`.

### 3. Retrieve Data

Use the `SELECT` command to retrieve the orders table's data.

```sql
SELECT * FROM orders;
```

You will get the following output:

```sql
+--------------------------------------------------------------------------+
| orders_detail                                                            | 
+--------------------------------------------------------------------------+
| {"customer":"Dean Smith","items":{"qty":2.000000,"product":"cup"}}       |
| {"customer":"Sissy Kate","items":{"product":"knife","qty":1.000000}}     |                                                        
| {"customer":"Emma Stone","items":{"qty":4.000000,"product":"spoon"}}     |
| {"customer":"Chris Bale","items":{"product":"fork","qty":5.000000}}      |
| {"customer":"Mike Stuart","items":{"qty":2.000000,"product":"spatula"}}  |
+--------------------------------------------------------------------------+
```

<Tip>It is normal for the JSON type’s result to look disordered.</Tip>


# Bool Type



## **Overview**

A `BOOL` is a data type mainly used for expressions that will return only two possible values, `true` and `false`.&#x20;

<Info>Bool is stored as a bitmap in `u64` values.</Info>

<Warning>**BOOLEAN** is an alias for the **BOOL** data type. You can create a table using **BOOLEAN**. However, it will be stored and processed equivalently to **BOOL**.</Warning>

## **Format**

*   `FALSE`

*   `TRUE`

## **Examples**

Below are a few examples of using a bool data type:

### Case #1: Create a Table

A librarian will create a **borrowBook** table that he will use to store book borrowing data. The table comprises the borrowed ID, the book name, the borrower, and the book's returned status, which uses the **bool** data type.

```sql
CREATE TABLE borrowBook  (  
   borrowID INT, 
   bookName TEXT,
   borrower TEXT,
   returnedStat BOOL NOT NULL  
);  
INSERT INTO borrowBook (borrowID,bookName, borrower, returnedStat)  
VALUES  
    (101, 'The Silent Patient', 'Mike', TRUE),  
    (201, 'Malibu Rising', 'Jean', TRUE),  
    (301, 'The Guest List', 'Mark', FALSE),  
    (401, 'The Four Winds', 'Cliff', TRUE),  
    (501, 'The Vanishing Half: A Novel', 'Sarah', TRUE),  
    (601, 'Red, White & Royal Blue', 'Anna', FALSE),  
    (701, 'The Duke and I', 'Blake', FALSE),  
    (801, 'The Lord of the Rings', 'Sandra', FALSE);  
```

The **borrowBook** table has been successfully created after executing the above query:

```sql
COMPLETE
INSERT 0 8
```

### Case #2: Display the Table

Run the `SELECT` statement to get all records from the **borrowBook** table:

```sql
SELECT * FROM borrowBook;
```

It will return the result as displayed below:

```sql
+-----------+---------------------------------+------------+---------------+
| borrowid  | bookname                        | borrower   | returnedstat  |
+-----------+---------------------------------+------------+---------------+
| 101       | The Silent Patient              | Mike       | t             |
| 201       | Malibu Rising                   | Jean       | t             |
| 301       | The Guest List                  | Mark       | f             |
| 401       | The Four Winds                  | Cliff      | t             |
| 501       | The Vanishing Half: A Novel     | Sarah      | t             |
| 601       | Red, White & Royal Blue         | Anna       | f             |
| 701       | The Duke and I                  | Blake      | f             |
| 801       | The Lord of the Rings           | Sandra     | f             |
+-----------+---------------------------------+------------+---------------+
```

### Case #3: List of the Returned Books

In the below example, the following statement is used to retrieve all the **books** that have already been returned:

```sql
SELECT * FROM borrowbook       
WHERE returnedstat= 'true';
```

We will get the following results:

```sql
+-----------+---------------------------------+------------+---------------+
| borrowid  | bookname                        | borrower   | returnedstat  |
+-----------+---------------------------------+------------+---------------+
| 101       | The Silent Patient              | Mike       | t             |
| 201       | Malibu Rising                   | Jean       | t             |
| 401       | The Four Winds                  | Cliff      | t             |
| 501       | The Vanishing Half: A Novel     | Sarah      | t             |
+-----------+---------------------------------+------------+---------------+
```

### Case #4: List of the Unreturned Books

Now, we will acquire all of the book records that haven’t been returned yet by running the `SELECT` statement with a specified `WHERE` condition as `false`:

```sql
SELECT * FROM borrowbook       
WHERE returnedstat= 'false'; 
```

We will get the following results:

```sql
+-----------+---------------------------------+------------+---------------+
| borrowid  | bookname                        | borrower   | returnedstat  |
+-----------+---------------------------------+------------+---------------+
| 301       | The Guest List                  | Mark       | f             |
| 601       | Red, White & Royal Blue         | Anna       | f             |
| 701       | The Duke and I                  | Blake      | f             |
| 801       | The Lord of the Rings           | Sandra     | f             |
+-----------+---------------------------------+------------+---------------+
```

### Case #5: Check a Book’s Return Status

In this example, we are going to figure out the returned status of the book **“The Lord of the Rings”** by executing the `SELECT` statement with a specified column in the `WHERE` clause:

```sql
SELECT * FROM borrowbook  
WHERE bookname = 'The Lord of the Rings';
```

The above query will filter all records based on the specified conditions, and we know that Sandra hasn’t returned the book yet:

```sql
+-----------+---------------------------------+------------+---------------+
| borrowid  | bookname                        | borrower   | returnedstat  |
+-----------+---------------------------------+------------+---------------+
| 801       | The Lord of the Rings           | Sandra     | f             |
+-----------+---------------------------------+------------+---------------+
```


# Date Type



## Overview

The `DATE` data type is used to store and insert date values.

<Info>The date value is stored without the time zone.</Info>

## Structure

The date type contains three components: year, month, and day. It’s represented in a 32-bit integer. Here is the breakdown:

*   **Day component:** 5 bits store the number of days within a month. Its value is in the range `<1, 31>`.

*   **Month component**: 4 bits store the month of the year. Its value is in the range `<1, 12>`.

*   **Year component**: 23 bits store the number of years. Its value is from range `<0, 2^23 - 1>`.

## Format

```sql
YYYY-MM-DD
```

*   `YYYY` - Four-digit year

*   `MM` - One / two-digit month

*   `DD` - One / two-digit day

## Example

In this example, we will create an **emp\_submission** table that consists of the candidate ID, candidate name, the submitted department, and a submission date with a `DATE` data type.

```sql
CREATE TABLE emp_submission (
    candidate_ID INT,
    candidate_Name TEXT,
    sub_dept TEXT,
    sub_date DATE
);

INSERT INTO emp_submission (candidate_ID, candidate_Name, sub_dept, sub_date)
VALUES 
(8557411, 'Kumar', 'HR', '2022-05-01'),
(8557421, 'Ricky', 'HR', '2022-01-09'),
(8557451, 'Alice', 'Finance', '2022-08-02'),
(8557461, 'Angel', 'Product', '2012-04-16'),
(8557431, 'Joan', 'Finance', '2022-02-02'),
(8557471, 'Cody', 'Product', '2022-03-20'),
(8557491, 'Liam', 'Product', '2022-06-15');
```

Now that the data has been inserted, let's execute the `SELECT` statement below:

```sql
SELECT * FROM emp_submission;
```

The following is the result of the `SELECT` statement where the values in the `sub_date` column have `DATE` data type:

```sql
+---------------+------------------+------------+---------------+
| candidate_id  | candidate_name   | sub_dept   | sub_date      |
+---------------+------------------+------------+---------------+
| 8557411       | Kumar            | HR         | 2022-05-01    |
| 8557421       | Ricky            | HR         | 2022-01-09    |
| 8557451       | Alice            | Finance    | 2022-08-02    |
| 8557461       | Angel            | Product    | 2012-04-16    |
| 8557431       | Joan             | Finance    | 2022-02-02    |
| 8557471       | Cody             | Product    | 2022-03-20    |
| 8557491       | Liam             | Product    | 2022-06-15    |
+---------------+------------------+------------+---------------+
```


# Timestamp Without Time Zone Type



## **Overview**

The timestamp data type stores **time** and **date** values without a time zone. It represents a fixed time, independent of any time zone or applied globally.

## **Format**

```sql
YYYY-MM-DD [HH:MM:SS[.SSSSSS]]
```

*   `YYYY`: Four-digit year

*   `MM`: One / two-digit month

*   `DD`: One / two-digit day

*   `HH`: One / two-digit hour (valid values from 00 to 23)

*   `MM`: One / two-digit minutes (valid values from 00 to 59)

*   `SS`: One / two-digit seconds (valid values from 00 to 59)

*   `[.SSSSSS]`: Up to six fractional digits (microsecond precision)

<Info>Fractional digits are the digits after the decimal point ( . )</Info>

## **Examples**

### Case #1: Create a Table

Here, we will create a **visitor** table to store visitor data in an office building. It consists of the visitor’s name, the purpose of the visit, company, time, and date, which uses the **Timestamp** data type.

```sql
CREATE TABLE visitors  (  
   visitorName TEXT, 
   visitPurp TEXT,
   visitComp TEXT,
   visitDate TIMESTAMP WITHOUT TIME ZONE
);  
INSERT INTO visitors (visitorName, visitPurp, visitComp, visitDate)  
VALUES  
    ('Peter', 'Interview', 'Apple', '2022-01-10 09:12:40'),  
    ('Will', 'Meeting', 'McKesson', '2022-01-29 11:28:02'),  
    ('Max', 'Meeting', 'McKesson', '2022-02-11 10:19:10'),  
    ('Dustin', 'Meeting', 'CVS Health', '2022-03-18 14:24:08'),  
    ('Lizzy', 'Meeting', 'CVS Health', '2022-04-23 13:10:09'),  
    ('Evy', 'Interview', 'Apple', '2022-05-01 08:45:50');
```

The **visitors** table has been successfully created after executing the above query:

```sql
COMPLETE
INSERT 0 6
```

### Case #2: Display the Table

Run the `SELECT` statement to get all records of the **visitors** table:

```sql
SELECT * FROM visitors;
```

It will return the result set as displayed below:

```sql
+--------------+--------------+---------------+-----------------------+
| visitorName  | visitPurp    | visitComp     | visitDate             |
+--------------+--------------+---------------+-----------------------+
| Peter        | Interview    | Apple         | 2022-01-10 09:12:40   |
| Will         | Meeting      | McKesson      | 2022-01-29 11:28:02   |
| Max          | Meeting      | McKesson      | 2022-02-11 10:19:10   |
| Dustin       | Meeting      | CVS Health    | 2022-03-18 14:24:08   |
| Lizzy        | Meeting      | CVS Health    | 2022-04-23 13:10:09   |
| Evy          | Interview    | Apple         | 2022-05-01 08:45:50   |
+--------------+--------------+---------------+-----------------------+
```

### Case #3: Look for a Specific Timestamp

In the below example, the following statement is used to get records with a specified timestamp:

```sql
SELECT * FROM visitors       
WHERE visitDate = '2022-04-23 13:10:09';
```

We will get the following successful results:

```sql
+--------------+--------------+---------------+-----------------------+
| visitorName  | visitPurp    | visitComp     | visitDate             |
+--------------+--------------+---------------+-----------------------+
| Lizzy        | Meeting      | CVS Health    | 2022-04-23 13:10:09   |
+--------------+--------------+---------------+-----------------------+
```

### Case #4: Insert a Value That Exceeds the Standard Format

The time in timestamp has a standard format, i.e., for **minutes** only valid for values from 00 to 59.&#x20;

The example below will insert a new record into the visitors table with a value of `60`, which exceeds the standard seconds format.

```sql
INSERT INTO visitors (visitorName, visitPurp, visitComp, visitDate)  
VALUES  
    ('Jolly', 'Survey', 'Apple', '2022-01-10 09:12:60');
```

```sql
INSERT 0 1

Query returned successfully in 135 msec.
```

Verify the result by running the `select` statement below:

```sql
SELECT * FROM visitors       
WHERE visitorName = 'Jolly';
```

We learned that the seconds are displayed as `00` as `60`, which adds 1 minute to the minutes' value.

```sql
+--------------+--------------+---------------+-----------------------+
| visitorName  | visitPurp    | visitComp     | visitDate             |
+--------------+--------------+---------------+-----------------------+
| Jolly        | Survey       | Apple         | 2022-01-10 09:13:00   |
+--------------+--------------+---------------+-----------------------+
```

## **AT TIME ZONE Operator**

The `AT TIME ZONE` operator enables us to convert the input timestamp to the target time zone specified in the query. Additionally, the timestamp you inputted will always be presented in the user's local timezone (currently set as UTC).

<Warning>It's important to note that the result type of this operator is different. It produces a timestamp with a time zone.</Warning>

### **Syntax**

To use the `AT TIME ZONE` operator, you can follow this syntax:

```sql
SELECT TIMESTAMP 'input_timestamp' AT TIME ZONE 'TIME_ZONE';
```

Here's what each element means:

*   `input_timestamp`: This represents the date and time value you want to convert. The user's time zone is fixed to UTC.

*   `TIME_ZONE`: The target time zone to which the timestamp will be converted.&#x20;

### **Example 1**

Suppose we have a timestamp, and we want to convert it into the MST time zone:

```sql
SELECT TIMESTAMP '2001-02-16 10:28:30' AT TIME ZONE 'MST';
```

The result will be a timestamp with the time zone adjusted to MST:

```sql
                f                
---------------------------------
 2001-02-16 17:28:30.000000+0000
(1 row)
```

### **Example 2**

Let's consider from the [visitors](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-4-timestamp-without-time-zone/timestamp-without-time-zone#case-1-create-a-table) table, we wish to retrieve a list of visit dates in the MST time zone. We can achieve this using the following query:

```sql
SELECT visitDate, visitDate AT TIME ZONE 'MST' as "visitDateMST" FROM visitors; 
```

With this query, we obtain a list of two columns: `visitDate` displays the timestamps without a time zone, and `visitDateMST` stores the timestamps converted to the MST time zone.

```sql
         visitdate          |          visitDateMST           
----------------------------+---------------------------------
 2022-01-10 09:12:40.000000 | 2022-01-10 16:12:40.000000+0000
 2022-01-29 11:28:02.000000 | 2022-01-29 18:28:02.000000+0000
 2022-02-11 10:19:10.000000 | 2022-02-11 17:19:10.000000+0000
 2022-03-18 14:24:08.000000 | 2022-03-18 21:24:08.000000+0000
 2022-04-23 13:10:09.000000 | 2022-04-23 20:10:09.000000+0000
 2022-05-01 08:45:50.000000 | 2022-05-01 15:45:50.000000+0000
(6 rows)
```


# Timestamp with Time Zone



## Overview

Oxla provides you with two data types for handling timestamps:

1.  [**Timestamp without Time Zone**](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-4-timestamp-without-time-zone/timestamp-without-time-zone): It allows you to store both date and time.

2.  **Timestamp with Time Zone**: It stores date and time values but does not store time zone information within the database. Instead, it processes the time zone information during operations.
    1.  During **INSERT** operation, the time zone is ignored. The date and time are stored without considering the time zone.

    2.  During **the SELECT** operation, the time zone information from the user's session is also ignored. The data is returned exactly as it is stored without adjusting the time zone.

<Warning>**Important Note:** <br /> Keep in mind that all user sessions have a local timezone associated with them, affecting how timestamps `with time zone` values are displayed. <br /><br /> The timezone information **is not stored in the database**. Consequently, every time a user requests a value of this type, Oxla converts from UTC to the user's local timezone before displaying it.</Warning>

On this page, you will learn about the timestamp with the time zone.

## Format

The `timestamp with time zone` data type has the following format:

```sql
YYYY-MM-DD HH:MM:SS.SSSSSS+TZ
```

*   `YYYY`: Four-digit year

*   `MM`: One / two-digit month

*   `DD`: One / two-digit day

*   `HH`: One / two-digit hour (valid values from 00 to 23)

*   `MM`: One / two-digit minutes (valid values from 00 to 59)

*   `SS`: One / two-digit seconds (valid values from 00 to 59)

*   `[.SSSSSS]`: Up to six fractional digits (microsecond precision)

*   `+TZ`: Time zone offset in the format +/-HH:MM (e.g., +05:30, -08:00)

## Examples

### Case #1: Create a table

Let's create a table named `event_log` that consists of a timestamp without a time zone and a timestamp with time zone columns. The values in the `event_timestamp_tz` are in the “Europe/Moscow” timezone.

```sql
CREATE TABLE events_log (
    event_name TEXT,
    event_timestamp TIMESTAMP WITHOUT TIME ZONE,
    event_timestamp_tz TIMESTAMP WITH TIME ZONE
);
INSERT INTO events_log (event_name, event_timestamp, event_timestamp_tz)
VALUES
    ('Event 1', '2023-07-27 12:30:00', '2023-07-27 12:30:00+03:00'),
    ('Event 2', '2023-07-27 08:45:00', '2023-07-27 08:45:00+03:00'),
    ('Event 3', '2023-07-27 20:15:00', '2023-07-27 20:15:00+03:00');
```

The table has been successfully created after executing the above query:

```sql
COMPLETE
INSERT 0 3
```

### Case #2: Display the table

Run the `SELECT` statement to get all records of the table:

```sql
SELECT event_timestamp, event_timestamp_tz
FROM events_log;
```

It will return the result as displayed below. We can see that the `event_timestamp_tz` is converted to UTC timezone.

```sql
      event_timestamp       |       event_timestamp_tz        
----------------------------+---------------------------------
 2023-07-27 12:30:00.000000 | 2023-07-27 09:30:00.000000+0000
 2023-07-27 08:45:00.000000 | 2023-07-27 05:45:00.000000+0000
 2023-07-27 20:15:00.000000 | 2023-07-27 17:15:00.000000+0000
(3 rows)
```

### Case #3: Ordering Table by Timestamp

Let’s assume we want to sort the events based on the `event_timestamp` column and display the corresponding UTC in the `event_timestamp_tz` column. Run the following query:

```sql
SELECT 
  event_timestamp, 
  event_timestamp_tz,
  event_timestamp AT TIME ZONE 'UTC' AS utc_time
FROM 
  events_log
ORDER BY 
  event_timestamp;
```

We’ll retrieve the `event_timestamp` and `event_timestamp_tz` columns and calculate the corresponding UTC time using the `AT TIME ZONE 'UTC'` operator.&#x20;

We then order the results based on the `event_timestamp` column, giving us a sorted list of events with their corresponding local and UTC times.

```sql
      event_timestamp       |       event_timestamp_tz        |            utc_time             
----------------------------+---------------------------------+---------------------------------
 2023-07-27 08:45:00.000000 | 2023-07-27 05:45:00.000000+0000 | 2023-07-27 08:45:00.000000+0000
 2023-07-27 12:30:00.000000 | 2023-07-27 09:30:00.000000+0000 | 2023-07-27 12:30:00.000000+0000
 2023-07-27 20:15:00.000000 | 2023-07-27 17:15:00.000000+0000 | 2023-07-27 20:15:00.000000+0000
(3 rows)
```

## AT TIME ZONE Operator

The `AT TIME ZONE` operator in timestamp with time zone converts the given timestamp with time zone to the new time zone, with no time zone designation.

**Syntax:**

```sql
SELECT TIMESTAMP WITH TIME ZONE 'timestamp' AT TIME ZONE 'TIME_ZONE';
```

*   `timestamp`: The date and time value with the time zone.

*   `TIME_ZONE`: The target time zone to which the timestamp will be converted. The user's timezone is fixed to UTC.

**Example:**

In this example, we will convert a specified timestamp with time zone into the UTC timezone.

```sql
SELECT TIMESTAMP WITH TIME ZONE '2023-03-04 10:29:90-05' AT TIME ZONE 'UTC';
```

The result will be a timestamp without a time zone.

```sql
             f              
----------------------------
 2023-03-04 15:30:30.000000
(1 row)
```

###


# Time Type



## Overview

The `TIME` data type in Oxla stores time values without any date information. It represents a specific time of day, independent of any time zone or date.&#x20;

## Format

The format for the TIME data type is as follows:

```sql
HH:MM:SS[.SSSSSS]
```

*   `HH`: One or two-digit hour (valid values from 00 to 23).

*   `MM`: One or two-digit minutes (valid values from 00 to 59).

*   `SS`: One or two-digit seconds (valid values from 00 to 59).

*   `[.SSSSSS]` : Optional fractional seconds, with up to six decimal places (microsecond precision).

## Examples

### #Case 1: Create a Schedule Table

Let's create a table to manage employee schedules, containing their names and the time they are scheduled to start work. The TIME data type will be used for the `start_time` column.

```sql
CREATE TABLE employee_schedule (
    employee_name TEXT,
    start_time TIME
);

INSERT INTO employee_schedule (employee_name, start_time)
VALUES
('John Doe', '08:30:00'),
('Jane Smith', '09:00:00'),
('Michael Johnson', '10:15:00');
```

The table has been successfully created after executing the above query:

```sql
COMPLETE
INSERT 0 3
```

### #Case 2: View the Employee Schedule

To view all employee schedules in the `employee_schedule` table, we can use the `SELECT` statement.

```sql
SELECT * FROM employee_schedule;
```

The output will display the employee names and their corresponding scheduled start times:

```sql
  employee_name  |   start_time    
-----------------+-----------------
 John Doe        | 08:30:00.000000
 Jane Smith      | 09:00:00.000000
 Michael Johnson | 10:15:00.000000
(3 rows)
```


# Time Operators



Time operators in Oxla allow you to perform various operations on dates, times, and intervals. Here's a guide to using these operators:

## **1. DATE + INTEGER**

Add a specific number of days to a date.

**Example**

```sql
select date '2022-03-15' + 14 as "result";
```

The result will be 14 days after '2022-03-15'.

```sql
   result   
------------
 2022-03-29
```

### 1.1. INTEGER + DATE

Adding and multiplying time operators can also be done in reverse order. For example, we add a number of days to a date in the format of `Integer + Date`.

```sql
select 14 + date '2022-03-15' AS "result";
```

The result will be the same, which is 14 days after '2022-03-15' is '2022-03-29'.

```sql
   result   
------------
 2022-03-29
```

## **2. DATE + INTERVAL**

Add a specified interval to a date.

**Example**

```sql
select date '2022-03-15' + interval '3 months' as "result";
```

The result will be the date three months after '2022-03-15'.

```sql
           result           
----------------------------
 2022-06-15 00:00:00.000000
```

## **3. DATE - INTEGER**

Subtract a certain number of days from a date.

**Example**

```sql
select date '2022-03-15' - 7 as "result";
```

The result will be 7 days before '2022-03-15'.

```sql
   result   
------------
 2022-03-08
```

## **4. DATE - INTERVAL**

Subtract a specified interval from a date.

**Example**

```sql
select date '2022-03-15' - interval '2 hour' as "result";
```

The result will be the timestamp with two hours before '2022-03-15'.

```sql
           result           
----------------------------
 2022-03-14 22:00:00.000000
```

## **5. DATE - DATE**

Subtract dates.

**Example**

```sql
select date '2023-03-15' - date '2023-01-10' as "result";
```

The number of days elapsed between '2023-03-15' and '2023-01-10' is 64 days.

```sql
 result 
--------
     64
```

## **6. DATE + TIME**

Add a time-of-day to a date.

**Example**

```sql
select date '2010-05-20' + time '02:00' as "result";
```

The result will be a timestamp with the specified time added to the given date.

```sql
           result           
----------------------------
 2010-05-20 02:00:00.000000
```

## **7. TIME + INTERVAL**

Add a certain interval to a given time.

**Example**

```sql
select time '12:30' + interval '1 hour' as "result";
```

The result will be the time 1 hour after '12:30'.

```sql
     result      
-----------------
 13:30:00.000000
```

## **8. TIME - INTERVAL**

Subtract a specified interval from a given time.

**Example**

```sql
select time '18:45' - interval '45 minutes' as "result";
```

The result will be the time 18:00.

```sql
     result      
-----------------
 18:00:00.000000
```

## **9. TIME - TIME**

Get a time difference by subtracting one time from another.

**Example**

```sql
select time '10:00' - TIME '08:20' as "result";
```

In this example, the time difference between the two provided times is 1 hour and 40 minutes.

```sql
     result      
-----------------
 01:40:00.000000
```

## **10. TIMESTAMP + INTERVAL**

Add a timestamp and an interval.&#x20;

**Example**

```sql
select timestamp '2021-01-05 12:00:00' + interval '5 days' as "result";
```

The result will be a new timestamp, adding 5 days to '2021-01-05 12:00:00'.

```sql
           result           
----------------------------
 2021-01-10 12:00:00.000000
```

## **11. TIMESTAMP - INTERVAL**

Subtract an interval from a timestamp.

**Example**

```sql
select timestamp '2022-01-04 12:00:00' - interval '3 days' as "result";
```

In this example, it subtracts 3 days from '2022-01-04 12:00:00'.

```sql
           result           
----------------------------
 2022-01-01 12:00:00.000000
```

## **12. TIMESTAMP - TIMESTAMP**

Get an interval by subtracting one timestamp from another.&#x20;

**Example**

```sql
select timestamp '2022-01-05 18:30:00' - timestamp '2022-01-01 12:00:00' as "result";
```

It gives the interval between the two timestamps, 102 hours and 30 minutes.

```sql
      result      
------------------
 102:30:00.000000
```

## **13. INTERVAL + INTERVAL**

Add intervals.

**Example**

```sql
select interval '2 months 2 days' + interval '6 days' as "result";
```

It adds 6 days to 2 days, resulting in a total of 2 months and 8 days.

```sql
    result     
---------------
 2 mons 8 days
```

## **14. INTERVAL - INTERVAL**

Subtract intervals.

**Example**

```sql
select interval '2 months' - interval '20 days' as "result";
```

It subtracts 20 days from 2 months.

```sql
     result      
-----------------
 2 mons -20 days
```

## **15. INTERVAL \* INTEGER**

Multiply an interval by an integer.

**Example**

```sql
select interval '2 hours' * 3 as "result";
```

It multiplies '2 hours' by 3, the result is 6 hours.

```sql
     result      
-----------------
 06:00:00.000000
```

## 16. INTERVAL \* DOUBLE PRECISION

Multiply an interval by a scalar.

**Example**

```sql
select interval '2 hours' * 1.5 as "result";
```

It multiplies '2 hours' by 1.5, and returns 3 hours.

```sql
    result      
-----------------
 03:00:00.000000
```

## 17. INTERVAL / NUMBER

Divide an interval by an integer or scalar.

### a) Divide by an integer

```sql
select interval '1 hour' / 2 as "result";
```

It divides '1 hour' by 2, and returns 30 minutes.

```sql
    result      
-----------------
 00:30:00.000000
```

### b) Divide by a scalar

```sql
select interval '2 hours' / 1.5 as "result";
```

It divides '2 hours' by 1.5, and returns 1 hour 20 minutes.

```sql
     result      
-----------------
 01:20:00.000000
```


# Interval Type



## Overview

The Interval data type represents periods between dates or times, which can be precisely calculated and expressed through various units. Those can be combined and include additional options for different interval calculations.

In this doc, you'll find more about the **interval syntax**, learn what are **supported units and abbreviations**, browse through **examples** and finally find out how to **extract data from intervals**.

## Syntax

The syntax for specifying an interval is as follows:

```sql
SELECT INTERVAL 'quantity unit [quantity unit...] [direction]' [OPTION]
```

**Parameters Description**

| **Parameter** | **Description**                                                                                                                                                              |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `quantity`    | The value representing the number of units                                                                                                                                   |
| `unit`        | - Year, month, day, hour, minute, etc. <br /> - Abbreviations, short forms and dash format is supported <br /> - Plural forms are also acceptable (e.g. months, days, weeks) |
| `direction`   | An optional parameter: **ago** or **empty string**                                                                                                                           |
| `OPTION`      | Additional options when parsing interval                                                                                                                                     |

## Supported Units and Abbreviations

| **Unit**    | **Abbreviations**  |
| ----------- | ------------------ |
| Millennium  | -                  |
| Century     | -                  |
| Decade      | -                  |
| Year        | `y`, `yr`, `yrs`   |
| Month       | -                  |
| Week        | -                  |
| Day         | `d`                |
| Hour        | `h`, `hr`, `hrs`   |
| Minute      | `min`, `mins`, `m` |
| Second      | `s`, `sec`, `secs` |
| Millisecond | `ms`               |
| Microsecond | -                  |

## Options for Interval Parsing

*   `YEAR`, `MONTH`, `DAY`, `HOUR`, `MINUTE`, `SECOND`
*   `YEAR TO MONTH`, `DAY TO HOUR`, `DAY TO MINUTE`, `DAY TO SECOND`, `HOUR TO MINUTE`,  `HOUR TO SECOND`, `MINUTE TO SECOND`

## Examples

#### Select Interval With Multiple Units

In this example, we'll calculate the interval by combining multiple units of time.

```sql
SELECT INTERVAL '5 years 4 months 2 weeks 3 days 5 hours 10 minutes 25 seconds' as "Interval";
```

```sql
            Interval             
---------------------------------
 5 years 4 mons 17 days 05:10:25
(1 row)
```

#### Using Abbreviations

This example shows how to use abbreviated units for time intervals.

```sql
SELECT INTERVAL '10 yr 8 months 2 weeks 6 days 5 hrs 10 min 20 s as "Interval";
```

```sql
             Interval             
----------------------------------
 10 years 8 mons 20 days 05:10:20
(1 row)
```

#### Using Dash Format

Here you'll find out how to use the dash format for specifying intervals.

```sql
SELECT INTERVAL '1-2 3 DAYS 04:05:06.070809' as "Interval";
```

```sql
               Interval               
--------------------------------------
 1 year 2 mons 3 days 04:05:06.070809
(1 row)
```

#### Parsing Intervals Using Specific Units

By running the code below, the output will show everything up to minutes and ignore seconds and miliseconds.

```sql
SELECT INTERVAL '1-2 5 DAYS 07:08:06.040809' MINUTE as "Interval";
```

```sql
           Interval            
-------------------------------
 1 year 2 mons 5 days 07:08:00
(1 row)
```

#### Displaying Specific Range Only

Executing the query below will result only years and months being displayed excluding days, hours, minutes, and seconds from the input.

```sql
SELECT INTERVAL '2-4 5 DAYS 04:05:06.070809' YEAR TO MONTH as "Interval";
```

```sql
    Interval    
----------------
 2 years 4 mons
(1 row)
```

#### Extracting Data From Interval

In order to extract the interval numbers from the timestamp, you can use the **EXTRACT()** function the following way:

```sql
SELECT EXTRACT (field FROM interval)
```

*   `field`: supports time units, such as `YEAR`, `MONTH`, `DAY`, `HOUR`, etc.
*   `interval`: specified timestamp.

```sql
SELECT EXTRACT (MINUTE
FROM INTERVAL '2 hours 30 minutes');
```

As the output of the above query, only the minutes part will be returned.

```sql
   extract    
------------
        30
(1 row)
```

<Note>If you query a field that is not specified in the timestamp, you will get `0` as an output.</Note>


# Text Type



## Overview

The text data type is a UTF8-encoded text with Unicode support, which stores a sequence of characters (text).

<Warning>**STRING** is an alias for the **TEXT** data type. You can create a table using **STRING**. However, it will be stored and processed equivalently to **TEXT**.</Warning>

## **Examples**

Let's create an employee table with a text data type in each column:

```sql
CREATE TABLE employee (
    employeeName TEXT,
    employeeDept TEXT,
    employeeRole TEXT
);
INSERT INTO employee (employeeName, employeeDept, employeeRole)
VALUES ('John','Finance','Staff'),
       ('Maya','Product','Staff'),
       ('Jane','Finance','Staff'),
       ('Phil','HR','Manager');
```

<Check>Insert the text value between the single quotes **' '**.</Check>

The created table is shown below:

```sql
+---------------+---------------+---------------+
| employeename  | employeedept  | employeerole  |
+---------------+---------------+---------------+
| John          | Finance       | Staff         |
| Maya          | Product       | Staff         |
| Jane          | Finance       | Staff         |
| Phil          | HR            | Manager       |
+---------------+---------------+---------------+
```

## **Text With SUBSTR Function**

The `substr()` function extracts a specific number of characters from a text.&#x20;

### **Syntax**

```sql
substr( text, start_position, length )
```

Let's analyze the above syntax:

*   `text`is the specified text.

*   `start_position` is used as the starting position, specifying the part from which the substring will be returned. It is written as an int value.&#x20;

*   `length` is used to determine the number of characters to be extracted. It can be one or more characters.

<Note>The first position in the `text` is 1.</Note>

### **Example**

Insert a value into the text column.

```sql
SELECT substr('Watermelon',6,5) AS "Fruit";
```

The updated table is shown below:

```sql
+-------------+
| Fruit       |    
+-------------+
| melon       |
+-------------+
```

## **Text With LENGTH Function**

The `length()` function returns the number of characters in a text.&#x20;

<Note>The number of characters might be different from the byte length.</Note>

### **Syntax**

The length function will take a text as a parameter.

```sql
LENGTH (text);
```

### **Example**

Insert a value into the text column.

```sql
SELECT LENGTH ('UNITED STATES');
```

The updated table is shown below.

```sql
+---------+
| f       |
+---------+
| 13      | 
+---------+
```

<Info>The `length()` function will also count spaces.</Info>


# Numeric Data Type - Aliases



We allow aliases that can be used interchangeably with the primary data types. However, while these aliases can be used, they will be mapped to their corresponding primary data types during data processing.

Here, we'll discuss the numeric data type aliases:

### **INTEGER Alias**

The `INTEGER` alias is an alternative name for the `INT` data type. For example, the following two queries are functionally the same:

```sql
CREATE TABLE ExampleTable (
    id INTEGER,
);

-- Functionally the same as the previous table
CREATE TABLE AnotherTable (
    id INT,
);
```

<Warning>It's important to note that even though `INTEGER` is used, the data is stored and treated as `INT`.</Warning>

### **LONG Alias**

The `LONG` alias is often used to represent larger integer values. For example:

```sql
CREATE TABLE LargeValues (
    value LONG,
);

-- Functionally the same as the previous table
CREATE TABLE LargeValuesEquivalent (
    value BIGINT,
);
```

<Warning>Any usage of `LONG` is stored and treated as `BIGINT`.</Warning>

### **FLOAT Alias**

The `FLOAT` alias corresponds to the `REAL` data type. For example:

```sql
CREATE TABLE FloatExample (
    price FLOAT,
);

-- Functionally the same as the previous table
CREATE TABLE FloatEquivalent (
    price REAL,
);
```

<Warning>When you use `FLOAT`, it's stored and treated as `REAL`.</Warning>

### **DOUBLE Alias**

The `DOUBLE` alias is used to define `DOUBLE PRECISION` floating-point numbers. For example:

```sql
CREATE TABLE DoubleExample (
    measurement DOUBLE,
);

-- Functionally the same as the previous table
CREATE TABLE DoubleEquivalent (
    measurement DOUBLE PRECISION,
);
```

<Warning>When you use `DOUBLE`, it's stored and treated as `DOUBLE PRECISION`.</Warning>


# Numeric Type



## Int Type

The `INT` data type represents whole numbers without decimal points. It is a 32-bit signed integer with a range from -2147483648 to 2147483647.

### Format

```sql
column_name INT
```

### Example

The following is an example of how to create a column using an `INT` type.

```sql
CREATE TABLE cities (
    city_id INT,
    cityname TEXT,
    population INT
);
INSERT INTO cities (city_id, cityname, population)
VALUES 
(8557411, 'New York', 8419000),
(8557421, 'London', 8982000),
(8557451, 'Hongkong', 7482000),
(8557491, 'Seoul', 9776000);
```

Now, run the following query to display the table.

```sql
SELECT * FROM cities;
```

It will result in a table show below.

```sql
 city_id | cityname | population 
---------+----------+------------
 8557411 | New York |    8419000
 8557421 | London   |    8982000
 8557451 | Hongkong |    7482000
 8557491 | Seoul    |    9776000
(4 rows)
```

## Bigint Type

The `BIGINT` data type stores large whole numbers that exceed the `INT` range. It is a 64-bit signed integer with a range from -9223372036854775808 to 9223372036854775807.

### Format

```sql
column_name BIGINT
```

### Example

The following is an example of how to create a column using the `BIGINT` type:

```sql
CREATE TABLE galaxies (
    galaxy_name TEXT,
    star BIGINT
);
INSERT INTO galaxies (galaxy_name, star)
VALUES 
('Milky Way', 100000000000),
('Cigar', 30000000000),
('Andromeda', 1000000000000),
('Cosmos', 2000000000000000000);
```

Now, run the following query to display the table:

```sql
SELECT * FROM galaxies;
```

You will get the following output:

```sql
 galaxy_name |        star         
-------------+---------------------
 Milky Way   |        100000000000
 Cigar       |         30000000000
 Andromeda   |       1000000000000
 Cosmos      | 2000000000000000000
(4 rows)
```

## Real Type

The `REAL` data type is a 32-bit floating-point number compliant with the IEEE 754 binary32 format.

### Format

```sql
column_name REAL
```

### Example

**1. Create a Table**

Here, we are creating a table with a `REAL` column type.

```sql
CREATE TABLE numbers (
    column_1 REAL
);

INSERT into numbers (column_1)
VALUES (1.234568);
```

Display the table with the following query.

```sql
SELECT * FROM numbers;
```

The stored value is shown below.

```sql
 column_1 
----------
 1.234568
(1 row)
```

**2. Rounding**

Rounding might happen if the precision of an input number is too high.&#x20;

```sql
CREATE TABLE numbers1 (
column_1 REAL
);

INSERT into numbers1 (column_1)
VALUES (1.2345689);
```

Display the table with the following query.

```sql
SELECT * FROM numbers1;
```

The table below shows the value after rounding.

```sql
 column_1 
----------
 1.234569
(1 row)
```

**3. Create a Table With Numbers Exceeding the Range**

The `REAL` type only stores 32-bit floating-point numbers. In this example, we input the numbers that exceed the range.

```sql
CREATE TABLE numbers2 (
    column_1 REAL
);

INSERT into numbers2 (column_1)
VALUES (1.2345682991822);
```

Display the table with the following query.

```sql
SELECT * FROM numbers2;
```

The final output will only return numbers that match the range.

```sql
 column_1  
-----------
 1.2345684
(1 row)
```

## Double Precision Type

The `DOUBLE PRECISION` data type is a 64-bit floating-point number compliant with the IEEE 754 binary64 format.

### Format

```sql
column_name DOUBLE PRECISION
```

### Example

**1. Create a Table**

Here, we are creating a table with a `DOUBLE PRECISION` type column.

```sql
CREATE TABLE numbersdouble (
    column_1 DOUBLE PRECISION
);

INSERT into numbersdouble (column_1)
VALUES (1.234568817283122);
```

Display the table with the following query.

```sql
SELECT * FROM numbersdouble;
```

The output is shown below.

```sql
     column_1      
-------------------
 1.234568817283122
(1 row)
```

**2. Rounding**

Rounding might happen if the precision of an input number is too high.&#x20;

```sql
CREATE TABLE numbersdouble1 (
    column_1 DOUBLE PRECISION
);

INSERT into numbersdouble1 (column_1)
VALUES (1.234568817283122773);
```

Display the table with the following query.

```sql
SELECT * FROM numbersdouble1;
```

The table below shows the value after rounding.

```sql
      column_1      
--------------------
 1.2345688172831228
(1 row)
```

## Scientific Notation Support

Oxla now supports scientific notation for floating-point types. This feature allows you to use expressions like 1.1e+3, 1e-20, 1.1e02 and similar in your queries.

**Example**

```sql
SELECT 1.1e+3, 1e-20, 1.1e02;
```

***Output***

```sql
 ?column? | ?column? | ?column?
----------+----------+----------
     1100 |    1e-20 |      110
(1 row)
```


# Overview



While creating a table, you need to specify a data type for each column to define what kind of data you want to store. This section will look into the various data types supported in Oxla. Now, let’s get an overview of each data type:

| **Data Types**                | **Definition**                                             | **Format**                                     |
| ----------------------------- | ---------------------------------------------------------- | ---------------------------------------------- |
| `BOOL`                        | Boolean value.                                             | `True` or `False`.                             |
| `TEXT`                        | UTF8 encoded string with Unicode support.                  | 'text'                                         |
| `DATE`                        | Date value.                                                | `YYYY-MM-DD`                                   |
| `TIMESTAMP WITHOUT TIME ZONE` | Time and date values without a time zone.                  | `YYYY-MM-DD [HH:MM:SS[.SSSSSS]]`               |
| `TIMESTAMP WITH TIME ZONE`    | Date and time values, including the time zone information. | `YYYY-MM-DD HH:MM:SS.SSSSSS+TZ`                |
| `TIME`                        | Time values without any date information.                  | `HH:MM:SS[.SSSSSS]`                            |
| `JSON`                        | A value in JSON standard format.                           | `variable_name JSON`                           |
| `INTERVAL`                    | Encodes a span of time                                     | `year-month (YYYY-MM); day-time (DD HH:MM:SS)` |
| `INT`                         | 32-bit signed integer                                      | one or more digits "0" to "9"                  |
| `BIGINT`                      | 64-bit signed integer                                      | large numeric/decimal value                    |
| `REAL`                        | 32-bit floating point number                               | `float(n)`                                     |
| `DOUBLE PRECISION`            | 64-bit floating point number                               | `decimal(p, s)`                                |


# ABS



## Overview

The `ABS()` function returns an absolute number, i.e., the positive value of a number. The data type of the returned value will depend on the data type of the value passed to the `ABS()` function.

## Syntax

The syntax for the `ABS() `function is as follows:

```sql
ABS(x)
```

The `ABS()` function requires one argument:

*   `x`: An expression that evaluates to a number.

<Note>The **ABS()** function will return the negation of the negative numbers.</Note>

## Examples

### Case #1: Absolute value of a negative number

The following example demonstrates how the `ABS()` function can be used to obtain the absolute value of a negative number:

```sql
SELECT ABS(-10.25);
```

It will return an absolute value of the passed argument:

```sql
+--------+
| f      | 
+--------+
| 10.25  |
+--------+
```

### Case #2: ABS() function with an expression

The following example demonstrates how the `ABS()` function can be used with an expression to obtain the absolute value of the result:

```sql
SELECT ABS( 100 - 250);
```

The result of the above statement is **-150**. However, you will get the output **150**, as 150 is the positive version of -150.

```sql
+------+
| f    | 
+------+
| 150  |
+------+
```

### Case #3: Using the ABS() function with a table

The following example demonstrates how the `ABS()` function can be used with a table to obtain the absolute values of all numbers in a specific column:

1.  First, create a table named absTable containing an ***initialValue*** column with some positive and negative values:

```sql
CREATE TABLE absTable(initialValue float);

INSERT INTO absTable(initialValue)
VALUES 
(550),
(-210), 
(72.12),
(-87.93),
(-0.0);
```

2.  Next, use the following query to find the absolute value of all numbers:

```sql
SELECT initialValue, ABS(initialValue) AS absoluteValue
FROM absTable;
```

3.  The above query will retrieve all values in the **"initialValue"** column and their absolute values in the **"absoluteValue"** column. The output will look something like this:

```sql
+---------------+----------------+
| initialValue  | absoluteValue  |
+---------------+----------------+
| 550           | 550            |
| -210          | 210            |
| 72.12         | 72.12          |
| 87.93         | 87.93          |
| -0            | 0              |
+---------------+----------------+
```


# CBRT



## Overview

The `CBRT()` function calculates and returns the cube root of a given number. In mathematical terms, for a number *x*, its cube root *y* is determined by the equation *y³ = x*.

## Syntax

The syntax for the `CBRT()` function is as follows:

```sql
CBRT(number)
```

Where:

*   `number`: This is a required value representing the number for which you want to calculate the cube root. It can be a positive or negative whole number, a decimal, or even an expression that evaluates to a number.

For example, you can use expressions like `SELECT CBRT(some_column) from test_table`, assuming `some_column` contains a numeric value.

<Note>**Return Value:** <br /> - It will return `NULL` if the argument is `NULL`. <br /> - It will give an error if you input a parameter that is not a numeric type.</Note>

## Examples

Below are several usage examples of the `CBRT()` function:

### Case #1: **Basic Cube Root Calculation**

Consider the following example:

```sql
  SELECT CBRT(125);
```

The result of this query will be:

```sql
 cbrt 
------
    5
```

### Case #2: **Cube Root of a Negative Value**

To calculate the cube root of a negative number, use the `CBRT()` function as shown:

```sql
  SELECT CBRT(-125);
```

The final result is as follows.

```sql
 cbrt 
------
   -5
```

### Case #3: **Cube Root of Decimal Result**

For calculations with decimal numbers, use the `CBRT()` function as demonstrated below:

```sql
SELECT CBRT(32);
```

The result will be a decimal value, as shown below:

```sql
       cbrt        
-------------------
 3.174802103936399
```

### Case #4: **Cube Root of Decimal Input**

In this scenario, fractional seconds are incorporated into the argument:

```sql
SELECT CBRT(0.12815);
```

The result will be the cube root of the provided decimal value.

```sql
    cbrt    
------------
 0.50416523
```

### Case #5: Handling Incorrect Argument

When a non-numeric argument is provided, the `CBRT()` function works as follows:

```sql
SELECT CBRT('abc');
```

An error will be generated, and the result will not be valid.

```sql
invalid input syntax for type double precision: "abc"
```

### Case #6: CBRT Operator (`||/(x)`)

Here's an example using the CBRT operator (`||/(x)`) to calculate the cube root of a given number:

```sql
SELECT ||/(1728) AS cbrt_operator;
```

In this example, we calculate the cube root of 1728 using the CBRT operator. The result of this query will be:

```sql
   cbrt_operator    
--------------------
 12.000000000000002
```


# CEIL



## Overview

The `CEIL()` function returns the nearest positive or negative integer value greater than or equal to the provided decimal input number.

## Syntax

The syntax of the `CEIL()` function is as follows:

```sql
CEIL(x)
```

The `CEIL()` function requires one argument:

*   `x`: A positive or a negative decimal number (or an expression that evaluates to a decimal number).

## Examples

### Case #1: Rounding up a positive decimal value

The following example demonstrates how the `CEIL() `function rounds up a positive decimal value:

```sql
SELECT CEIL (300.55);
```

As shown below, it will return 301, as it is the nearest integer value greater than 300.55.

```sql
+------+
| f    |
+------+
| 301  |
+------+
```

### Case #2: Rounding up a negative decimal value

The following example demonstrates how the `CEIL() `function rounds up a negative decimal value:

```sql
SELECT CEIL(-89.9) AS "Ceil";
```

The output of this statement will be -89, as -89 is the nearest integer value greater than or equal to -89.9, as shown below.

```sql
+-------+
| Ceil  |
+-------+
| -89   |
+-------+
```

### Case #3: Using the `CEIL()` function with a table

The following example demonstrates how the `CEIL()` function can be used with a table to round up the values in a specific column:

1.  First, create a table called ***CeilRecords*** with the following query:

```sql
CREATE TABLE CeilRecords (numbers float);
  
INSERT INTO CeilRecords(numbers) 
VALUES 
    (-28.85),
    (-9.4),
    (0.87),
    (78.16),
    (42.16);
```

The above statement will create a table called **"CeilRecords"** with a column called **"numbers"** and insert 5 decimal values into it.

2.  The statement below can be used to retrieve and round up the value for all records in the column \***numbers**:

```sql
SELECT *, CEIL(numbers) AS CeilValue FROM CeilRecords;
```

The final result will contain the following:

*   A **numbers** column with initial decimal values.

*   A **CeilValue** column with rounded-up integer values.

```sql
+---------+------------+
| numbers  | CeilValue  |
+---------+------------+
| -28.85  | -28        |
| -9.4    | -9         |
| 0.87    | 1          |
| 78.16   | 79         |
| 42.16   | 43         |
+---------+------------+
```

\`\`


# EXP



## **Overview**

The `EXP()` function returns the exponential value of a number specified in the argument.

## **Syntax**

The syntax for the `EXP()` is:

```sql
EXP(number);
```

Where:

*   `number`: The number for which you want to calculate the exponential value. Equivalent to the formula `e^number`.

## **Examples**

Let's explore examples to see how the `EXP()` function works.

### Case #1: **Basic Usage**

In this case, we use the `EXP()` function with positive and negative values.

```sql
SELECT EXP(0) AS "EXP of 0", 
      EXP(1) AS "EXP of 1",
      EXP(2) AS "EXP of 2",
      EXP(-1) AS "EXP of -1",
      EXP(-2) AS "EXP of -2";
```

You will get the following result:

```sql
EXP of 0  |     EXP of 1      |     EXP of 2     |      EXP of -1      |     EXP of -2      
----------+-------------------+------------------+---------------------+--------------------
        1 | 2.718281828459045 | 7.38905609893065 | 0.36787944117144233 | 0.1353352832366127
```

### Case #2: Using `EXP()` with Fractions

This case uses the `EXP()` function with a fractional argument.

```sql
SELECT EXP(3.2);
```

Here is the result:

```sql
        exp         
--------------------
 24.532531366911574
```

### Case #3: Using `EXP()` with Expressions

Here, we use the `EXP()` function with expressions.

```sql
SELECT EXP(5 * 5);
```

See the result below:

```sql
        exp        
-------------------
 72004899337.38588
```


# FLOOR



## **Overview**

The `FLOOR()` returns a number rounded down that is less than or equal to the specified argument.&#x20;

## **Syntax**

The syntax for the `FLOOR()` function in Oxla is:

```sql
FLOOR(x)
```

The `FLOOR()` function requires one argument:

`x`: A positive or a negative decimal number (or an expression that evaluates to a decimal number).

## **Examples**

### Case #1: Rounding Down a Positive Decimal Value

The following example demonstrates how the `FLOORL()` function rounds down a positive decimal value:

```sql
SELECT FLOOR(345.6765467);
```

It will return 345 as it is the closest value smaller than the argument.

```sql
+------+
| f    |
+------+
| 345  |
+------+
```

### Case #2: Rounding Down a Negative Decimal Value

The following example demonstrates how the `FLOORL()` function rounds down a negative decimal value:

```sql
SELECT FLOOR(-0.987657);
```

You will get the following result as it is the nearest integer smaller than or equal to the specified argument.

```sql
+-------+
| f     |
+-------+
| -1    |
+-------+
```

### Case #3: Using the FLOOR() Function With a Table

The following example demonstrates how the `FLOOR()` function can be used with a table to round down the values in a specific column:

1.  Create a new table called **FloorRecords** with double-precision values using the query below:

```sql
CREATE TABLE FloorRecords (numbers float);
INSERT INTO FloorRecords VALUES (3.987), (4.325), (-0.76), (-22.57);
```

2.  Retrieve the table with its value by running the following query:

```sql
SELECT * ,FLOOR(numbers) AS Floorvalue FROM FloorRecords;
```

3.  The return table will contain the following:

*   **numbers,** the column with the initial double-precision values.

*   **FloorValue**, the column with the rounded-down values. 

```sql
+------------+---------------+
| numbers    | Floorvalue    |
+------------+---------------+
| 3.987	     | 3             |
| 4.325	     | 4             |
| -0.76	     | -1            |
| -22.57     | -23           |
+------------+---------------+
```


# GREATEST



## **Overview**

The `GREATEST()` function extracts the greatest or largest value from a set of values. It needs at least one argument to work with, and if you mix different types, like a text and a number, it will return an error.&#x20;

For example, comparing the greatest value among 4, "two", and 9 would result in an error.

## **Syntax**

The syntax for the `GREATEST()` function is as follows:

```sql
GREATEST(value_1, [value_n])
```

Where:

*   `value_1`: Represents the first value.

*   `value_n`: Represents one or more additional values, separated by commas.

<Note>**Info:**<br /> -`NULL` values within the expressions are ignored. <br /> - The result will be `NULL` if all expressions evaluate to `NULL`.</Note>

## **Examples**

Here are examples that illustrate the usage of the `GREATEST()` function:

### Case #1: **Basic Usage**

Consider the following example:

```sql
SELECT GREATEST(3,5,8,9,10);
```

The query will return `3`, the smallest value among the provided values.

```sql
greatest 
---------
     10
```

### Case #2: **String Comparison**

String comparison is also supported, as shown below:

```sql
SELECT GREATEST('apple', 'banana', 'cherry');
```

In this case, the result will be `'cherry'`, the greatest string according to the order.

```sql
greatest 
----------
 cherry
```

### Case #3: **Handling NULL Values**

`NULL` values are ignored when determining the greatest value:

```sql
SELECT GREATEST (5,null,9);
```

The result will be the greatest non-NULL value, which is `9`.

```sql
least 
-------
     9
```

### Case #4: **Positive and Negative Numbers**

Negative numbers can also be compared:

```sql
SELECT GREATEST (4,-4,-8,8);
```

This query will return `8`, the greatest value among the provided numbers.

```sql
least 
-------
    8
```

### Case #5: **Using Table Data**

The `GREATEST` function can also be used to find the Greatest value between column data. For example, let’s create a table named **Student** that stores students' names and scores.

```sql
CREATE TABLE Student(
    Student_name TEXT,
    Student_Class TEXT,
    Subject1 INT,
    Subject2 INT,
    Subject3 INT,
    Subject4 INT
);

INSERT INTO  
    Student(Student_name, Student_Class, Subject1, Subject2, Subject3, Subject4)
VALUES
    ('Sayan', 'Junior', 81, 90, 86, 92 ),
    ('Nitin', 'Junior', 90, 84, 88, 91 ),
    ('Aniket', 'Senior', 81, 80, 87, 95 ),
    ('Abdur', 'Junior', 85, 90, 80, 90  ),
    ('Sanjoy', 'Senio', 88, 82, 84, 90 );
```

Use the `SELECT` statement to view all the records:

```sql
SELECT * FROM Student;
```

```sql
student_name | student_class | subject1 | subject2 | subject3 | subject4 
--------------+---------------+----------+----------+----------+----------
 Sayan        | Junior        |       81 |       90 |       86 |       92
 Nitin        | Junior        |       90 |       84 |       88 |       91
 Aniket       | Senior        |       81 |       80 |       87 |       95
 Abdur        | Junior        |       85 |       90 |       80 |       90
 Sanjoy       | Senio         |       88 |       82 |       84 |       90
```

Now, we will find the greatest marks for every student in all subjects.

```sql
Select Student_name, GREATEST(Subject1, Subject2, Subject3, Subject4) AS Greatest_Mark
FROM Student;
```

```sql
student_name | greatest_mark 
--------------+---------------
 Sayan        |            92
 Nitin        |            91
 Aniket       |            95
 Abdur        |            90
 Sanjoy       |            90
```


# LEAST



## **Overview**

The `LEAST()` function returns the least or smallest value in a list of values. It needs at least one argument to work with, and if you mix different types, like a text and a number, it will return an error.&#x20;

For example, comparing the greatest value among 4, "two", and 9 would result in an error.

## **Syntax**

The syntax for the `LEAST()` function is as follows:

```sql
LEAST(value_1, [value_n])
```

Where:

*   `value_1`: Represents the first value.

*   `value_n`: Represents one or more additional values, separated by commas.

<Note>**Info:**<br /> -`NULL` values in the list will be ignored. <br /> - The result will be `NULL` if all the expressions evaluate to `NULL`.</Note>

## **Examples**

Below are several examples of the `LEAST()` function:

### Case #1: **Basic Usage**

Consider the following example:

```sql
SELECT LEAST(3,5,8,9,10);
```

The query will return `3`, the smallest value among the provided values.

```sql
 least 
-------
     3
```

### Case #2: **String Comparison**

String comparison is also supported, as shown below:

```sql
SELECT LEAST('a','b','c','aa'); 
```

In this case, the result will be `'a'`, as it is the smallest string.

```sql
 least 
-------
     a
```

### Case #3: **Handling NULL Values**

`NULL` values are ignored when determining the smallest value:

```sql
SELECT LEAST (5,null,9);
```

The result will be the smallest non-NULL value, which is `5`.

```sql
 least 
-------
     5
```

### Case #4: **Negative Numbers**

Negative numbers can also be compared:

```sql
SELECT LEAST (4,-4,-8,8);
```

This query will return `-8`, the smallest value among the provided numbers.

```sql
 least 
-------
    -8
```

### Case #5: **Using Table Data**

Suppose we have a table named `grades` containing columns `x`, `y`, and `z`.&#x20;

```sql
CREATE TABLE grades (
    name TEXT,
    x INT,
    y INT,
    z INT
);

INSERT INTO grades (name, x, y, z)
VALUES
    ('Jane', 50, 0, 70),
    ('Rio', 60, 30, 80),
    ('John', 60, 60, 86),
    ('Rose', 80, 90, 88),
    ('Gary', 100, 80, 90);
```

To find the smallest value among these columns, you can use the following query:

```sql
SELECT *, LEAST(x, y, z) AS least_grade FROM grades;
```

This query will add a new column named `least_grade` to the result, displaying the smallest value among columns `x`, `y`, and `z`.

```sql
 name |  x  | y  | z  | least_grade 
------+-----+----+----+-------------
 Jane |  50 |  0 | 70 |           0
 Rio  |  60 | 30 | 80 |          30
 John |  60 | 60 | 86 |          60
 Rose |  80 | 90 | 88 |          80
 Gary | 100 | 80 | 90 |          80
```


# LN



## **Overview**

`LN()` will return the exponential value of its argument, which is recognized as the input parameter's natural logarithm.&#x20;

<Note>**Info:**<br /> The logarithm doesn’t take negative numbers or 0.</Note>

## **Syntax**

The syntax of the `LN()` function is described as follows.

```sql
LN (x)
```

`x`:  A positive or a negative number (or an expression that evaluates to a number).

## **Examples**

### **Case #1: Basic LN() function**

The example below shows that `LN()` function will return the natural logarithm of the number **7,87653**.

```sql
SELECT LN(7.87653);
```

The final result is as follows.

```sql
+-------------+
| f           |
+-------------+
| 2.0638874   |
+-------------+
```

### **Case #2: Using LN() Function With a Table**

In the following example, we will combine `LN()` function with `CREATE TABLE` statement. Therefore we can obtain natural logarithmic values of a specific column.

1.  Create a new table named **LNTable** containing the **initValue** column with an integer value.&#x20;

```sql
CREATE TABLE LNtable(initValue int);
INSERT INTO LNtable(initValue)
VALUES (75), (18), (28);
```

2.  Run the following query to get the logarithm output of the column:

```sql
SELECT * ,LN(initValue) AS lnValue FROM LNtable;
```

3.  It will return the initial value with its natural logarithm value.

*   **initValue** column with the initial integer values.

*   **lnValue** column with the natural logarithm values.

```sql
+------------+---------------------------+
| initValue  | lnValue                   |
+------------+---------------------------+
| 75         | 4.31748811353631          |
| 18         | 2.8903717578961645        |
| 28         | 3.332204510175204         |
+------------+---------------------------+
```


# LOG



# **Overview**

The  `LOG()` function returns the base-10 logarithm or logarithm of the specified base of a given number.

# **Syntax**

The following illustrates the syntax of the `LOG()` function:

```sql
-- base-10 logarithm
LOG(number)

-- logarithm of number
LOG(base, number)
```

Where:

*   `base`: The base number. It must be greater than 0 and not equal to 1.

*   `number`: The number whose logarithm you want to obtain. It must be a positive number and greater than 0.

# **Examples**

Let's explore some examples of the `LOG()` function.

## **Case #1: Get base-10 logarithm**

### 1. Basic Usage

In this case, the `LOG()` function calculates the base-10 logarithm of a specified number.

```sql
SELECT LOG(2), LOG(2.5);
```

You will get the output below:

```sql
        log         |   log   
--------------------+---------
 0.3010299956639812 | 0.39794
```

### 2. Using Negative Value

In this example, the `LOG()` function is applied to negative numbers.

```sql
SELECT LOG(-1);
```

Any input of negative values will give you a `NaN` result.

```sql
 log 
-----
 NaN
```

### 3. Using Null Value

The `LOG()` function will return `NULL` if the argument is `NULL`.

```sql
SELECT LOG(null);
```

You will get a null result when an argument passed is null.

```sql
 log 
-----
    
```

### 4. Using Zero Value

In this example, the `LOG()` takes zero as an argument.

```sql
SELECT LOG(0);
```

You will get the output below:

```sql
    log    
-----------
 -Infinity
```

## **Case #2: Get Logarithm**

### 1. Basic Usage

In this case, the `LOG()` function calculates the logarithm of a specified number.

```sql
SELECT LOG(4, 16), 
       LOG(0.7, 0.8), 
       LOG(0.5, 10),
       LOG(1, null);
```

You will get the output below:

```sql
 log |    log     |    log    | log 
-----+------------+-----------+-----
   2 | 0.62562156 | -3.321928 |    
```

### 2. Using Table

Consider a database table called ***data*** with the following records:

```sql
CREATE TABLE data (
    data_column TEXT,
    x REAL,
    y REAL
);

INSERT INTO data (data_column, x, y) VALUES 
('Data 1', 0.5, 2),
('Data 2', 1, 2),
('Data 3', 5, 2),
('Data 4', 10, 10),
('Data 5', 50, 10);

SELECT * FROM data;
```

```sql
 data_column |  x  | y  
-------------+-----+----
 Data 1      | 0.5 |  2
 Data 2      |   1 |  2
 Data 3      |   5 |  2
 Data 4      |  10 | 10
 Data 5      |  50 | 10
```

Use the `LOG()` function to calculate the logarithm of column ***x*** (as a base) and column \*y \*(as a number):

```sql
SELECT *, LOG(y, x) AS LOG_Value FROM data;
```

You will get the result as shown below:

```sql
 data_column |  x  | y  | log_value 
-------------+-----+----+-----------
 Data 1      | 0.5 |  2 |        -1
 Data 2      |   1 |  2 |         0
 Data 3      |   5 |  2 |  2.321928
 Data 4      |  10 | 10 |         1
 Data 5      |  50 | 10 |   1.69897
```


# Overview



Numeric functions in Oxla are designed to perform mathematical calculations and manipulate integer or floating-point numbers. Oxla supports the following numeric functions:

| **Functions**                                                                                                                 | **Description**                                                                                                  |
| ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| [CEIL()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/ceil)                                | This function rounds up to the nearest positive or negative integer value greater than or equal to the argument. |
| [ABS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/abs)                                  | This function returns the absolute value of an argument, regardless of whether it is positive or negative.       |
| [SQRT()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/sqrt)                                | This function returns the square root of its argument.                                                           |
| [CBRT()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/cbrt)                                | This function returns the cube root of a given number.                                                           |
| [RANDOM()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/random)                            | This function returns a random number between 0 (inclusive) and 1 (exclusive).                                   |
| [FLOOR()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/floor)                              | This function returns a number rounded down that is less than or equal to the specified argument.                |
| [LN()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/ln)                                    | This function returns the exponential value of its argument.                                                     |
| [SIN()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/sin)                                  | This function returns the trigonometric sine value of a specified angle in radians.                              |
| [**LEAST()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/least)                          | This function returns the least or smallest value in a list of values.                                           |
| [**GREATEST()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/greatest)                    | This function extracts the greatest or largest value from a set of values.                                       |
| [**ROUND()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/round)                          | This function rounds numbers to the nearest integer or to a specified number of decimal places.                  |
| [**EXP()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/exp)                              | This function returns the exponential value of a number specified in the argument.                               |
| [**LOG()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/log)                              | This function returns the base-10 logarithm or logarithm of the specified base of a given number.                |
| [**POWER()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/power)                          | This function returns the value of a number raised to the power of another number specified in the arguments.    |
| [TO\_CHAR() from Number](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/to-char-from-number) | Formats a number into a string using a given format.                                                             |
| [**SIGN()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/sign)                            | This function returns -1 for negative arguments, 1 for positive arguments or 0 if the argument is 0.             |


# POWER



# **Overview**

The `POWER()` function calculates the value of a number raised to the power of another number specified in the arguments.&#x20;

# **Syntax**

The following illustrates the syntax of the `POWER()` function:

```sql
POWER(a,b)
```

Where:

*   `a`: The base number.

*   `b`: The exponent to which the base number is raised.

# **Examples**

Let's explore some examples of the `POWER()` function.

## Case #1: **Basic Usage**

In this case, the `POWER()` function calculates the result of raising one number to the power of another.

```sql
SELECT POWER(3, 4) AS "Example 1",
       POWER(7, 3) AS "Example 2";
```

You will get the output below:

```sql
 Example 1 | Example 2 
-----------+-----------
        81 |       343
```

## Case #2: Using `POWER()` with Negative Values

In this case, the `POWER()` function is applied to negative numbers.

```sql
SELECT POWER(-4, -5), POWER(-1, -2), POWER(-6, -7);
```

You will get the output below:

```sql
 power | power | power 
-------+-------+-------
 -1024 |     1 |     0
```

## Case #3 Using `POWER()` with Floating-Point Numbers

In this example, the `POWER()` function is used to calculate 2.5 raised to the power of 3.0.&#x20;

```sql
SELECT POWER(2.5, 3.0) AS power_result;
```

The result, 15.625, is the value obtained by raising 2.5 to the third power.

```sql
 power_result
--------------
       15.625
```

## Case #4 Zero To the Power of Zero

This case shows that 0 expression raised to the power of 0 returns 1.

```sql
SELECT POWER(0, 0);
```

You will get the output below:

```sql
 power 
-------
     1
```


# RANDOM



## Overview

The `RANDOM()` function in Oxla generates a random number within a defined range. By default, the range is between 0 (inclusive) and 1 (exclusive), resulting in a value greater than or equal to 0 and less than 1.

## Syntax

The syntax for generating a random integer or floating-point number using the `RANDOM()` function is as follows:

```sql
RANDOM()
```

<Note>There are no parameters or arguments for the `RANDOM()` function.</Note>

## Examples

### Case #1: Generating a random number

The RANDOM() function generates a random number greater than or equal to zero but less than one by default. The following statement can be used to retrieve a random number:

```sql
SELECT RANDOM();
```

As a result, you will get a random number greater than 0 and less than 1. However, it will never return the maximum value of 1.

```sql
+-----------------------+
| f                     |
+-----------------------+
| 0.9122627193276355    |
+-----------------------+
```

### Case #2: Generating a random decimal number within a range

To generate a random decimal number between two values, you can use the following statement:

```sql
SELECT RANDOM()*(b-a)+a;
```

Where:

*   **"a"** represents the lower bound of the range.

*   **"b"** represents the upper bound of the range.

The return value will be a random floating-point number greater than or equal to a and less than b.&#x20;

****Example****

To generate a random decimal number greater than or equal to 10 and less than 25, the following statement can be used:

```sql
SELECT RANDOM()*(25 - 10)+10;
```

Below is an example of a random number that you may retrieve:

```sql
+-----------------------+
| f                     |
+-----------------------+
| 18.156098711616043    |
+-----------------------+
```

<Warning>It is important to note that the function will never return the maximum value of b.</Warning>


# ROUND



## **Overview**

The `ROUND()` function rounds numbers using round half to even method (bankers rounding).

## **Syntax**

The following illustrates the syntax of the `ROUND()` function:

```sql
ROUND(number);
```

Where:

*   `number`: The number to round, it can be positive, negative, or zero, and it can be an [Integer](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-9-numeric-types/numeric-type) or a [Double Precision](https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/3-3-9-numeric-types/numeric-type#double-precision-type).

## **Examples**

Let's explore some examples to see how the `ROUND()` function works.

### Case #1: **Basic Usage**

In this example, we round decimal numbers to integers:

```sql
SELECT
    round(28.11) AS "round(28.11)",
    round(12.51) AS "round(12.51)",
    round(-9.11) AS "round(-9.11)",
    round(102.5) AS "round(102.5)",
    round(101.5) AS "round(101.5)",
    round(-40.51) AS "round(-40.51)";
```

The query will return the nearest integer for all provided values.

```sql
 round(28.11) | round(12.51) | round(-9.11) | round(102.5) | round(101.5) | round(-40.51) 
--------------+--------------+--------------+--------------+---------------+---------------
           28 |           13 |           -9 |          102 |          102 |           -41
```

### Case #2: Using `ROUND` with Table

Suppose you have a table named **Product** that stores product prices with multiple decimal places. You want to round the prices.&#x20;

```sql
CREATE TABLE Product (
    ProductID INT,
    ProductName TEXT,
    Price DOUBLE PRECISION
);

INSERT INTO Product (ProductID, ProductName, Price)
VALUES
    (1, 'Widget A', 12.345),
    (2, 'Widget B', 34.678),
    (3, 'Widget C', 9.99),
    (4, 'Widget D', 45.00),
    (5, 'Widget E', 7.12345),
    (6, 'Widget F', 19.876), 
    (7, 'Widget G', 3.5),
    (8, 'Widget H', 29.999);
```

We use the `ROUND()` function to round the Price column when retrieving the data.&#x20;

```sql
SELECT ProductName, ROUND(Price) AS RoundedPrice FROM Product;
```

The result will display the product names along with their prices rounded.

```sql
 productname | roundedprice 
-------------+--------------
 Widget A    |           12
 Widget B    |           35
 Widget C    |           10
 Widget D    |           45
 Widget E    |            7
 Widget F    |           20
 Widget G    |            4
 Widget H    |           30
```


# SIGN



## Overview

The `SIGN()` function returns a sign of an argument. The returned values are -1 if the argument is less than zero, 1 if the argument is greater than zero, 0 if the argument is equal to zero.

## Syntax

The syntax for the `SIGN() `function is as follows:

```sql
SIGN(x)
```

The `SIGN()` function requires one argument:

*   `x`: an expression that evaluates to a number.

## Examples

### Case #1: Sign of a number

The following example demonstrates how the `SIGN()` function can be used to obtain the sign of a number:

```sql
SELECT
    SIGN(0.1) AS "SIGN(0.1)",
    SIGN(999) AS "SIGN(999)",
    SIGN(0) AS "SIGN(0)",
    SIGN(-0) AS "SIGN(-0)";
```

The query will return the signs of the passed arguments:

```sql
 SIGN(0.1) | SIGN(999) | SIGN(0) | SIGN(-0)
-----------+-----------+---------+----------
         1 |         1 |       0 |        0

```

Note: `-0` is accepted as an argument and is equal to zero

### Case #2: SIGN() function with an expression

The following example demonstrates how the `SIGN()` function can be used with an expression:

```sql
SELECT SIGN(100 - 200);
```

will return the sign of the expression evaluation:

```sql
 sign
------
   -1
------
```

### Case #3: Using the SIGN() function with a table

The following example demonstrates how the `SIGN()` function can be used with a table to obtain the absolute values of all numbers in a specific column:

1.  Create a table signTable containing an ***value*** column with some positive, negative and equal to zero values:

```sql
CREATE TABLE signTable(value float);

INSERT INTO signTable(value)
VALUES 
(1000),
(-200),
(0),
(0.22),
(-12.3),
(-0.0);
```

2.  Use the following query to find the sign of all inserted values:

```sql
SELECT value, SIGN(value) AS sign
FROM signTable;
```

3.  The result will be as follows::

```sql
 value | sign
-------+------
  1000 |    1
  -200 |   -1
     0 |    0
  0.22 |    1
 -12.3 |   -1
    -0 |    0
```


# SIN



## **Overview**

`SIN()` is a numeric function that returns the trigonometric sine value of a specified angle in radians.

## **Syntax**

The syntax of the `SIN()` function is as follows.

```sql
SIN (x)
```

The `SIN()` function requires one argument:

`x`:  A positive or a negative angle (or an expression that evaluates to an angle).

## **Examples**

### Case #1: Sine a Positive Value

The example below will use the `SIN()` function with a positive angle as the argument.

```sql
SELECT SIN(5);
```

It will return the sine value of 5.

```sql
+-----------------------+
| f                     |
+-----------------------+
| -0.9589242746631385   |
+-----------------------+
```

### Case #2: Sine a Negative Value

The following example shows the `SIN(`) function with a negative angle as the argument.

```sql
SELECT SIN(-3);
```

The output will be as follows.

```sql
+----------------------+
| f                    |
+----------------------+
| -0.1411200080598672  |
+----------------------+
```

### Case #3: Sine a Fraction Value

The following example shows the `SIN()` function with a fractional value as the argument.

```sql
SELECT SIN(5.8732);
```

The output will be as follows.

```sql
+----------------------+
| f                    |
+----------------------+
| -0.3985959081271079  |
+----------------------+
```

### Case #4: Sine With an Expression

The `SIN()` function can also include an expression, as shown in the example below:

```sql
SELECT sin(8.5 * 2.3);
```

You will get the following output:

```sql
+-----------------------+
| f                     |
+-----------------------+
| 0.6445566903363104    |
+-----------------------+
```

### Case #5: Using the `SIN()` Function With a Table

In the following example, we will combine `SIN()` function with `CREATE TABLE` statement to obtain the sine values of a specific column.

1.  Create a new table named **sineTable** containing the **initialValue** column. Input some values with the negative and positive angles into the column.

```sql
CREATE TABLE sineTable(initialValue int);
INSERT INTO sineTable(initialValue)
VALUES (-5),(18), (0),(-27);
```

2.  Run the query below to get the output of a sine value:

```sql
SELECT * ,SIN(initialValue) AS sinValue FROM sineTable;
```

3.  The final result will have the **initialValue** column with the source value and the **sinValue** column with their calculated sine values.  

```sql
+---------------+-------------------------------+
| initialvalue  | sinValue                      |
+---------------+-------------------------------+
| -75           | 0.38778163540943045           |
| 180           | -0.8011526357338304           |
| 0             | 0                             | 
| -270          | 0.1760459464712114            |
+---------------+-------------------------------+
```


# SQRT



## Overview

The `SQRT()` function returns the square root of a given positive number.

## Syntax

The syntax for the `SQRT()` function in Oxla is:

```sql
SQRT(x)
```

The `SQRT()` function requires one argument:

*   `x`: A positive number or an expression that evaluates to a positive number.

## Examples

### Case #1: SQRT() a Positive Value

The following example demonstrates how the `SQRT()` function can be used to find the square root of a positive integer:

```sql
SELECT SQRT(81);
```

You will get the following result:

```sql
+-----+
| f   |
+-----+
| 9   |
+-----+
```

### Case #2: SQRT() With an Expression

Let’s look at an example of using the `SQRT()` function to find the square root of the result of an expression.

```sql
SELECT SQRT(60 + 4);
```

The result of the above statement is the square root of 64:

```sql
+-----+
| f   |
+-----+
| 8   |
+-----+
```

### Case #3: SQRT() With Double Precision Result

In addition to integers, Oxla also supports calculating square roots with floating-point numbers as the outcome. For further details, please refer to the statement below:

```sql
SELECT SQRT(70);
```

The output of the statement above is 8.3666, which is the square root of 70 with double precision, as demonstrated below:

```sql
+----------+
| f        |
+----------+
| 8.3666   |
+----------+
```

### Case #4: SQRT() a Negative Number

The following example demonstrates how attempting to use the `SQRT()` function with a negative value will return an error:

```sql
SELECT SQRT(-25);
```

As the `SQRT()` function only accepts positive numbers, you will get a ***NaN (Not a Number)*** result for the square root of -25, as shown below:

```sql
+-------+
| f     |
+-------+
| NaN   |
+-------+
```

### Case #5: SQRT Operator (`|/(x)`)

Here's an example using the SQRT operator (`|/(x)`) to calculate the square root of a given number:

```sql
SELECT |/(169) AS sqrt_operator;
```

In this example, we calculate the square root of 169 using the SQRT operator. The result of this query will be:

```sql
 sqrt_operator 
---------------
            13
```


# TO_CHAR from Number



## **Overview**

The `TO_CHAR` function formats a number into a string using a given format.

## **Syntax**

The syntax for using the `TO_CHAR` function is as follows:

```sql
TO_CHAR(value, format_string)
```

Parameters in the syntax include:

*   `value`: A number that will be formatted to a string.

*   `format`: The format of the input string.

## **Format**&#x20;

Format string supports following template patterns (can be lowercase):

| **Pattern** | **Description**                                            |
| ----------- | ---------------------------------------------------------- |
| `9 `        | Digit position (may be dropped if insignificant)           |
| `0`         | Digit position (never dropped)                             |
| `.`         | Decimal point                                              |
| `,`         | Group (thousands) separator                                |
| `D`         | Decimal point                                              |
| `G`         | Group separator                                            |
| `S`         | Plus/minus sign directly before or after a number          |
| `PL`        | Plus sign in the specified position (for negative numbers) |
| `MI`        | Minus sign in specified position (for positive numbers)    |
| `SG`        | Plus/minus sign in the specified position.                 |

### ❌ Limitations

*   All text inside double quote `"{text}"` will not be considered a pattern.

*   The quote character `""` will not appear in the result string.

*   Any text that does not match any pattern will be preserved in the result string.

## **Examples**

### Case 1: **Formatting with Leading Zeros**

The query formats 123.456 with leading zeros using the pattern '00000.00000'.

```sql
SELECT TO_CHAR(123.456, '00000.00000');
```

The output displays the formatted number as shown below.

```sql
   to_char    
--------------
  00123.45600
```

### Case 2: **Formatting with Variable Length**

The query formats the number 123.456 with a variable-length pattern '99999.99999'.

```sql
SELECT TO_CHAR(123.456, '99999.99999');
```

The output displays the formatted number as shown below.

```sql
   to_char    
--------------
    123.45600
```

### Case 3: **Formatting with Group**

The query formats the number 123456 with grouping separators using the pattern '9,999,999,999'.

```sql
SELECT TO_CHAR(123456, '9,999,999,999');
```

It will return the output below.

```sql
    to_char     
----------------
        123,456
```

### Case 4: **Formatting with Negative Number**

The query formats the number -123 with a custom pattern including the sign.

```sql
SELECT TO_CHAR(-123, '"Number formatted with pattern:000S":{000S}');
```

The output shows the custom-formatted number.

```sql
                  to_char                  
-------------------------------------------
 Number formatted with pattern:000S:{123-}
```

### Case 5: **Formatting with Sign**

The query formats the number -123.456 with a custom pattern including the sign and separated integer.

```sql
SELECT TO_CHAR(-123.456, '"Sing is: "SG" integer part is: "999", mantissa part is: ".999');
```

The output shows the customized format as shown below.

```sql
                         to_char                         
---------------------------------------------------------
 Sing is: - integer part is: 123, mantissa part is: .456
```


# Overview



Aggregate functions compute a single result from a set of input values. Oxla supports the following functions:

| **Functions**                                                                                             | **Description**                                                                                                                 |
| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| [SUM](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/sum)            | Calculates and returns the sum of all values.                                                                                   |
| [MIN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/min)            | Calculates and returns the minimum value.                                                                                       |
| [FOR\_MIN](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/for-min)   | Calculates and returns a value corresponding to the minimal metric in the same row from a set of values.                        |
| [MAX](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/max)            | Calculates and returns the maximum value.                                                                                       |
| [FOR\_MAX](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/for-max)   | Calculates and Returns a value corresponding to the maximum metric in the same row from a set of values.                        |
| [AVG](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/avg)            | Calculates and returns the average value.                                                                                       |
| [COUNT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/count)        | Counts the number of rows.                                                                                                      |
| [BOOL\_AND](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/bool-and) | Calculates the boolean of all the boolean values in the aggregated group. `FALSE` if at least one of aggregated rows is `FALSE` |
| [BOOL\_OR](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/bool-or)   | Calculates the boolean of all the boolean values in the aggregated group. `TRUE` if at least one of aggregated rows is `TRUE`.  |

| **Function qualifiers**                                                                                  | **Description**                                                                      |
| -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| [DISTINCT](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/distinct) | Allows aggregation functions to operate on a distinct set of values within a column. |

<Check>You can utilize the aggregate functions with the `GROUP BY` and `HAVING` clauses in the `SELECT` statement. </Check>


# AVG



## Overview

The `AVG()` function lets you calculate the average value of records.

The input and return types we support can be seen in the table below.

![avg types](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/avg.png)

<Info>If the input type is 32-bit, then the result will be 64-bit.</Info>

💡**Special cases:** Returns NaN if the input contains a NaN.

## Examples

In this example, we will use an **orders** table that stores details of the purchase transactions:

```sql
CREATE TABLE orders (
    orderid int,
    custname text,
    orderproduct text,
    ordertotal real
);
INSERT INTO orders (orderid, custname, orderproduct, ordertotal)
VALUES
(9557411, 'Maya', 'Jeans', 10.5),
(9557421, 'Aaron', 'T-Shirt', 9.2),
(9557451, 'Alex', 'Hat', 10.8),
(9557311, 'Will', 'Hat', 8.5),
(9557321, 'Will', 'T-Shirt', 12.15),
(9557351, 'Maya', 'T-Shirt', 9.5),
(9557221, 'Maya', 'Jeans', 11.02),
(9557251, 'Alex', 'Jeans', 11.09),
(9557231, 'Aaron', 'Hat', 14.56),
(9557281, 'Aaron', 'Hat', 12.15),
(9557291, 'Will', 'T-Shirt', 13.1);
```

```sql
SELECT * FROM orders;
```

The above query will show the following table:

```sql
+----------+-----------+---------------+-------------+
| orderid  | custname  | orderproduct  | ordertotal  |
+----------+-----------+---------------+-------------+
| 9557411  | Maya      | Jeans         | 10.5        |
| 9557421  | Aaron     | T-Shirt       | 9.2         |
| 9557451  | Alex      | Hat           | 10.8        |
| 9557311  | Will      | Hat           | 8.5         |
| 9557321  | Will      | T-Shirt       | 12.15       |
| 9557351  | Maya      | T-Shirt       | 9.5         |
| 9557221  | Maya      | Jeans         | 11.02       |
| 9557251  | Alex      | Jeans         | 11.09       |
| 9557231  | Aaron     | Hat           | 14.56       |
| 9557281  | Aaron     | Hat           | 12.15       |
| 9557291  | Will      | T-Shirt       | 13.1        |
+----------+-----------+---------------+-------------+
```

### #Case 1: `AVG()` with a single expression

In the first example, we want to calculate the average amount of all orders that customers have paid:

```sql
SELECT AVG(ordertotal) AS "Order Total Average"
FROM orders;
```

It will return the following output:

```sql
+---------------------+
| Order Total Average |
+---------------------+
| 11.142727331681685  |
+---------------------+
```

### #Case 2: `AVG()` with a `GROUP BY` clause

The following example uses the `AVG()` function and `GROUP BY` clause to calculate the average amount paid by each customer:

*   First, the `GROUP BY` clause divides orders into groups based on customers

*   Then, the `AVG` function is applied to each group.

```sql
SELECT custname AS "Customer", AVG (ordertotal) AS "Total Price Average"
FROM orders
GROUP BY custname;
```

It will display the output as shown below:

```sql
+-----------+----------------------+
| Customer  | Total Price Average  |
+-----------+----------------------+
| Aaron     | 11.96999994913737    |
| Alex      | 10.945000171661377   |
| Will      | 11.25                |
| Maya      | 10.34000015258789    |
+-----------+----------------------+
```

***

💡 You can use the cast operator like`::NUMERIC(10,2)` to add two decimal numbers after the comma:

```sql
SELECT custname AS "Customer", AVG (ordertotal)::NUMERIC(10,2) AS "Total Price Average"
FROM orders
GROUP BY custname;
```

The result will trim and round two numbers after the comma:

```sql
+-----------+----------------------+
| Customer  | Total Price Average  |
+-----------+----------------------+
| Aaron     | 11.97                |
| Alex      | 10.95                |
| Will      | 11.25                |
| Maya      | 10.34                |
+-----------+----------------------+
```


# BOOL_AND



## Overview

The `BOOL_AND()` function calculates all the boolean values in the aggregated group, which will have these results:

*   `true` if all the values are `true` for every row.

*   `false` if at least one row in the group is `false`.

The input and the return type must be in `BOOL`.

<Info>`NULL` values are not aggregated, so it will return `NULL` if there are zero input rows.</Info>

## Examples

In this example, we will use a payment table that stores details of the orders, whether the order has been paid or unpaid by the customer:

```sql
CREATE TABLE payment (
    orderid int,
    custname text,
    orderproduct text,
    ordertotal real,
    paid boolean
);
INSERT INTO payment (orderid, custname, orderproduct, ordertotal, paid)
VALUES 
(9557411, 'Maya', 'Jeans', 10.5, true),
(9557421, 'Aaron', 'T-Shirt', 9.2, true),
(9557451, 'Alex', 'Hat', 10.8, true),
(9557311, 'Will', 'Hat', 8.5, true),
(9557321, 'Will', 'T-Shirt', 12.15, true),
(9557351, 'Maya', 'T-Shirt', 9.5, true),
(9557221, 'Maya', 'Jeans', 11.02, true),
(9557251, 'Alex', 'Jeans', 11.09, true),
(9557231, 'Aaron', 'Hat', 14.56, false),
(9557281, 'Aaron', 'Hat', 12.15, true),
(9557291, 'Will', 'T-Shirt', 13.1, true);
```

```sql
SELECT * FROM payment;
```

The above query will show the following table:

```sql
+----------+-----------+---------------+-------------+-------+
| orderid  | custname  | orderproduct  | ordertotal  | paid  |
+----------+-----------+---------------+-------------+-------+
| 9557411  | Maya      | Jeans         | 10.5        | t     |
| 9557421  | Aaron     | T-Shirt       | 9.2         | t     |
| 9557451  | Alex      | Hat           | 10.8        | t     |
| 9557311  | Will      | Hat           | 8.5         | t     |
| 9557321  | Will      | T-Shirt       | 12.15       | t     |
| 9557351  | Maya      | T-Shirt       | 9.5         | t     |
| 9557221  | Maya      | Jeans         | 11.02       | t     |
| 9557251  | Alex      | Jeans         | 11.09       | t     |
| 9557231  | Aaron     | Hat           | 14.56       | f     |
| 9557281  | Aaron     | Hat           | 12.15       | t     |
| 9557291  | Will      | T-Shirt       | 13.1        | t     |
+----------+-----------+---------------+-------------+-------+
```

### #Case 1: `BOOL_AND` with a false result

We will find out if all customers have paid for their orders using the query below:

```sql
SELECT BOOL_AND(paid) AS "final_result" FROM payment;
```

In the `BOOL_AND` function, if there is at least one `FALSE` value, the overall result will be `FALSE`. The final output shows that there is an order that hasn’t been paid.

```sql
+--------------+
| final_result |
+--------------+
| f            |
+--------------+
```

### #Case 2: `BOOL_AND` with a true result

We will find out if Maya has paid for her orders using the query below:

```sql
SELECT BOOL_AND(paid) AS Maya_Paid
FROM payment
WHERE custname ='Maya';
```

In the `BOOL_AND` function, if all values are `TRUE`, then the overall result will be `TRUE`. The final output shows that Maya has paid all her orders.

```sql
+------------+
| maya_paid  |
+------------+
| t          |
+------------+
```


# BOOL_OR



## Overview

The `BOOL_OR()` function calculates all the boolean values in the aggregated group, which will have these results:

*   `false` if all the values are `false` for every row.

*   `true` if at least one row in the group is true.

The input and the return type must be in `BOOL`.

<Info>`NULL` values are not aggregated, so it will return `NULL` if there are zero input rows.</Info>

## Examples

In this example, we will use a payment\*\* \*\*table that stores details of the orders, whether the order has been paid or unpaid by the customer:

```sql
CREATE TABLE payment (
    orderid int,
    custname text,
    orderproduct text,
    ordertotal real,
    paid boolean
);
INSERT INTO payment (orderid, custname, orderproduct, ordertotal, paid)
VALUES 
(9557411, 'Maya', 'Jeans', 10.5, false),
(9557421, 'Aaron', 'T-Shirt', 9.2, false),
(9557451, 'Alex', 'Hat', 10.8, false),
(9557311, 'Will', 'Hat', 8.5, true),
(9557321, 'Will', 'T-Shirt', 12.15, false),
(9557351, 'Maya', 'T-Shirt', 9.5, true),
(9557221, 'Maya', 'Jeans', 11.02, false),
(9557251, 'Alex', 'Jeans', 11.09, false),
(9557231, 'Aaron', 'Hat', 14.56, false),
(9557281, 'Aaron', 'Hat', 12.15, false),
(9557291, 'Will', 'T-Shirt', 13.1, false);
```

```sql
SELECT * FROM payment;
```

The above query will show the following table:

```sql
+----------+-----------+---------------+-------------+--------+
| orderid  | custname  | orderproduct  | ordertotal  | paid   |
+----------+-----------+---------------+-------------+--------+
| 9557411  | Maya      | Jeans         | 10.5        | f      |
| 9557421  | Aaron     | T-Shirt       | 9.2         | f      |
| 9557451  | Alex      | Hat           | 10.8        | f      |
| 9557311  | Will      | Hat           | 8.5         | t      |
| 9557321  | Will      | T-Shirt       | 12.15       | f      |
| 9557351  | Maya      | T-Shirt       | 9.5         | t      |
| 9557221  | Maya      | Jeans         | 11.02       | f      |
| 9557251  | Alex      | Jeans         | 11.09       | f      |
| 9557231  | Aaron     | Hat           | 14.56       | f      |
| 9557281  | Aaron     | Hat           | 12.15       | f      |
| 9557291  | Will      | T-Shirt       | 13.1        | f      |
+----------+-----------+---------------+-------------+--------+
```

### #Case 1: `BOOL_OR` with a true result

We will find out if all customers have paid for their orders using the query below:

```sql
SELECT BOOL_OR(paid) AS "final_result" FROM payment;
```

If there is at least one `TRUE` value, the overall result will be `TRUE`. The final output shows that some order has been paid regardless of the other unpaid orders.

```sql
+--------------+
| final_result |
+--------------+
| t            |
+--------------+
```

### #Case 2: `BOOL_OR` with a false result

We will find out if Aaron has paid for his orders using the query below:

```sql
SELECT BOOL_OR(paid) AS aaron_paid
FROM payment
WHERE custname ='Aaron';
```

If all values are `FALSE`, then the overall result will be `FALSE`. The final output shows that Aaron hasn’t paid for all his orders.

```sql
+-------------+
| aaron_paid  |
+-------------+
| f           |
+-------------+
```


# COUNT



## Overview

The `COUNT()` function allows you to get the number of records that match a specific condition.

The input and return types we support can be seen in the table below.

![count types](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/count.png)

<Info>The output will return the number of rows in a table regardless of the input types.</Info>

## Examples

In this example, we will use an orders table that stores details of the purchase transactions:

```sql
CREATE TABLE orders (
    orderid int,
    custname text,
    orderproduct text,
    ordertotal real
);
INSERT INTO orders (orderid, custname, orderproduct, ordertotal)
VALUES
(9557411, 'Maya', 'Jeans', 10.5),
(9557421, 'Aaron', 'T-Shirt', 9.2),
(9557451, 'Alex', 'Hat', 10.8),
(9557311, 'Will', 'Hat', 8.5),
(9557321, 'Will', 'T-Shirt', 12.15),
(9557351, 'Maya', 'T-Shirt', 9.5),
(9557221, 'Maya', 'Jeans', 11.02),
(9557251, 'Alex', 'Jeans', 11.09),
(9557231, 'Aaron', 'Hat', 14.56),
(9557281, 'Aaron', 'Hat', 12.15),
(9557291, 'Will', 'T-Shirt', 13.1);
```

```sql
SELECT * FROM orders;
```

The above query will show the following table:

```sql
+----------+-----------+---------------+-------------+
| orderid  | custname  | orderproduct  | ordertotal  |
+----------+-----------+---------------+-------------+
| 9557411  | Maya      | Jeans         | 10.5        |
| 9557421  | Aaron     | T-Shirt       | 9.2         |
| 9557451  | Alex      | Hat           | 10.8        |
| 9557311  | Will      | Hat           | 8.5         |
| 9557321  | Will      | T-Shirt       | 12.15       |
| 9557351  | Maya      | T-Shirt       | 9.5         |
| 9557221  | Maya      | Jeans         | 11.02       |
| 9557251  | Alex      | Jeans         | 11.09       |
| 9557231  | Aaron     | Hat           | 14.56       |
| 9557281  | Aaron     | Hat           | 12.15       |
| 9557291  | Will      | T-Shirt       | 13.1        |
+----------+-----------+---------------+-------------+
```

### #Case 1: `COUNT()` with a single expression

The following example will return the number of all orders in the orders table:

```sql
SELECT COUNT(*) FROM orders;
```

The final result will be as follows:

```sql
+-------+
| count |
+-------+
| 11    |
+-------+
```

### #Case 2: `COUNT()` with a `GROUP BY` clause

This example will combine the `COUNT()` function and the `GROUP BY` clause.

*   The `GROUP BY` clause groups the orders based on the customer’s name.

*   The `COUNT()` function counts the orders for each customer.

```sql
SELECT custname, COUNT (orderid)
FROM orders
GROUP BY custname;
```

It will display the output as shown below:

```sql
+-----------+--------+
| custname  | count  |
+-----------+--------+
| Aaron     | 3      |
| Alex      | 2      |
| Will      | 3      |
| Maya      | 3      |
+-----------+--------+
```

### #Case 3: `COUNT()` with a `HAVING` clause

In this example, we combine the `COUNT()` function and the `HAVING` clause to apply a specific condition to find customers who have made more than two orders:

```sql
SELECT custname, COUNT (orderid)
FROM orders
GROUP BY custname
HAVING COUNT (orderid) > 2;
```

*   The `GROUP BY` clause groups the orders based on the customer’s name.

*   The `HAVING` clause will filter only customers with more than two order IDs.

*   The `COUNT()` function counts the orders for each customer.

```sql
+-----------+--------+
| custname  | count  |
+-----------+--------+
| Aaron     | 3      |
| Will      | 3      |
| Maya      | 3      |
+-----------+--------+
```


# DISTINCT qualifier



## Overview

When using aggregation functions, they can contain the `DISTINCT` keyword. It acts as a qualifier for them, to ensure that only unique values are being processed. Here's how a sample syntax looks like:

```sql
aggregation function (DISTINCT expression [clause] ...) ...
```

`DISTINCT` keyword can be combined with the following aggregate functions:

*   `AVG()`
*   `COUNT()`
*   `MAX()`
*   `MIN()`
*   `SUM()`

All functions listed above, operate on the same input and return types, that are supported by their counterparts without any qualifiers. They can be grouped without any limitations, provided that they utilise a **single** `DISTINCT` keyword.

<Warning>Any type of **multiple** `DISTINCT` qualifiers used in a query with `GROUP BY` statements are **not supported** at the moment, however if the query doesn't include such statements, it will get executed but the output's column order will be reversed at the moment</Warning>

## Examples

In this section we'll focus on a few examples, that showcase sample usage of the above mentioned concepts. They will be based on creation of the following tables:

```sql
CREATE TABLE customer (
  customer_id int,
  cust_name string
);
INSERT INTO customer
    (customer_id, cust_name)
VALUES
    (11112, 'Alex'),
    (11113, 'Aaron'),
    (11114, 'Alice'),
    (11115, 'Nina'),
    (11116, 'Rosy'),
    (11117, 'Martha'),
    (11118, 'John');

CREATE TABLE rental (
    rental_id int,
    rental_date timestamp,
    return_date timestamp,
    car string,
    customer_id int,
    total_price int
);
INSERT INTO rental (rental_id, rental_date, return_date, car, customer_id, total_price)
VALUES
(8557411, '2022-04-02 09:10:19', '2022-04-10 10:15:05', 'Audi', 11112, 1400),
(8557421, '2022-04-06 07:00:30', '2022-04-19 07:10:19', 'BMW', 11115, 2000),
(8557451, '2022-04-19 08:00:20', '2022-04-24 08:05:00', 'Cadillac', 11112, 1000),
(8557311, '2022-05-11 09:15:28', '2022-05-18 09:00:18', 'Audi', 11115, 1500),
(8557321, '2022-05-20 10:12:22', '2022-05-28 10:08:48', 'Audi', 11113, 1500),
(8557351, '2022-06-10 12:18:09', '2022-06-20 18:12:23', 'Cadillac', 11114, 1200),
(8557221, '2022-06-17 14:02:02', '2022-06-20 14:17:02', 'Chevrolet', 11112, 1300),
(8557251, '2022-07-12 05:19:49', '2022-07-19 07:15:28', 'Chevrolet', 11116, 1400),
(8557231, '2022-08-09 09:29:08', '2022-08-24 09:30:58', 'Cadillac', 11114, 2000),
(8557291, '2022-08-18 15:15:20', '2022-09-01 15:30:19', 'BMW', 11117, 3000);
```

Here's how the created tables will look like, respectively:

```sql
SELECT * FROM customer;

+-------------+-----------+
| customer_id | cust_name |
+-------------+-----------+
| 11112       | Alex      |
| 11113       | Aaron     |
| 11114       | Alice     |
| 11115       | Nina      |
| 11116       | Rosy      |
| 11117       | Martha    |
| 11118       | John      |
+-------------+-----------+

SELECT * FROM rental;

+------------+---------------------+---------------------+-----------+---------------+-------------+
| rental_id  | rental_date         | return_date         | car       | customer_id   | total_price |
+------------+---------------------+---------------------+-----------+---------------+-------------+
| 8557411    | 2022-04-02 09:10:19 | 2022-04-10 10:15:05 | Audi      | 11112         | 1400        |
| 8557421    | 2022-04-06 07:00:30 | 2022-04-19 07:10:19 | BMW       | 11115         | 2000        |
| 8557451    | 2022-04-19 08:00:20 | 2022-04-24 08:05:00 | Cadillac  | 11112         | 1000        |
| 8557311    | 2022-05-11 09:15:28 | 2022-05-18 09:00:18 | Audi      | 11115         | 1500        |
| 8557321    | 2022-05-20 10:12:22 | 2022-05-28 10:08:48 | Audi      | 11113         | 1500        |
| 8557351    | 2022-06-10 12:18:09 | 2022-06-20 18:12:23 | Cadillac  | 11114         | 1200        |
| 8557221    | 2022-06-17 14:02:02 | 2022-06-20 14:17:02 | Chevrolet | 11112         | 1300        |
| 8557251    | 2022-07-12 05:19:49 | 2022-07-19 07:15:28 | Chevrolet | 11116         | 1400        |
| 8557231    | 2022-08-09 09:29:08 | 2022-08-24 09:30:58 | Cadillac  | 11114         | 2000        |
| 8557291    | 2022-08-18 15:15:20 | 2022-09-01 15:30:19 | BMW       | 11117         | 3000        |
+------------+---------------------+---------------------+-----------+---------------+-------------+
```

### `DISTINCT` combined with `COUNT` function

The following example uses `DISTINCT` qualifier combined with `COUNT()` function to calculate the number of unique car brands in rentals:

```sql
SELECT COUNT (DISTINCT car) AS number_of_car_brands
FROM rental;
```

When executing the above code, it will return the following output:

```sql
+----------------------+
| number_of_car_brands |
+----------------------+
| 4                    |
+----------------------+
```

Here's another example, that uses `DISTINCT` qualifier combined with `COUNT()` function to calculate the amount of rentals by each customer:

```sql
SELECT c.cust_name AS customer_name, COUNT (DISTINCT r.rental_id) AS rental_count
FROM rental r
JOIN customer c ON r.customer_id = c.customer_id
GROUP BY c.cust_name;
```

It will calculate the `rental_count` by each `customer_name` as shown below:

```sql
+----------------+--------------+
| customer_name  | rental_couunt|
+----------------+--------------+
| Nina           | 2            |
| Aaron          | 1            |
| Alice          | 2            |
| Martha         | 1            |
| Alex           | 3            |
| Rosy           | 1            |
+----------------+--------------+
```

### `DISTINCT` combined with `MAX()` function

The following example uses `DISTINCT` qualifier combined with `MAX()` function to find maximum single spending per each customer, dropping any repeated transactions:

```sql
SELECT c.cust_name AS customer_name,
       MAX (DISTINCT r.total_price) AS max_spending
FROM rental r
JOIN customer c ON r.customer_id = c.customer_id
GROUP BY c.cust_name;
```

The output for that code will be as follows:

```sql
+---------------+--------------+
| customer_name | max_spending |
+---------------+--------------+
| Martha        | 3000         |
| Rosy          | 1400         |
| Alex          | 1400         |
| Alice         | 2000         |
| Nina          | 2000         |
| Aaron         | 1500         |
+---------------+--------------+
```

### `DISTINCT` combined with `SUM()` function

The following example compares the sum of unique revenues versus the sum of all revenues in rental data:

```sql
SELECT
    SUM (DISTINCT r.total_price) AS unique_revenue,
    SUM (r.total_price) AS total_revenue
FROM rental r;
```

Here's the ouput of the above query:

```sql
+----------------+---------------+
| unique_revenue | total_revenue |
+----------------+---------------+
| 11400          | 16300         |
+----------------+---------------+
```

The result may help to understand what is the impact of repeating transactions on total revenue.

## Limitations

There are few use-cases that we are aware of but do not support currently:

*   Aggregation functions with `DISTINCT` keyword used as an argument of an expression, e.g.

```sql
SELECT 1 + COUNT(DISTINCT col) FROM table
```

*   Any type of **multiple** `DISTINCT` qualifiers used in a query with `GROUP BY` statements


# FOR_MAX



## Overview

`FOR_MAX()` function takes two arguments: metric and value. Returns a value corresponding to the maximum metric in the same row from a set of values.

The value argument can be one of the following types:

*   `INT`

*   `LONG`

*   `FLOAT`

*   `DOUBLE`

*   `DATE`&#x20;

*   `TIMESTAMP`&#x20;

The value argument can be of any type except `STRING`.

💡**Special cases:**

*   Returns `NULL` if:
    *   there are no input rows&#x20;

    *   the metric column has only `NULL` values

    *   the value corresponding to the maximum metric is `NULL`.

*   Returns `NaN` if the input contains a `NaN`.

## Examples

We have a payments table that stores the records of payments by customers, along with discounts applied during the payment:

```sql
CREATE TABLE payments (
    paymentid int,
    customer_name string,
    price real,
    discount real
);
INSERT INTO payments (paymentid, customer_name, price, discount)
VALUES 
(1, 'Alex', 280.12, 0.1),
(2, NULL, 35.75, NULL),
(3, 'Alex', 45.1, 0.05),
(4, 'Alex', NULL, 0.4),
(5, 'John', NULL, 0.1),
(6, 'Bob', 50.45, 0.07),
(7, 'Bob', 120.5, 0.0);
```

```sql
SELECT * FROM payments;
```

It will create a table as shown below:

```sql
+-----------+---------------+--------+----------+
| paymentid | customer_name | price  | discount |
+-----------+---------------+--------+----------+
|         2 |               |  35.75 |          |
|         4 | Alex          |        |      0.4 |
|         3 | Alex          |   45.1 |     0.05 |
|         1 | Alex          | 280.12 |      0.1 |
|         6 | Bob           |  50.45 |     0.07 |
|         5 | John          |        |      0.1 |
|         7 | Bob           |  120.5 |        0 |
+-----------+---------------+--------+----------+
```

### #Case 1: `FOR_MAX()` on the whole table

For example, let's check the price for the highest discount applied to it:

```sql
SELECT FOR_MAX(discount, price) AS for_lowest_discount
FROM payments;
```

It will return the following output (`NULL` in this case):

```sql
+---------------------+
| for_lowest_discount |
+---------------------+
|                     |
+---------------------+
```

### #Case 2: `FOR_MAX()` with `GROUP BY` clause

For this example, we use a `GROUP BY` clause to group the customers, then use `FOR_MAX()` to get a discount for the highest price paid by each customer.

```sql
SELECT customer_name, FOR_MAX(price, discount) AS discount
FROM payments
GROUP BY customer_name;
```

Which will give the following result:

```sql
+---------------+----------+
| customer_name | discount |
+---------------+----------+
|               |          |
| Bob           |        0 |
| Alex          |      0.1 |
| John          |          |
+---------------+----------+
```


# FOR_MIN



## Overview

`FOR_MIN()` function takes two arguments: metric and value. Returns a value corresponding to the minimal metric in the same row from a set of values.

The metric argument can be one of the following types:

*   `INT`

*   `LONG`

*   `FLOAT`

*   `DOUBLE`

*   `DATE`&#x20;

*   `TIMESTAMP`&#x20;

The value argument can be of any type except `STRING`.

💡**Special cases:**

*   Returns `NULL` if:
    *   there are no input rows&#x20;

    *   the metric column has only `NULL` values

    *   the value corresponding to the minimum metric is `NULL`.

*   Returns `NaN` if the input contains a `NaN`.

## Examples

We have a payments table that stores the records of payments by customers, along with discounts applied during the payment:

```sql
CREATE TABLE payments (
    paymentid int,
    customer_name string,
    price real,
    discount real
);
INSERT INTO payments (paymentid, customer_name, price, discount)
VALUES 
(1, 'Alex', 280.12, 0.1),
(2, NULL, 35.75, NULL),
(3, 'Alex', 45.1, 0.05),
(4, 'Alex', NULL, 0.4),
(5, 'John', NULL, 0.1),
(6, 'Bob', 50.45, 0.07),
(7, 'Bob', 120.5, 0.0);
```

```sql
SELECT * FROM payments;
```

It will create a table as shown below:

```sql
+-----------+---------------+--------+----------+
| paymentid | customer_name | price  | discount |
+-----------+---------------+--------+----------+
|         2 |               |  35.75 |          |
|         4 | Alex          |        |      0.4 |
|         3 | Alex          |   45.1 |     0.05 |
|         1 | Alex          | 280.12 |      0.1 |
|         6 | Bob           |  50.45 |     0.07 |
|         5 | John          |        |      0.1 |
|         7 | Bob           |  120.5 |        0 |
+-----------+---------------+--------+----------+
```

### #Case 1: `FOR_MIN()` on the whole table

For example, let's check the price for the lowest discount applied to it:

```sql
SELECT FOR_MIN(discount, price) AS for_lowest_discount
FROM payments;
```

It will return the following output:

```sql
+---------------------+
| for_lowest_discount |
+---------------------+
|               120.5 |
+---------------------+
```

### #Case 2: `FOR_MIN()` with `GROUP BY` clause

For this example, we use a `GROUP BY` clause to group the customers, then use `FOR_MIN()` to get a discount for the lowest price paid by each customer.

```sql
SELECT customer_name, FOR_MIN(price, discount) AS discount
FROM payments
GROUP BY customer_name;
```

Which will give the following result:

```sql
+---------------+----------+
| customer_name | discount |
+---------------+----------+
|               |          |
| Bob           |     0.07 |
| Alex          |     0.05 |
| John          |          |
+---------------+----------+
```


# MAX



## Overview

`MAX()` function returns the maximum value from a set of records.

The input and return types we support can be seen in the table below.

![max types](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/max.png)

<Check>The return will be the same as the data type used as the input values.</Check>

💡**Special cases:**

*   Returns `NULL` if there are no input rows or `NULL` values.

*   Returns `NaN` if the input contains a `NaN`.

## Examples

<Info>For the `MAX()` examples, we will use the same sample table as in the MIN() section.</Info>

We have a movies table that stores the movie details, such as the movie's title, category, and IMDb rating.

```sql
CREATE TABLE movies (
    movieid int,
    moviename string,
    moviecategory string,
    imdbrating real
);
INSERT INTO movies (movieid, moviename, moviecategory, imdbrating)
VALUES
(8557411, 'The Shawshank Redemption', 'Drama', 9.4),
(8557421, 'Life Is Beautiful', 'Romance', 8.4),
(8557451, 'The Godfather', 'Crime', 9.3),
(8557311, 'Prisoners', 'Thriller', 8.5),
(8557321, 'Inception', 'Science Fiction', 9),
(8557351, 'The Dark Knight', 'Action', 9.2),
(8557221, 'Coco', 'Drama', 8.2),
(8557251, 'The Sixth Sense', 'Horror', 8.1),
(8557231, 'Kill Bill: Vol. 1', 'Action', 8.1),
(8557281, 'The Notebook', 'Romance', 7.8),
(8557291, 'Forrest Gump', 'Drama', 8);
```

```sql
SELECT * FROM movies;
```

The above query will show the following table:

```sql
+---------+--------------------------+-----------------+-------------+
| movieid | moviename                | moviecategory   | imdbrating  |
+---------+--------------------------+-----------------+-------------+
| 8557411 | The Shawshank Redemption | Drama           | 9.4         |
| 8557421 | Life Is Beautiful        | Romance         | 8.4         |
| 8557451 | The Godfather            | Crime           | 9.3         |
| 8557311 | Prisoners                | Thriller        | 8.5         |
| 8557321 | Inception                | Science Fiction | 9           |
| 8557351 | The Dark Knight          | Action          | 9.2         |
| 8557221 | Coco                     | Drama           | 8.2         |
| 8557251 | The Sixth Sense          | Horror          | 8.1         |
| 8557231 | Kill Bill: Vol. 1        | Action          | 8.1         |
| 8557281 | The Notebook             | Romance         | 7.8         |
| 8557291 | Forrest Gump             | Drama           | 8           |
+---------+--------------------------+-----------------+-------------+
```

### #Case 1: `MAX()` with a single expression

For example, you might want to know what is the highest rating among all stored movies:

```sql
SELECT MAX(imdbRating) AS "Highest Rating"
FROM movies;
```

It will return the following output:

```sql
+-----------------+
| Highest Rating  |
+-----------------+
| 9.4             |
+-----------------+
```

### #Case 2: `MAX()` with GROUP BY clause

We use a `MAX()` for this example to get the highest rating in each movie category.

```sql
SELECT movieCategory AS "Movie Category", MAX(imdbRating) AS "Highest Rating"
FROM movies
GROUP BY movieCategory;
```

It will display the highest rating from a group of `movieCategory` as shown below:

```sql
+------------------+-----------------+
| Movie Category   | Highest Rating  |
+------------------+-----------------+
| Thriller         | 8.5             |
| Romance          | 8.4             |
| Crime            | 9.3             |
| Horror           | 8.1             |
| Drama            | 9.4             |
| Action           | 9.2             |
| Science Fiction  | 9               |
+------------------+-----------------+
```

### #Case 3: `MAX()` in a subquery

In this example, we want to get a movie that has the highest rating by using a subquery:

```sql
SELECT movieName, IMDbRating
FROM movies
WHERE IMDbRating = (
SELECT MAX(IMDbRating)
FROM movies
);
```

It will return the following result:

```sql
+---------------------------+-------------+
| moviename                 | imdbrating  |
+---------------------------+-------------+
| The Shawshank Redemption  | 9.4         |
+---------------------------+-------------+
```


# MIN



## Overview

`MIN()` function returns the minimum value from a set of records.

The input and return types we support can be seen in the table below.

![min types](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/min.png)

<Check>The return will be the same as the data type used as the input values.</Check>

💡**Special cases:**

*   Returns `NULL` if there are no input rows or `NULL` values.

*   Returns `NaN` if the input contains a `NaN`.

## Examples

We have a movies table that stores the movie details, such as the movie’s title, category, and IMDb rating:

```sql
CREATE TABLE movies (
    movieid int,
    moviename string,
    moviecategory string,
    imdbrating real
);
INSERT INTO movies (movieid, moviename, moviecategory, imdbrating)
VALUES
(8557411, 'The Shawshank Redemption', 'Drama', 9.4),
(8557421, 'Life Is Beautiful', 'Romance', 8.4),
(8557451, 'The Godfather', 'Crime', 9.3),
(8557311, 'Prisoners', 'Thriller', 8.5),
(8557321, 'Inception', 'Science Fiction', 9),
(8557351, 'The Dark Knight', 'Action', 9.2),
(8557221, 'Coco', 'Drama', 8.2),
(8557251, 'The Sixth Sense', 'Horror', 8.1),
(8557231, 'Kill Bill: Vol. 1', 'Action', 8.1),
(8557281, 'The Notebook', 'Romance', 7.8),
(8557291, 'Forrest Gump', 'Drama', 8);
```

```sql
SELECT * FROM movies;
```

It will create a table as shown below:

```sql
+---------+--------------------------+-----------------+-------------+
| movieid | moviename                | moviecategory   | imdbrating  |
+---------+--------------------------+-----------------+-------------+
| 8557411 | The Shawshank Redemption | Drama           | 9.4         |
| 8557421 | Life Is Beautiful        | Romance         | 8.4         |
| 8557451 | The Godfather            | Crime           | 9.3         |
| 8557311 | Prisoners                | Thriller        | 8.5         |
| 8557321 | Inception                | Science Fiction | 9           |
| 8557351 | The Dark Knight          | Action          | 9.2         |
| 8557221 | Coco                     | Drama           | 8.2         |
| 8557251 | The Sixth Sense          | Horror          | 8.1         |
| 8557231 | Kill Bill: Vol. 1        | Action          | 8.1         |
| 8557281 | The Notebook             | Romance         | 7.8         |
| 8557291 | Forrest Gump             | Drama           | 8           |
+---------+--------------------------+-----------------+-------------+
```

### #Case 1: `MIN()` with a single expression

For example, you might want to know what is the lowest rating of all stored movies:

```sql
SELECT MIN(imdbRating) AS "Lowest Rating"
FROM movies;
```

It will return the following output:

```sql
+----------------+
| Lowest Rating  |
+----------------+
| 7.8            |
+----------------+
```

### #Case 2: `MIN()` with `GROUP BY` clause

For this example, we use a `GROUP BY` clause to group the movie categories, then use `MIN()` to get the lowest rating in each movie category.

```sql
SELECT movieCategory AS "Movie Category", MIN(imdbRating) AS "Lowest Rating"
FROM movies
GROUP BY movieCategory;
```

It will display the lowest rating from a group of `movieCategory` as shown below:

```sql
+------------------+----------------+
| Movie Category   | Lowest Rating  |
+------------------+----------------+
| Thriller         | 8.5            |
| Romance          | 7.8            |
| Crime            | 9.3            |
| Horror           | 8.1            |
| Drama            | 8              |
| Action           | 8.1            |
| Science Fiction  | 9              |
+------------------+----------------+
```

### #Case 3: `MIN()` in a subquery

In this example, we can get a movie that has the lowest rating by using a subquery:

*   First, the subquery will select the lowest rating using a `MIN()` function and store it as the `IMDbRating`.

*   Then, the outer query selects the movie with a rating equal to the lowest rating stored in the `IMDbRating`.

```sql
SELECT movieName, IMDbRating
FROM movies
WHERE IMDbRating = (
    SELECT MIN(IMDbRating)
    FROM movies
);
```

It will return the following result:

```sql
+---------------+-------------+
| moviename     | imdbrating  |
+---------------+-------------+
| The Notebook  | 7.8         |
+---------------+-------------+
```


# SUM



## Overview

`SUM()` calculates the sum of values from stored records. `SUM()` doesn’t consider `NULL` in the calculation, and it returns `NULL` instead of zero if the executed statement returns no rows.

The input and return types we support can be seen in the table below.

| Input type | Return type |
| ---------- | ----------- |
| INT        | LONG        |
| LONG       | LONG        |
| FLOAT      | DOUBLE      |
| DOUBLE     | DOUBLE      |
| INTERVAL   | INTERVAL    |

<Note>If the input type is 32-bit, then the result will be 64-bit.</Note>

## Examples

We have two sample tables here:

**customer table**

```sql
CREATE TABLE customer (
  customer_id int,
  cust_name string
);
INSERT INTO customer
    (customer_id, cust_name)
VALUES
    (11112, 'Alex'),
    (11113, 'Aaron'),
    (11114, 'Alice'),
    (11115, 'Nina'),
    (11116, 'Rosy'),
    (11117, 'Martha'),
    (11118, 'John');
```

```sql
SELECT * FROM customer;
```

It will create a table as shown below:

```sql
+-------------+-----------+
| customer_id | cust_name |
+-------------+-----------+
| 11112       | Alex      |
| 11113       | Aaron     |
| 11114       | Alice     |
| 11115       | Nina      |
| 11116       | Rosy      |
| 11117       | Martha    |
| 11118       | John      |
+-------------+-----------+
```

**rental table**

```sql
CREATE TABLE rental (
    rental_id int,
    rental_date timestamp,
    return_date timestamp,
    car string,
    customer_id int,
    total_price int
);
INSERT INTO rental (rental_id, rental_date, return_date, car, customer_id, total_price)
VALUES
(8557411, '2022-04-02 09:10:19', '2022-04-10 10:15:05', 'Audi', 11112, 1400),
(8557421, '2022-04-06 07:00:30', '2022-04-19 07:10:19', 'BMW', 11115, 2000),
(8557451, '2022-04-19 08:00:20', '2022-04-24 08:05:00', 'Cadillac', 11112, 1000),
(8557311, '2022-05-11 09:15:28', '2022-05-18 09:00:18', 'Audi', 11115, 1500),
(8557321, '2022-05-20 10:12:22', '2022-05-28 10:08:48', 'Audi', 11113, 1500),
(8557351, '2022-06-10 12:18:09', '2022-06-20 18:12:23', 'Cadillac', 11114, 1200),
(8557221, '2022-06-17 14:02:02', '2022-06-20 14:17:02', 'Chevrolet', 11112, 1300),
(8557251, '2022-07-12 05:19:49', '2022-07-19 07:15:28', 'Chevrolet', 11116, 1400),
(8557231, '2022-08-09 09:29:08', '2022-08-24 09:30:58', 'Cadillac', 11114, 2000),
(8557291, '2022-08-18 15:15:20', '2022-09-01 15:30:19', 'BMW', 11117, 3000);
```

```sql
SELECT * FROM rental;
```

Here, we have a rental table which stores the details for car rental:

```sql
+------------+---------------------+---------------------+-----------+---------------+-------------+
| rental_id  | rental_date         | return_date         | car       | customer_id   | total_price |
+------------+---------------------+---------------------+-----------+---------------+-------------+
| 8557411    | 2022-04-02 09:10:19 | 2022-04-10 10:15:05 | Audi      | 11112         | 1400        |
| 8557421    | 2022-04-06 07:00:30 | 2022-04-19 07:10:19 | BMW       | 11115         | 2000        |
| 8557451    | 2022-04-19 08:00:20 | 2022-04-24 08:05:00 | Cadillac  | 11112         | 1000        |
| 8557311    | 2022-05-11 09:15:28 | 2022-05-18 09:00:18 | Audi      | 11115         | 1500        |
| 8557321    | 2022-05-20 10:12:22 | 2022-05-28 10:08:48 | Audi      | 11113         | 1500        |
| 8557351    | 2022-06-10 12:18:09 | 2022-06-20 18:12:23 | Cadillac  | 11114         | 1200        |
| 8557221    | 2022-06-17 14:02:02 | 2022-06-20 14:17:02 | Chevrolet | 11112         | 1300        |
| 8557251    | 2022-07-12 05:19:49 | 2022-07-19 07:15:28 | Chevrolet | 11116         | 1400        |
| 8557231    | 2022-08-09 09:29:08 | 2022-08-24 09:30:58 | Cadillac  | 11114         | 2000        |
| 8557291    | 2022-08-18 15:15:20 | 2022-09-01 15:30:19 | BMW       | 11117         | 3000        |
+------------+---------------------+---------------------+-----------+---------------+-------------+
```

### #Case 1: `SUM()` in `SELECT` statement

The following example uses the `SUM()` function to calculate the total rent price of all `rental_id`:

```sql
SELECT SUM (total_price) AS total
FROM rental
```

It will return a sum value of the `total_price`:

```sql
+--------+
| total  |
+--------+
| 16300  |
+--------+
```

### #Case 2: `SUM()` with a `NULL` result

The following example uses the `SUM()` function to calculate the total rent price of the `customer_id = 11118.`

```sql
SELECT SUM (total_price) AS total
FROM rental
WHERE customer_id = 11118;
```

Since no records in the **rental** table have the `customer_id = 11118`, the `SUM()` function returns a `NULL`.

```sql
+--------+
| total  |
+--------+
| null   |
+--------+
```

### #Case 3: `SUM()` with `GROUP BY` clause

You can use the `GROUP BY` clause to group the records in the table and apply the `SUM()` function to each group afterward.

The following example uses the `SUM()` function and the `GROUP BY` clause to calculate the total price paid by each customer:

```sql
SELECT customer_id,
SUM (total_price) AS total_spend
FROM rental
GROUP BY customer_id;
```

It will calculate the `total_price` from a group of `customer_id` as shown below:

```sql
+--------------+--------------+
| customer_id  | total_spend  |
+--------------+--------------+
| 11115        | 3500         |
| 11117        | 3000         |
| 11116        | 1400         |
| 11113        | 1500         |
| 11112        | 3700         |
| 11114        | 3200         |
+--------------+--------------+
```

### #Case 4: `SUM()` with `HAVING` clause

You can use the `SUM()` function with the `HAVING` clause to filter out the sum of groups based on a specific condition:

```sql
SELECT
    customer_id,
    SUM (total_price) AS total_spend
FROM rental
GROUP BY customer_id
HAVING SUM(total_price) >= 3000;
```

It will return the customers who spent greater than or equal to 3000:

```sql
+--------------+--------------+
| customer_id  | total_spend  |
+--------------+--------------+
| 11115        | 3500         |
| 11117        | 3000         |
| 11112        | 3700         |
| 11114        | 3200         |
+--------------+--------------+
```

### #Case 5: `SUM()` with multiple expression

The example uses the following:

*   `SUM()` function to calculate total rental days.

*   `JOIN` clause to combine the rental table with the customer table.

*   `GROUP BY` group a result-set based on the customers' names.

```sql
SELECT s.cust_name, SUM(return_date - rental_date ) AS rental_period
FROM rental AS r
JOIN customer AS s
ON r.customer_id = s.customer_id
GROUP BY cust_name;
```

The final result will display the customers' names with their total rental period.

```sql
+------------+-------------------+
| cust_name  | rental_period     |
+------------+-------------------+
| Aaron      | 7 days 23:56:26   |
| Martha     | 14 days 00:14:59  |
| Rosy       | 7 days 01:55:39   |
| Nina       | 19 days 23:54:39  |
| Alex       | 16 days 01:24:26  |
| Alice      | 25 days 05:56:04  |
+------------+-------------------+
```


# CONCAT



## Overview

The `CONCAT()` function is used to concatenate all inputs that consist of one or more values into one result.

The input and return types we support can be seen in the table below.

![concat types](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/concat.png)

💡**Special cases:** Returns `NULL` if there are no input rows or `NULL` values.

## Examples

### Case 1: Basic `CONCAT()` function

The below example uses the `CONCAT()` function to concatenate three values = into a single result:

```sql
SELECT CONCAT ('Oxla', '.', 'com') AS "Website";
```

The final result will be as follows:

```sql
+------------+
| Website    |
+------------+
| Oxla.com   |
+------------+
```

### Case 2: `CONCAT()` function using column

We have an example of a **payment** table that stores customer payment data.

```sql
CREATE TABLE payment (
  paymentid int,
  custFirstName string,
  custLastName string,
  product string,
  ordertotal int
);
INSERT INTO payment
    (paymentid, custFirstName, custLastName, product, ordertotal)
VALUES
    (9557451,'Alex','Drue','Latte',2.10),
    (9557421,'Lana','Rey','Latte',2.10),
    (9557411,'Tom','Hanks','Americano',1.85),
    (9557351,'Maya','Taylor','Cappuccino',2.45),
    (9557321,'Smith','Jay','Cappuccino',2.45),
    (9557311,'Will','Ritchie','Americano',1.85);
```

```sql
SELECT * FROM payment;
```

The above query will display the following table:

```sql
+------------+----------------+----------------+--------------+---------------+
| paymentid  | custFirstName  | custLastName   | product      | ordertotal    |
+------------+----------------+----------------+--------------+---------------+
| 9557451    | Alex           | Drue           | Latte        | 2.10          |
| 9557421    | Lana           | Rey            | Latte        | 2.10          |
| 9557411    | Tom            | Hanks          | Americano    | 1.85          |
| 9557351    | Maya           | Taylor         | Cappuccino   | 2.45          |
| 9557321    | Smith          | Jay            | Cappuccino   | 2.45          |
| 9557311    | Will           | Ritchie        | Americano    | 1.85          |
+------------+----------------+----------------+--------------+---------------+
```

The following query will concatenate values in the `custFirstName` and `custLastName` columns of the **payment** table:

```sql
SELECT CONCAT  (custFirstName, ' ', custLastName) AS "Customer Name"
FROM payment;
```

It will display an output where spaces separate the first and last names.

```sql
+-----------------+
| Customer Name   |
+-----------------+
| Tom Hanks       |
| Lana Rey        |
| Alex Drue       |
| Will Ritchie    |
| Smith Jay       |
| Maya Taylor     |
+-----------------+
```

### Case 3: CONCAT() function with NULL

We use the `CONCAT()` function in the following example to concatenate a string with a `NULL` value:

```sql
SELECT CONCAT('Talent Source ',NULL) AS "concat";
```

The result shows that the `CONCAT` function will skip the `NULL` value:

```sql
+------------------+
| concat           |
+------------------+
| Talent Source    |
+------------------+
```


# ENDS_WITH



## Overview

The `ENDS_WITH()` function determines whether the first argument ends with a specified string in the second argument or not.

```sql
ENDS_WITH(first_argument, 'second_argument')
```

*   `first_argument`: the specified argument, which will be the search reference. It can be a string or a column name.

*   `second_argument`: the specified argument, which will have the search keywords.

The input type will be `STRING`, and the return type is `BOOL`, shown as `true` or `false`.

💡**Special case:**

*   It will return `NULL` for the `NULL` record.

*   It will return `true` (including the `NULL` record) if the `second_argument` is not specified.

## Examples

### #Case 1: `ENDS_WITH()` function using column

Let’s say we have a table named **courses**:

```sql
CREATE TABLE courses (
  course_id int,
  course_name string,
  credits string
);
INSERT INTO courses 
    (course_id, course_name, credits) 
VALUES 
    (2111,'Basics of Plant Biotechnology',2),
    (2102,'Biochemistry',3),
    (1241,'Statistics',3),
    (4142,'Microbial Biodiversity',2),
    (3262,'Introduction to Plant Pathology',3),
    (3233,'Enzyme Technology',2),
    (1201,'Rural Sociology',2);
```

```sql
SELECT * FROM courses;
```

The above query will display the following table:

```sql
+------------+----------------------------------+-----------+ 
| course_id  | course_name                      | credits   |
+------------+----------------------------------+-----------+
| 2111       | Basics of Plant Biotechnology    | 2         |
| 2102       | Biochemistry                     | 3         |
| 1241       | Statistics                       | 3         |
| 4142       | Microbial Biodiversity           | 2         |
| 3262       | Introduction to Plant Pathology  | 3         |
| 3233       | Enzyme Technology                | 2         |
| 1201       | Rural Sociology                  | 2         |
+------------+----------------------------------+-----------+
```

Using the following query, we want to confirm the values of the **course\_name** column that end with "ology" in the table above:

```sql
SELECT course_name, ENDS_WITH(course_name, 'ology') FROM courses;
```

It will return true to all the courses with the name ending with **ology. **Otherwise**,** `false`.

```sql
+----------------------------------+-------------+
| course_name                      | ends_with   |
+----------------------------------+-------------+
| Basics of Plant Biotechnology    | true        |
| Biochemistry                     | false       |
| Statistics                       | false       |
| Microbial Biodiversity           | false       |
| Introduction to Plant Pathology  | true        |
| Enzyme Technology                | true        |
| Rural Sociology                  | true        |
+----------------------------------+-------------+
```

### Case 2: `ENDS_WITH()` function with no specified argument

Here we have the \*\*patients\_data \*\*table with a `NULL` value in the **allergies** column.

```sql
CREATE TABLE patients_data (
  record_number int,
  patient_name string,
  height_in_cm int,
  weight_in_kg int,
  allergies string
);
INSERT INTO patients_data 
    (record_number, patient_name, height_in_cm, weight_in_kg, allergies) 
VALUES 
    (2009000908,'Vivienne Desjardin',168,49,''),
    (2012000876,'Elizabeth Reinhard',163,55,''),
    (2015000965,'James McCarthy',188,70,'penicillin'),
    (2020000109,'Jose Ramirez',170,70,'sulfonamide'),
    (2020000222,'Stefani Ricci',170,70,'peniccilin');
```

```sql
SELECT * FROM patients_data;
```

```sql
+----------------+---------------------+---------------+--------------+-------------+
| record_number  | patient_name        | height_in_cm  | weight_in_kg | allergies   |
+----------------+---------------------+---------------+--------------+-------------+
| 2009000908     | Vivienne Desjardin  | 168           | 49           | null        |
| 2012000876     | Elizabeth Reinhard  | 163           | 55           | null        |
| 2015000965     | James McCarthy      | 188           | 70           | penicillin  |
| 2020000109     | Jose Ramirez        | 170           | 70           | sulfonamide |
| 2020000222     | Stefani Ricci       | 170           | 70           | peniccilin  |
+----------------+---------------------+---------------+--------------+-------------+
```

For example, we run the `ENDS_WITH` function but with no specified `second_argument`.

```sql
SELECT allergies, ENDS_WITH(allergies, '') FROM patients_data;
```

We will have the result where the `ENDS_WITH` will return true to all records (even the `null` one).

```sql
+--------------+--------------+
| allergies    | starts_with  |
+--------------+--------------+
| null         | true         |
| null         | true         |
| penicillin   | true         |
| sulfonamide  | true         |
| peniccilin   | true         |
+--------------+--------------+
```


# LENGTH



## Overview

The `LENGTH()` function is used to find the length of a string, i.e., the number of characters in a given string. It accepts a string as a parameter. Syntax of the length function is illustrated below:

```sql
LENGTH(string)
```

The input type is a string, and the return type is int, as it returns the number of characters.

**💡Special cases:**

*   If a null value is passed in the function, i.e., `LENGTH(NULL)`, it will return `NULL`.

*   If the parameter is an empty string `LENGTH(")`, it will return 0.

*   If the parameter is a space character `LENGTH('')`, not empty or null, it will return 1 as it is not empty anymore.

## Examples

### #Case 1: Basic `LENGTH()` function

The below example uses the `LENGTH()` function to find out the length of a string text:

```sql
SELECT LENGTH ('Oxla PostgreSQL Tutorial');
```

The final output will be as follows:

```sql
+------------+
| length     |
+------------+
| 24         |
+------------+
```

### #Case 2: `LENGTH()` function using columns

Let's see how the `LENGTH()` function works on the **personal\_details** table containing the employee's **id**, **first\_name**, **last\_name**, and **gender** of a retail store as columns.

```sql
CREATE TABLE personal_details (
  id int,
  first_name string,
  last_name string,
  gender string
);
INSERT INTO personal_details 
    (id, first_name, last_name, gender) 
VALUES 
    (1,'Mark','Wheeler','M'),
    (2,'Tom','Hanks','M'),
    (3,'Jane','Hopper','F'),
    (4,'Emily','Byers','F'),
    (5,'Lucas','Sinclair','M');
```

```sql
SELECT * FROM personal_details;
```

The above query will show the following table:

```sql
+-----+-------------+-------------+----------+
| id  | first_name  | last_name   | gender   |
+-----+-------------+-------------+----------+
| 1   | Mark        | Wheeler     | M        |
| 2   | Tom         | Hanks       | M        |
| 3   | Jane        | Hopper      | F        |
| 4   | Emily       | Byers       | F        |
| 5   | Lucas       | Sinclair    | M        |
+-----+-------------+-------------+----------+
```

The following query returns the last name and the length of the last name from the personal\_details table, where the length of the last\_name is greater than 5.

```sql
SELECT last_name,length(last_name)
AS "Length of Last Name"
FROM personal_details
WHERE LENGTH(last_name) > 5;
```

The output displays all those items in the last\_name column with a length of more than 5 characters.

```sql
+---------------+-----------------------+
| last_name     | Length of Last Name   |
+---------------+-----------------------+
| Wheeler       | 7                     |
| Hopper        | 6                     |
| Sinclair      | 8                     |
+---------------+-----------------------+
```


# LOWER



## Overview

The LOWER() function returns a given string, an expression, or values in a column in all lowercase letters. The syntax of the function is illustrated below:

```sql
LOWER(string)
```

It accepts input as a string and returns the text in the lowercase alphabet.

💡**Special Cases:** If there are characters in the input which are not of type string, they remain unaffected by the LOWER()function.

<Info>We support Unicode so that the ß is equivalent to the string ss.</Info>

## Examples

### #Case 1: Basic `LOWER()` function

The following basic query converts the given string in all lowercase alphabets:

```sql
SELECT LOWER('PostGreSQL');
```

The final output will be as follows:

```sql
+------------+
| lower      |
+------------+
| postgresql |
+------------+
```

### #Case 2: `LOWER()` function using columns

Let’s see how the `LOWER()` function works using an example with columns. We have a **personal\_details** table containing columns **id**, **first\_name**, **last\_name**, and **gender** of retail store employees.

```sql
CREATE TABLE personal_details (
  id int,
  first_name string,
  last_name string,
  gender string
);
INSERT INTO personal_details 
    (id, first_name, last_name, gender) 
VALUES 
    (1,'Mark','Wheeler','M'),
    (2,'Tom','Hanks','M'),
    (3,'Jane','Hopper','F'),
    (4,'Emily','Byers','F'),
    (5,'Lucas','Sinclair','M');
```

```sql
SELECT * FROM personal_details;
```

The above query will show the following table:

```sql
+-----+-------------+-------------+----------+
| id  | first_name  | last_name   | gender   |
+-----+-------------+-------------+----------+
| 1   | Mark        | Wheeler     | M        |
| 2   | Tom         | Hanks       | M        |
| 3   | Jane        | Hopper      | F        |
| 4   | Emily       | Byers       | F        |
| 5   | Lucas       | Sinclair    | M        |
+-----+-------------+-------------+----------+
```

Let’s assume that we want to convert the first and last names of employees with **id** numbers 2, 4, and 5 to all lowercase letters, which can be done using the following query:

```sql
SELECT first_name,last_name,LOWER(first_name),LOWER(last_name)
FROM personal_details
where id in (2, 4, 5);
```

The output displays the first and last names of employees with the specified ids in lowercase letters:

```sql
+------------+-------------+----------+----------+
| first_name | last_name   | lower    | lower    |
+------------+-------------+----------+----------+
| Tom        | Hanks       | tom      | hanks    |
| Emily      | Byers       | emily    | byers    |
| Lucas      | Sinclair    | lucas    | lucas    |
+------------+-------------+----------+----------+
```


# POSITION



## **Overview**

The POSITION function returns the position of the first occurrence of a substring in a string. It works the same as [STRPOS](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/strpos), but it has slightly different syntax.

## **Syntax**

The `REPLACE()` function syntax is as follows.

```sql
POSITION(substring IN string)
```

The position of the substring within the string starts from 1. If the substring is not found, it returns 0.

## **Examples**

### Example 1

This query looks for the position of the substring `world` within the string `Hello, world!`.

```sql
SELECT POSITION('world' IN 'Hello, world!');
```

The result would be the starting position of the substring `world`, which is 7.

```sql
position 
----------
        7
```

### Example 2

The query looks for the position of the substring `123` within the string `1a2b3c`.

```sql
SELECT POSITION('123' IN '1a2b3c');
```

`123` is found starting at position 1, the result would be 1.

```sql
position 
----------
        7
```

### Example 3

The query tries to find the position of the substring `abc` within the string `xyz`.

```sql
SELECT POSITION('abc' IN 'xyz');
```

`abc` is not found in `xyz`, the result would be 0.

```sql
position 
----------
        0
```

### Example 4

This query searches for the position of the substring `cde` within the string `cde`.

```sql
SELECT POSITION('cde' IN 'cde');
```

`cde` is the entire string, the result would be 1.

```sql
position 
----------
        1
```


# POSIX Regular Expressions



**POSIX** stands for Portable Operating System Interface. It defines a set of standard operating system interfaces based on the UNIX OS.

In POSIX Basic Regex syntax, most characters are treated as literals, i.e., they match only themselves. But, there are some exceptions, which are called **Metacharacters**.

| **Functions** | **Description**                                                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `.`           | Matches any single character. For example, `a.c` matches "**abc**", but `[a.c]` matches only "**a**", "**.**", or "**c**".      |
| `-`           | Used to define a range. For example, `[a-c]` will match characters **a** to **c** (both inclusive).                             |
| \[]           | Calculates and returns a value corresponding to the minimal metric in the same row from a set of values.                        |
| `^`           | Calculates and returns the maximum value.                                                                                       |
| `$`           | Calculates and Returns a value corresponding to the maximum metric in the same row from a set of values.                        |
| `*`           | Calculates and returns the average value.                                                                                       |
| `{n}`         | Counts the number of rows.                                                                                                      |
| `{n,m}`       | Calculates the boolean of all the boolean values in the aggregated group. `FALSE` if at least one of aggregated rows is `FALSE` |


# REGEXP_REPLACE



## **Overview**

The `REGEXP_REPLACE()` function replaces all occurrences of a regular expression pattern in a string with a specified replacement string.

## **Syntax**

It has the following basic syntax:

```sql
REGEXP_REPLACE(source_string, pattern, replacement, [flags])
```

The function takes six parameters:

*   `source_string`**:** The string that we want to perform the replacement on.

*   `pattern`**:** The POSIX regular expression pattern to match.

*   `replacement`: The replacement string.

*   `flags`: (Optional) A string that changes the matching behaviour of `REGEXP_REPLACE` function. See the [Flags](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/regexp-replace/regexp#flags) section for more details.

<Info>**Special Cases** <br /><br /> - The function returns `NULL` if there are no input rows or `NULL` values. <br /> - If the regular expression pattern is not found in the string, then the `REGEXP_REPLACE()` function will return the original string.</Info>

## Flags

The `flags` parameter is an optional string that controls how the function operates. Here are the supported `flags` in Oxla:

### - `g`

Global replacement. This flag ensures that all occurrences of the pattern are replaced.

For example, without specifying the `g` flag, `REGEXP_REPLACE` only replaces the first occurrence. In this case, only the first digit (`1`) is replaced with `X`.

```sql
SELECT REGEXP_REPLACE('ab12c', '[0-9]', 'X');
```

```sql
 regexp_replace 
----------------
 abX2c
```

By adding the `g` flag, all occurrences are replaced with `x`.

```sql
SELECT REGEXP_REPLACE('ab12c', '[0-9]', 'X', 'g');
```

```sql
 regexp_replace 
----------------
 abXXc
```

### - `i`

Use this flag for case-insensitive matching. It should not be used together with the `c` flag.

### - `c`

The `REGEXP_REPLACE()` function is case sensitive by default, so using the `c` flag has the same effect as having no flags at all.  It should not be used together with the `i` flag.

<Info>If multiple flags are used, the last one takes precedence. For example: <br /><br /> - For flags `ci`, the regex will be case-insensitive. . <br /> - For flags `ic`, the regex will be case-sensitive.</Info>

## **Examples**

### Case #1: Basic REGEXP\_REPLACE() Function

In this example, the function is used with a basic POSIX regular expression pattern:

```sql
Select REGEXP_REPLACE('The OXLA supports various data types', 'T[^ ]*', 'We') AS "Replaced_String";
```

The result will be:

```sql
+-----------------------------------------+
| Replaced_String                         |
+-----------------------------------------+
| We OXLA supports various data types     |
+-----------------------------------------+
```

In this example,  the pattern used is\*\* "T\[^ ]\*"\*\*, which matches any substring that starts with a 'T' character, followed by any number of non-space characters. The function replaces the matched substring with the specified replacement string **"We"**.

### Case #2: Replacing Special Characters

The following example demonstrates how to replace a non-alphanumeric character in a string with an underscore.

```sql
SELECT REGEXP_REPLACE('Hello World!', '[^A-Za-z0-9 ]', '~') AS "Replaced_String";
```

In the above query, the second parameter is a regular expression **“\[^A-Za-z0-9 ]”** that matches any characters that are not uppercase/lowercase letters, digits, or spaces.

The result will be:

```sql
+-------------------+
| Replaced String   |
+-------------------+
| Hello World~  	|
+-------------------+
```

### Case #3: REGEXP\_REPLACE() Function with Flag

The following example shows how the `REGEXP_REPLACE()` function can replace certain substrings with a flag defined.

1.  We'll start by creating the `quotes` table:

```sql
CREATE TABLE quotes (quotes_text string);
INSERT INTO quotes (quotes_text)
VALUES ('Work hard and stay hungry. Lazy people get nowhere in life.'),
       ('An excuse is a way for a LAZY person to feel better.'),
       ('The word LUCKY is how a lazy person describes someone who works hard.');

SELECT quotes_text FROM quotes;
```

The result will be as follows:

```sql
                              quotes_text                              
-----------------------------------------------------------------------
 Work hard and stay hungry. Lazy people get nowhere in life.
 An excuse is a way for a LAZY person to feel better.
 The word LUCKY is how a lazy person describes someone who works hard.
(3 rows)
```

2.  Now, let's use the `REGEXP_REPLACE()` function with the `i` flag to replace all occurrences of the word `lazy` with `active` regardless of the case sensitivity.

```sql
SELECT quotes_text, REGEXP_REPLACE(quotes_text, 'lazy', 'active', 'i') AS "New quotes" FROM quotes;
```

In this result, all occurrences of the word `lazy` (**Including case insensitive**) have been replaced with active.

```sql
                              quotes_text                              |                               New quotes                                
-----------------------------------------------------------------------+-------------------------------------------------------------------------
 Work hard and stay hungry. Lazy people get nowhere in life.           | Work hard and stay hungry. active people get nowhere in life.
 An excuse is a way for a LAZY person to feel better.                  | An excuse is a way for a active person to feel better.
 The word LUCKY is how a lazy person describes someone who works hard. | The word LUCKY is how a active person describes someone who works hard.
(3 rows)
```

words with the replacement.


# REPLACE



## **Overview**

The `REPLACE()` function looks for and replaces a substring with a new one in a string. This function is often used to update the outdated or spelling mistakes in data that require an amendment.

<Info>Oxla also has the `REGEXP_REPLACE()` function. It enables you to search and replace a substring(s) that matches with a POSIX regular expression. See [here](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/regexp-replace/regexp) for more info.</Info>

## **Syntax**

The `REPLACE()` function syntax is described as follows.

```sql
REPLACE(string, old_substring, new_substring)
```

The syntax requires three arguments, explained below:

*   `string`: the string that you want to replace.

*   `old_substring`: the substring that you want to replace. All parts will be replaced if it appears multiple times in the string.

*   `new_substring`: the new substring that will replace the old one\*\*.\*\*

<Warning>The `REPLACE()` function performs a case-sensitive replacement.</Warning>

## **Examples**

### Case #1: Basic `REPLACE()` function

We will replace the substring of the “**OxlaDatabase”** string from “\*\*New” \*\*to “**Oxla”**, as shown below:

```sql
SELECT REPLACE ('NewDatabase', 'New', 'Oxla');
```

The `REPLACE()` function will find and replace all occurrences in the string and return the following:

```sql
+---------------------+
| f                   |
+---------------------+
| OxlaDatabase        |
+---------------------+
```

### Case #2: Replacing the specified values in a table

This example shows how to replace the values of a specific column in a table.

1.  Create a new table named **extracurriculars** with **club** and **category** columns and insert the values into the respective columns.

```sql
CREATE TABLE hobby (
  club string,
  category string 
);
INSERT INTO hobby 
    (club, category) 
VALUES 
    ('Bridge','group'),
    ('Painting','individual'),
    ('Basketball','group'),
    ('Volleyball','group');
```

2.  Retrieve all values from the table using the following query.

```sql
SELECT * FROM hobby;
```

```sql
+------------+---------------+
| club       | category      |
+------------+---------------+
| Bridge     | group         |
| Painting   | individual    |
| Basketball | group         |
| Volleyball | group         |
+--------------+-------------+
```

3.  Replace the **“group”** value in the **category** column with\*\* “sports”.\*\*

```sql
SELECT REPLACE(category, 'group', 'sports') from hobby;
```

4.  The final result will look like the following. 

```sql
+--------------+
| f            |
+--------------+
| sports       |
| individual   |
| sports       |
| sports       |
+--------------+
```

### Case #3:  Remove a word with `REPLACE()` function

In the following example, we will remove \*\*“Friends” \*\*in a string with a `REPLACE()` function.&#x20;

```sql
SELECT REPLACE('Hello Friends','Friends','');
```

The final output will leave the remaining word, **“Hello”.**

```sql
+-----------+
| f         |
+-----------+
| Hello     |
+-----------+
```

### Case #4:  Replace multiple patterns with `REPLACE()` function

The following example uses the `REPLACE()` function to replace multiple patterns of the given string.&#x20;

```sql
SELECT REPLACE(REPLACE(REPLACE(REPLACE('2*[9-5]/{4+8}', '[', '('), ']', ')'), '{', '('), '}', ')');
```

We can see that the REPLACE function is called multiple times to replace the corresponding string as specified:

*   the **`[]`** into **`()`**

*   the **`{}`** into **`()`**

```sql
+------------------+
| f                |
+------------------+
| 2*(9-5)/(4-8)    |
+------------------+
```


# STARTS_WITH



## Overview

The `STARTS_WITH()` function determines whether the first argument starts with a specified string in the second argument or not.

```sql
STARTS_WITH(first_argument, 'second_argument')
```

*   `first_argument`: the specified argument, which will be the search reference. It can be a string or a column name.

*   `second_argument`: the specified argument, which will have the search keywords.

The input type will be `STRING`, and the return type is `BOOL`, shown as `true` or `false`.

💡**Special case:**

*   It will return `NULL` for the `NULL` record.

*   It will return `true` (including the `NULL` record) if the `second_argument` is not specified.

## Examples

### #Case 1: `STARTS_WITH()` function using column

Let’s say we have a table with the title **petsData**, as shown below.

```sql
CREATE TABLE petsData (
  petid int,
  petname string,
  species string,
  breed string,
  sex string,
  age int
);
INSERT INTO petsData 
    (petid, petname, species, breed, sex, age) 
VALUES 
    (2021001,'Bartholomeow','cat','persian','m',2),
    (2021004,'Jack','dog','boston terrier','m',1),
    (2022001,'Jesse','hamster','dzungarian','m',1),
    (2022010,'Bella','dog','dobberman','f',3),
    (2022011,'June','cat','american shorthair','f',2);
```

```sql
SELECT * FROM petsData;
```

The above query will show the following table:

```sql
+----------+--------------+----------+---------------------+------+-----+
| petid    | petname      | species  | breed               | sex  | age |
+----------+--------------+----------+---------------------+------+-----+
| 2021001  | Bartholomeow | cat      | persian             | m    | 2   |
| 2021004  | Jack         | dog      | boston terrier      | m    | 1   |
| 2022001  | Jesse        | hamster  | dzungarian          | m    | 1   |
| 2022010  | Bella        | dog      | dobberman           | f    | 3   |
| 2022011  | June         | cat      | american shorthair  | f    | 2   |
+----------+--------------+----------+---------------------+------+-----+
```

From the table above, we want to retrieve the values of **petname** column that start with “J” by using the following query:

```sql
SELECT petname, STARTS_WITH(petname, 'J') FROM petsData;
```

It will return `true` to the pet with a pet starting with the letter J. Otherwise, `false`.

```sql
+--------------+---------------+
|   petname     | starts_with  |
+---------------+--------------+
| Bartholomeow  | false        |
| Jack          | true         |
| Jesse         | true         |
| Bella         | false        |
| June          | true         |
+---------------+--------------+
```

### Case 2: `STARTS_WITH()` function with no specified argument

Here we have the **petsData** table with a `NULL` value in the breed column.

```sql
CREATE TABLE petsData (
  petid int,
  petname string,
  species string,
  breed string,
  sex string,
  age int
);
INSERT INTO petsData 
    (petid, petname, species, breed, sex, age) 
VALUES 
    (2021001,'Bartholomeow','cat','persian','m',2),
    (2021004,'Jack','dog','boston terrier','m',1),
    (2022001,'Jesse','hamster','dzungarian','m',1),
    (2022010,'Bella','dog','dobberman','f',3),
    (2022011,'June','cat','american shorthair','f',2),
    (2022012,'Phoebe','gold fish','','f',1);
```

```sql
SELECT * FROM petsData;
```

```sql
+----------+--------------+------------+---------------------+------+------+
| petid    | petname      | species    | breed               | sex  | age  |
+----------+--------------+------------+---------------------+------+------+
| 2021001  | Bartholomeow | cat        | persian             | m    | 2    |
| 2021004  | Jack         | dog        | boston terrier      | m    | 1    |
| 2022001  | Jesse        | hamster    | dzungarian          | m    | 1    |
| 2022010  | Bella        | dog        | dobberman           | f    | 3    |
| 2022011  | June         | cat        | american shorthair  | f    | 2    |
| 2022012  | Phoebe       | gold fish  |                     | f    | 1    |
+----------+--------------+------------+---------------------+------+------+
```

For example, we run the `STARTS_WITH` function but with no specified `second_argument:`

```sql
SELECT breed, STARTS_WITH(breed, '') FROM petsData;
```

We will have the following result where the `STARTS_WITH` will return true to all records (even the `null` one):

```sql
+---------------------+--------------+
| breed               | starts_with  |
+---------------------+--------------+
| persian             | true         |
| boston terrier      | true         |
| dzungarian          | true         |
| dobberman           | true         |
| american shorthair  | true         |
| null                | true         |
+---------------------+--------------+
```


# Overview



String functions are used to analyze and manipulate string values. Oxla supports the following String functions:

| **Functions**                                                                                                             | **Description**                                                                                                                                                                                                                   |
| ------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [LENGTH()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/length)                         | Returns the number of characters in a string.                                                                                                                                                                                     |
| [LOWER()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/lower)                           | Makes string lowercase.                                                                                                                                                                                                           |
| [UPPER()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/upper)                           | Makes string upper case.                                                                                                                                                                                                          |
| [STARTS\_WITH()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/starts-with)              | It returns true if the first argument starts with the second argument.                                                                                                                                                            |
| [ENDS\_WITH()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/ends-with)                  | It returns true if the first argument ends with the second argument.                                                                                                                                                              |
| [CONCAT()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/concat)                         | Concatenates all inputs into a single result.Concatenates all inputs into a single result.Concatenates all inputs into a single result.Concatenates all inputs into a single result.Concatenates all inputs into a single result. |
| [SUBSTR()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/substr)                         | Retrieves substring.                                                                                                                                                                                                              |
| [STRPOS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/strpos)                         | Finds the position at which the substring (defined as a second argument) starts within the string (defined as a first argument).                                                                                                  |
| [REGEXP\_REPLACE()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/regexp-replace/regexp) | Substitutes new text for substrings that match POSIX regular expression patterns.                                                                                                                                                 |
| [REPLACE()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/replace)                       | Finds and replaces a substring with a new one in a string.                                                                                                                                                                        |
| [POSITION()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/position)                     | Returns the position of the first occurrence of a substring in a string.                                                                                                                                                          |

String operators:

| **Functions**              | **Description**                                                                                                  |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| text \~ text -> boolean    | Return true if the first argument matches the pattern of the second argument in case sensitive match.            |
| text \~\* text -> boolean  | Return true if the first argument matches the pattern of the second argument in a case-insensitive match.        |
| text !\~ text -> boolean   | Return true if the first argument does not match the pattern of the second argument in case sensitive match.     |
| text !\~\* text -> boolean | Return true if the first argument does not match the pattern of the second argument in a case-insensitive match. |

 


# STRPOS



## Overview

The `STRPOS()` is used to return the position from where the substring (the second argument) is matched with the string (the first argument).

```sql
STRPOS(string, substring)
```

The input and return must be of type `string`.

💡**Special cases:**

*   Returns `NULL` if there are no input rows or `NULL` values.

*   If the `substring` is not found in the string, then the `STRPOS()` function will return 0.

## Examples

### Case 1: Basic `STRPOS()` function

In the example below, we will find the **ut** (substring) position in the **computer** (string):

```sql
SELECT STRPOS('computer', 'ut') AS "Position of ut";
```

We can see that **ut** is located at the fifth character of the **computer**:

```sql
+-----------------+
| Position of ut  |
+-----------------+
| 5               |
+-----------------+
```

### Case 2: STRPOS() function using column

We have a **listofwords** table where it stores the word data.

```sql
CREATE TABLE listofwords (
  words string
);
INSERT INTO listofwords 
    (words) 
VALUES 
    ('corral'),
    ('traditionally'),
    ('real'),
    ('communal'),
    ('challenge'),
    ('fall'),
    ('wall'),
    ('gallop'),
    ('albatross');
```

```sql
SELECT * FROM listofwords;
```

The above query will show the following table:

```sql
+----------------+
| words          |
+----------------+
| corral         |
| traditionally  | 
| real           | 
| communal       | 
| challenge      | 
| fall           | 
| wall           | 
| gallop         | 
| albatross      | 
+----------------+
```

The following query will display the words and a position of a specific substring = ‘**al**’ using the `STRPOS()` function:

```sql
SELECT words, STRPOS(words, 'al') AS "Position of al"
FROM listofwords;
```

The result will display the **al** position of different words:

```sql
+----------------+------------------+
| words          | Position of al   |
+----------------+------------------+
| corral         | 5                |
| traditionally  | 10               |
| real           | 3                |
| communal       | 7                |
| challenge      | 3                |
| fall           | 2                |
| wall           | 2                |
| gallop         | 2                |
| albatross      | 1                |
+----------------+------------------+
```


# SUBSTR



## Overview

The `SUBSTR()` function extracts a specific number of characters from a string.

## Syntax

The syntax of the function is illustrated below:

**2 Arguments**

```sql
substr( string, start_position)
```

**3 Arguments**

```sql
substr( string, start_position, length )
```

<Tip>Both syntaxes will have input and return of type `string`.</Tip>

### Start Position

The `start_position` is used as the starting position, specifying the part from where the substring is to be returned. It is written as an integer value.

| **Input**                                      | **Return**                                                                                                                                                                                                                                                                                       |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `start_position < 0 ``start_position < string` | The `start_position` is a given character in the string. The count starts from the first character.                                                                                                                                                                                              |
| `start_position > string`                      | Returns an empty substring.                                                                                                                                                                                                                                                                      |
| `start_position` = negative value              | The count starts from the provided negative value, with subsequent characters yielded as it approaches 0. <br /><br /> If the index is less than or equal to 0, no characters are returned. <br /><br /> Once it exceeds 0, characters from the string are yielded, starting from the first one. |

### **Length**

The `length` is used to determine the number of characters to be extracted\*. \*It can be one or more characters.

| **Input**                 | **Return**                                                                                                 |
| ------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `length` = 0              | Returns an empty substring.                                                                                |
| `length` is not set       | The function will start from the specified `start_position` and end at the last character of the `string`. |
| `length` = negative value | Returns an error.                                                                                          |

## Examples

### Case 1: `SUBSTR()` function with specified `start_position` & `length`&#x20;

In this example, we will set the `start_position` with the first six characters and have five characters extracted:

```sql
SELECT substr('Watermelon',6,5) AS "Fruit";
```

The updated table is shown below:

```sql
Fruit 
-------
 melon
```

### Case 2: `SUBSTR()` function with `length` = 0

The following query will extract a string with `length` = 0:

```sql
SELECT substr('Watermelon',6,0) AS "Fruit";
```

It will display an empty output as there is no `length` specified:

```sql
Fruit 
-------

```

### Case 3: `SUBSTR()` function with `length` = negative value

Here we will check if the `length` is specified with a negative value:

```sql
SELECT substr('Watermelon',6,-2) AS "Fruit";
```

Instead of extracting the string from the last characters, it will return an error as seen below:

```sql
ERROR:  Length of substring cannot be negative
```

### Case 4: `SUBSTR()` function with `start_position` > `string`&#x20;

We know that **Watermelon** only has ten characters, but this time, we will figure out if the specified `start_position` is larger than the string’s characters:

```sql
SELECT substr('Watermelon',20,2) AS "Fruit";
```

It will display an empty output as shown below:

```sql
Fruit 
-------

```

### Case 5: `SUBSTR()` Function with 2 Arguments

In this example, we will set the `start_position` with the first six characters and have five characters extracted.

```sql
SELECT substr('database', 6) AS "Result";
```

It will display the substring from position 6 output as shown below:

```sql
Result 
--------
 ase
```


# SUBSTRING



<Warning>SUBSTR is an alias for SUBSTRING. Learn more at [SUBSTR](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/substr) documentation.</Warning>

## Overview

The SUBSTRING() function lets you extract a part of a string and return that substring.

## Syntax

Here are the 2 basic syntaxes of the SUBSTRING() function in Oxla:

**2 Arguments**

```sql
SUBSTRING( string, start_position )
```

**3 Arguments**

```sql
SUBSTRING(string, start_position, length)
```

<Tip>Both syntaxes will have input and return of type `string`.</Tip>

## Example

The following example uses the `SUBSTRING()` function to extract the first 7 characters from the string.

```sql
SELECT SUBSTRING('OxlaDocumentation', 1, 7);
```

It will display the substring from position 6 output as shown below:

```sql
substring 
-----------
 OxlaDoc
```


# UPPER



## Overview

The `UPPER()` function returns a given string, an expression, or values in a column in all uppercase letters. The syntax of the function is illustrated below:

```sql
UPPER(string)
```

It accepts input as a string and returns text in uppercase letters.

💡 **Special Case:**

*   If characters in the input are not of type string, they remain unaffected by the `UPPER()` function.

*   We support Unicode for the `UPPER()` function.

## Examples

### #Case 1: Basic `UPPER()` function

The following basic query converts the given string in all uppercase alphabets:

```sql
SELECT UPPER('PostGreSQL');
```

The final output will be as follows:

```sql
+-------------+
| upper       |
+-------------+
| POSTGRESQL  |
+-------------+
```

### #Case 2: UPPER() function using columns and CONCAT() function

Let’s see how the `UPPER()` function works using an example with columns. We have a table named **personal\_details** containing employee's **id**, **first\_name**, **last\_name**, and **gender** of a retail store:

```sql
CREATE TABLE personal_details (
  id int,
  first_name string,
  last_name string,
  gender string
);
INSERT INTO personal_details 
    (id, first_name, last_name, gender) 
VALUES 
    (1,'Mark','Wheeler','M'),
    (2,'Tom','Hanks','M'),
    (3,'Jane','Hopper','F'),
    (4,'Emily','Byers','F'),
    (5,'Lucas','Sinclair','M');
```

```sql
SELECT * FROM personal_details;
```

The above query will show the following table:

```sql
+-----+-------------+-------------+----------+
| id  | first_name  | last_name   | gender   |
+-----+-------------+-------------+----------+
| 1   | Mark        | Wheeler     | M        |
| 2   | Tom         | Hanks       | M        |
| 3   | Jane        | Hopper      | F        |
| 4   | Emily       | Byers       | F        |
| 5   | Lucas       | Sinclair    | M        |
+-----+-------------+-------------+----------+
```

Let’s assume that:

1.  We want to convert employees' first and last names with **id** numbers 1, 3, and 5 to all uppercase letters.

2.  Then, combine them using the `CONCAT()` function into one **full\_name** column in uppercase.

It can be done using the following query:

```sql
SELECT CONCAT (UPPER(first_name),' ', UPPER(last_name))
as full_name
FROM personal_details
where id in (1, 3, 5);
```

The output displays the first and last names of employees with the specified ids in uppercase letters:

```sql
+---------------------+
| full_name           |
+---------------------+
| MARK WHEELER        |
| JANE HOPPER         |
| LUCAS SINCLAIR      |
+---------------------+
```


# CURRENT_TIMESTAMP



## Overview

The `CURRENT_TIMESTAMP()` returns the current timestamp value representing the date and time the query was executed.

<Info>Note that the time returned by this function is the time when the query was executed.</Info>

### Syntax

```sql
CURRENT_TIMESTAMP(precision)
```

The `precision` is used to set the number of digits in the fractional seconds precision in the **second** field.

If you omit the `precision`, the `CURRENT_TIMESTAMP()` function will return a current timestamp that includes the complete fractional seconds precision.

<Warning>The maximum precision value that you can input is 6.</Warning>

## Examples

### #Case 1: Current timestamp

The following example shows how to get the current date and time with a `CURRENT_TIMESTAMP()`function:

```sql
SELECT CURRENT_TIMESTAMP AS "Current Time";
```

The final result will display the current date and time in your timezone:

```sql
+-----------------------------+
| Current Time                |
+-----------------------------+
| 2022-08-31 16:56:06.464016  |
+-----------------------------+
```

### #Case 2: Current timestamp with precision

Let's assume we want to get the current timestamp but with a 2-fractional seconds precision:

```sql
SELECT CURRENT_TIMESTAMP(2);
```

The function will return the current date and time with 2 digits after seconds:

```sql
+-------------------------+
| current_timestamp       |
+-------------------------+
| 2022-08-31 17:15:22.16  |
+-------------------------+
```


# DATE_TRUNC



## **Overview**

The `DATE_TRUNC()` function truncates intervals or timestamps/time zones to a specified field. The return type is the same as the source type.&#x20;

## **Syntax**

The syntax for using the `DATE_TRUNC()` function is as follows:

```sql
DATE_TRUNC(field, source);
```

or

```sql
DATE_TRUNC(field, source, time_zone);
```

Let's analyze the above syntax:

*   `field`: The unit of time used to truncate the `source` value. It accepts `text` inputs and is case-insensitive.

*   `source`: The value you want to truncate. It can be `INTERVAL`, `TIMESTAMP`, or `TIMESTAMP WITH TIME ZONE`.

*   `time_zone` *(applicable for the second syntax option)*: The time zone for the operation. It accepts `text` input.

## **Fields**

Below is a list of supported values to specify the fields param in `DATE_TRUNC()` syntax.

*   `microseconds `

*   `milliseconds`

*   `second`

*   `minute`

*   `hour`

*   `day`

*   `week`

*   `month`

*   `quarter`

*   `year`

*   `decade`

*   `century`

*   `millennium`

## Examples

### Case #1: **Truncating to Year**

This example truncates the timestamp to the year level.&#x20;

```sql
select DATE_TRUNC('year', '1911-12-02 19:40:00'::timestamp);
```

The timestamp \*\*“1911-12-02 19:40:00” \*\*has been truncated to 1911, with the month and day set to January 1st.&#x20;

```sql
         date_trunc         
----------------------------
 1911-01-01 00:00:00.000000
```

### Case #2: **Truncating to Day**

This query truncates the timestamp **"1911-12-02 19:40:00"** to the day level.

```sql
select DATE_TRUNC('day', '1911-12-02 19:40:00'::timestamp);
```

The timestamp has been truncated to the same day, year, month, and day components.&#x20;

```sql
        date_trunc         
----------------------------
 1911-12-02 00:00:00.000000
```

### Case #3: **Truncating to Week**

This query truncates the timestamp **"1911-12-02 19:40:00"** to the week level.

```sql
select DATE_TRUNC('week', '1911-12-02 19:40:00'::timestamp);
```

The timestamp has been truncated to the week starting on November 27, 1911.&#x20;

```sql
        date_trunc         
----------------------------
 1911-11-27 00:00:00.000000
```

### Case #4: **Truncating to Quarter**

This query truncates the timestamp **"1911-12-02 19:40:00"** to the quarter level.

```sql
select DATE_TRUNC('quarter', '1911-12-02 19:40:00'::timestamp);
```

The year component of the timestamp is truncated, but the month and day components are set to the beginning of the quarter.

```sql
        date_trunc         
----------------------------
 1911-10-01 00:00:00.000000
```

### Case #5: **Truncating to Hour**

This query truncates the interval of **"15 hours 10 minutes"** to the hour level.

```sql
select DATE_TRUNC('hour', '15 hour 10 minutes'::interval);
```

The interval\*\* \*\*has been truncated to 15 hours, with the minutes and seconds set to zero.

```sql
   date_trunc    
-----------------
 15:00:00.000000
```

### Case #6: **Truncating to Quarter (Interval)**

This query truncates the interval **"16 years 4 months"** to the quarter level.

```sql
select DATE_TRUNC('quarter', '16 years 4 months'::interval);
```

The interval has been truncated to the nearest quarter.

```sql
   date_trunc    
-----------------
 16 years 3 mons
```


# EXTRACT



## Overview

The `EXTRACT()` function extracts a given part from a specified source. The source must be a value expression of timestamp, time, or interval.

### Syntax

```sql
EXTRACT(field from source)
```

Let's analyze the above syntax:

*   `field`: used to specify the time parts that are to be extracted.

*   `source`: used to identify a date/time value. The value type is `TIMESTAMP` (YYYY-MM-DD HH:MM:SS) or `INTERVAL` (year - month - day hour - minute - second).

### Input and Return Type

The table below shows the supported input types of `field` and the return type of the `EXTRACT()` function:

![](https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/extract.png)

## Examples&#x20;

### #Case 1: `EXTRACT()` with Timestamp - Year

The below example uses the `EXTRACT()` function to extract a given timestamp’s **YEAR**:

```sql
SELECT EXTRACT(YEAR FROM TIMESTAMP '2020-12-31 13:30:15');
```

The final output will be as follows:

```sql
+----------+
| extract  |
+----------+
| 2020     |
+----------+
```

### #Case 2: `EXTRACT()` with Timestamp - Month

Here we will use the `EXTRACT()` function to extract a given timestamp’s **MONTH:**

```sql
SELECT EXTRACT(MONTH FROM TIMESTAMP '2016-10-31 13:30:15');
```

The final output will take the month’s part of a given timestamp:

```sql
+----------+
| extract  |
+----------+
| 10       |
+----------+
```

### #Case 3: `EXTRACT()` with Interval - Day

In this example, we will extract the \*\*DAY \*\*part of a given interval:

```sql
SELECT EXTRACT(DAY FROM INTERVAL '6 years 8 months 20 days 4 hours 47 minutes 22 second' );
```

The final output will be as follows:

```sql
+----------+
| extract  |
+----------+
| 20       |
+----------+
```

### #Case 4: `EXTRACT()` with Interval - Second

The below example uses the `EXTRACT()` function to extract seconds from the given interval.

```sql
SELECT EXTRACT(SECOND FROM INTERVAL '6 years 2 months 13 days 8 hours 30 minutes 43 second' );
```

The final output will be as follows:

```sql
+------------+
| extract    |
+------------+
| 43.000000  |
+------------+
```


# FORMAT_TIMESTAMP



## Overview

The `FORMAT_TIMESTAMP()` function returns a given timestamp value in a specified format. Its syntax is illustrated below:

```sql
FORMAT_TIMESTAMP(timestamp, format_string)
```

This function requires two arguments, i.e., a **timestamp** string that represents the timestamp value that needs to be converted to a specified format and a **format\_string** that specifies the format to be converted into. Its return type is a timestamp value with a timezone.

### #Case 1: Basic `FORMAT_TIMESTAMP()` function

The below example uses the `FORMAT_TIMESTAMP()` function to convert a given timestamp into a timestamp format as specified in the function arguments.

```sql
SELECT FORMAT_TIMESTAMP( 2 '2022-05-30 5:30:04', 3 'YYYY-MM-DD HH:MI:SS' 4);
```

Details of the format specified are as follows:

*   `YYYY` is the four-digit year 2022

*   `MM` is the month: 05

*   `DD` is the day: 30

*   `HH` is the hour: 5

*   `MI` is the minute: 30

*   `SS` is the second: 04

<Info>The format specified in the string can be used in any combination.</Info>

The final output will be as follows:

```sql
+-----------------------------+
| format_timestamp            |
+-----------------------------+
| 2022-05-30 05:30:04+05      |
+-----------------------------+
```

### #Case 2: `FORMAT_TIMESTAMP()` function using multiple spaces

The `FORMAT_TIMESTAMP()` when given multiple spaces in the input string, omits the spaces and only returns the correct timestamp value. Let's see how it works using the following example:

```sql
SELECT 2 FORMAT_TIMESTAMP('2008 Dec','YYYY MON');
```

It will return the following output:

```sql
+-----------------------------+
| format_timestamp            |
+-----------------------------+
| 2008-12-01 00:00:00+05      |
+-----------------------------+
```

### #Case 3: `FORMAT_TIMESTAMP()` function if the input value of the year is less than 4 digits

`FORMAT_TIMESTAMP()` will adjust the year to the nearest year value if the input argument has less than the required number of digits i.e., less than 4. To see how it works, look at the example below:

```sql
SELECT 2 FORMAT_TIMESTAMP('07 25 09 10:40', 'MM DD YY HH:MI');
```

It will return the following output:

```sql
+-----------------------------+
| format_timestamp            |
+-----------------------------+
| 2009-07-25 10:40:00+06      |
+-----------------------------+
```

In this example, the two-digit year `09` has been changed to the nearest four-digit year i.e., `2009`. Similarly, `70` will become `1970`, and `10` will become `2010,` etc.


# Overview



Timestamp functions return a date-time value based on a specified timestamp/interval. Oxla supports the following Timestamp functions:

| **Functions**                                                                                                                         | **Description**                                                                                                           |
| :------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ |
| [CURRENT\_TIMESTAMP()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/current-timestamp)           | Returns the current date and time as a timestamp data type.                                                               |
| [FORMAT\_TIMESTAMP()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/format-timestamp)             | Modifies the current timestamp into a different format.                                                                   |
| [UNIX\_SECONDS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/unix-seconds)                     | Converts a given timestamp to a UNIX timestamp in seconds.                                                                |
| [UNIX\_MILLIS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/unix-millis)                       | Converts a given timestamp to a UNIX timestamp in milliseconds.                                                           |
| [UNIX\_MICROS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/unix-macros)                       | Converts a given timestamp to a UNIX timestamp in microseconds.                                                           |
| [TIMESTAMP\_SECONDS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-second)            | Converts a UNIX timestamp in seconds to a timestamp.                                                                      |
| [TIMESTAMP\_MILLIS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-millis)             | Converts a UNIX timestamp in milliseconds to a timestamp.                                                                 |
| [TIMESTAMP\_MICROS()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-micros)             | Converts a UNIX timestamp in microseconds to a timestamp.                                                                 |
| [TIMESTAMP\_TRUNC()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-trunc)               | Truncates a given timestamp to the nearest time part. Supported time parts are YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND |
| [EXTRACT()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/extract)                                | Extracts some part of a specified timestamp or interval.                                                                  |
| [TO\_TIMESTAMP()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/to-timestamp)                     | Converts a string into a timestamp based on the provided format.                                                          |
| [DATE\_TRUNC()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/date-trunc)                         | Truncates intervals or timestamps/time zones to a specified field.                                                        |
| [TO\_CHAR() from Timestamp](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/to-char-from-timestamp) | Formats a timestamp into a string using a given format.                                                                   |


# TIMESTAMP_MICROS



## Overview

The `TIMESTAMP_MICROS()` function converts a given UNIX timestamp value in microseconds since 1970-01-01 00:00:00 UTC into a timestamp. Its syntax can be seen below:

```sql
SELECT TIMESTAMP_MICROS(Int64)
```

Its input type is an `int64` expression representing a UNIX timestamp in microseconds, and the return data type is a timestamp.

## Examples

### #Case 1: Basic `TIMESTAMP_MICROS()` function

The below example uses the `TIMESTAMP_MICROS()` function to convert a given UNIX timestamp in microseconds into a timestamp without a timezone:

```sql
SELECT TIMESTAMP_MICROS(2280419000000000) AS timestamp_microsvalues;
```

The final output will be as follows:

```sql
+-----------------------------+
| timestamp_microsvalues      |
+-----------------------------+
| 2042-04-06 17:43:20         |
+-----------------------------+
```

### #Case 2: `TIMESTAMP_MICROS()` function using columns

Let’s suppose we have a table named \*\*timemirco\_example \*\*with the following UNIX time values in microseconds in the **unix\_timestamp** column:

```sql
CREATE TABLE timemirco_example (
  unix_timestamp long
);

INSERT INTO timemirco_example VALUES 
('1350417000000000'),
('2130215000000000'),
('1110115000000000'),
('2310112000000000');
```

```sql
SELECT * FROM timemirco_example;
```

The above query will show the following table:

```sql
+--------------------+
| unix_timestamp     | 
+--------------------+
| 1350417000000000   |
| 2130215000000000   |
| 1110115000000000   |
| 2310112000000000   |
+--------------------+
```

We want to convert all UNIX timestamp values in microseconds to timestamp values. To do that, we have to run the following query:

```sql
SELECT unix_timestamp, TIMESTAMP_MICROS(unix_timestamp)
AS timestamp_value
FROM timemicro_example;
```

The output displays all the entries in the table in UNIX timestamp format (in microseconds) in the \*\*unix\_timestamp \*\* column and in the timestamp format in the column **timestamp\_value** without timezone:

```sql
+-------------------------+-----------------------+
| unix_timestamp          | timestamp_value       |
+-------------------------+-----------------------+
|1350417000000000         | 2012-10-16 19:50:00   |
|2130215000000000         | 2037-07-03 06:23:20   |
|1110115000000000         | 2005-03-06 13:16:40   |
|2310112000000000         | 2043-03-16 09:46:40   |
+-------------------------+-----------------------+
```


# TIMESTAMP_MILLIS



## Overview

The `TIMESTAMP_MILLIS()` function converts a given UNIX timestamp value in milliseconds since 1970-01-01 00:00:00 UTC into a timestamp. Its syntax can be seen below:

```sql
SELECT TIMESTAMP_MILLIS(Int64)
```

Its input type is an `int64` expression which represents a UNIX timestamp in milliseconds and the return data type is a timestamp.

## Examples

### #Case 1: Basic `TIMESTAMP_MILLIS()` function

The below example uses the `TIMESTAMP_MILLIS()` function to convert a given UNIX timestamp in milliseconds into a timestamp without a timezone.

```sql
SELECT TIMESTAMP_MILLIS(1671975000000) AS timestamp_millisvalues;
```

The final output will be as follows:

```sql
+-----------------------------+
| timestamp_millisvalues      |
+-----------------------------+
| 2022-12-25 13:30:00         |
+-----------------------------+
```

### #Case 2: `TIMESTAMP_MILLIS()` function using columns

Let's suppose we have a table named \*\*unix\_example \*\*with the following UNIX time values in milliseconds in the **unix\_timestamp** column:

```sql
CREATE TABLE unix_example (
  unix_timestamp long
);

INSERT INTO unix_timestamp VALUES 
('171472000000'),
('1671975000000'),
('153276000000');
```

```sql
SELECT * FROM unix_example;
```

The above query will show the following table:

```sql
+----------------+
| unix_timestamp | 
+----------------+
| 171472000000   |
| 1671975000000  |
| 153276000000   |
+----------------+
```

We want to convert all UNIX timestamp values in milliseconds to timestamp values. To do that, we have to run the following query:

```sql
SELECT unix_timestamp, TIMESTAMP_MILLIS(unix_timestamp)
AS timestamp_value
FROM unix_example;
```

The output displays all the entries in the table in UNIX timestamp format (in milliseconds) in the **unix\_timestamp **column and in the timestamp format in the column** timestamp\_value** without timezone.

```sql
+-------------------------+-----------------------+
| unix_timestamp          | timestamp_value       |
+-------------------------+-----------------------+
|171472000000             | 1975-06-08 15:06:40   |
|1671975000000            | 2022-12-25 13:30:00   |
|153276000000             | 1974-11-10 00:40:00   |
+-------------------------+-----------------------+
```


# TIMESTAMP_SECONDS



## Overview

The `TIMESTAMP_SECONDS()` function converts a given UNIX timestamp value in seconds from 1970-01-01 00:00:00 UTC into a timestamp. Its syntax can be seen below:

```sql
SELECT TIMESTAMP_SECONDS(Int64)
```

Its input type is an `int64` expression representing a UNIX timestamp in seconds, and the return data type is a timestamp.

## Examples

### #Case 1: Basic `TIMESTAMP_SECONDS()` function

The below example uses the `TIMESTAMP_SECONDS()` function to convert a given UNIX timestamp in seconds into a timestamp:

```sql
SELECT TIMESTAMP_SECONDS(1671975000) AS timestamp_secondsvalue;
```

The final output will be as follows:

```sql
+-----------------------------+
| timestamp_secondsvalue      |
+-----------------------------+
| 2022-12-25 13:30:00         |
+-----------------------------+
```

### #Case 2: `TIMESTAMP_SECONDS()` function using columns

Let's suppose we have a table named \*\*unix\_time \*\*with the following UNIX time values in seconds:

```sql
CREATE TABLE unix_time (
  unix_time int
);

INSERT INTO unix_time VALUES 
('982384720'),
('1671975000'),
('171472000');
```

```sql
SELECT * FROM unix_time;
```

The above query will show the following table:

```sql
+-------------+
| unix_time   | 
+-------------+
| 982384720   |
| 1671975000  |
| 171472000   |
+-------------+
```

We want to convert all UNIX timestamp values in seconds to timestamp values. To do that, we have to run the following query:

```sql
SELECT unix_time, TIMESTAMP_SECONDS(unix_time)
AS timestamp_value
FROM unix_time ;
```

The output displays all the entries in the table in UNIX timestamp format (in seconds) in the **unix\_time **column** **and in the timestamp format without timezone in the column** timestamp\_value**.

```sql
+-------------------------+-----------------------+
| unix_time               | timestamp_value       |
+-------------------------+-----------------------+
| 982384720               | 2001-02-17 04:38:40   |
| 1671975000              | 2022-12-25 13:30:00   |
| 171472000               | 1975-06-08 15:06:40   |
+-------------------------+-----------------------+
```


# TIMESTAMP_TRUNC



## Overview

The `TIMESTAMP_TRUNC()` function rounds a timestamp to a specific `day_time` granularity, resulting in a truncated timestamp.

### Syntax

```sql
SELECT TIMESTAMP_TRUNC(TIMESTAMP 'YYYY-MM-DD hour:min:sec', day_time);
```

`day_time` can be replaced with various time values as follows:

*   `SECOND`

*   `MINUTE`

*   `HOUR`

*   `DAY`

*   `MONTH`

*   `YEAR`

## Examples

### #Case 1: `TIMESTAMP_TRUNC()` - Hour

The following example shows how to round the hour to the closest value:

```sql
SELECT TIMESTAMP_TRUNC(TIMESTAMP '2017-09-18 14:43:39.02322', HOUR) ;
```

The final result will display the current date and time in your timezone:

```sql
+-----------------------------+
| f                           |
+-----------------------------+
| 2017-09-18 14:00:00.00000   |
+-----------------------------+
```

### #Case 2: `TIMESTAMP_TRUNC()` - Minute

Here we will truncate the specified timestamp into the nearest value:

```sql
SELECT TIMESTAMP_TRUNC(TIMESTAMP '2005-03-18 14:13:13', MINUTE) ;
```

The result will return the truncated timestamp as shown below:

```sql
+-----------------------------+
| f                           |
+-----------------------------+
| 2005-03-18 14:13:00.00000   |
+-----------------------------+
```

### #Case 3: Basic `TIMESTAMP_TRUNC()` function - Year

Run the following query to round the date to the closest value:

```sql
SELECT TIMESTAMP_TRUNC(TIMESTAMP '2023-03-04', YEAR);
```

The function will truncate the year and return the following result:

```sql
+-----------------------------+
| f                           |
+-----------------------------+
| 2023-01-01 00:00:00.00000   |
+-----------------------------+
```


# TO_CHAR from Timestamp



## **Overview**

The `TO_CHAR` function formats a timestamp into a string using a given format.

## **Syntax**

The syntax for using the `TO_CHAR` function is as follows:

```sql
TO_CHAR(timestamp, format_string)
```

Parameters in the syntax include:

*   `timestamp`: The `TIMESTAMP` or `TIMESTAMP WITH TIMEZONE` to be formatted to string.&#x20;

*   `format`: The format of the input string.&#x20;

## **Format**

Format string supports following template patterns (can be lowercase):

| **Pattern**                      | **Description**                    |
| -------------------------------- | ---------------------------------- |
| `YYYY`                           | Year (1-9999)                      |
| `HH`                             | Hour of day (1–12)                 |
| `HH12`                           | Hour of day (1–12)                 |
| `HH24`                           | Hour of day (0–23)                 |
| `MI`                             | Minute (0–59)                      |
| `SS`                             | Second (0–59)                      |
| `MS`                             | Millisecond (0–999)                |
| `US`                             | Microsecond (0–999999)             |
| `AM`, `am`, `PM` or `pm`         | Meridiem indicator without periods |
| `A.M.`, `a.m.`, `P.M.` or `p.m.` | Meridiem indicator with periods    |

### ❌ Limitations

*   All text inside double quote `"{text}" `will not be considered a pattern.

*   The quote character `""` will not appear in the result string.&#x20;

*   Any text that does not match any pattern will be preserved in the result string.

## **Examples**

### Case 1: Timestamp with Microseconds

The query aims to format a timestamp to display the year, month, day, hour, minute, second, and microseconds (`YYYY-MM-DD HH24:MI:SS.US`).

```sql
SELECT TO_CHAR('2012-03-04 05:06:07.080910'::timestamp, 'YYYY-MM-DD HH24:MI:SS.US');
```

The output shows the timestamp '2012-03-04 05:06:07.080910'.

```sql
          to_char           
----------------------------
 2012-03-04 05:06:07.080910
```

### Case 2: Time with Milliseconds and Meridiem

This query format a timestamp in a 12-hour clock format with the meridiem indicator (`p.m`).

```sql
SELECT TO_CHAR('2012-03-04 05:06:07.080910'::timestamp, 'HH12-MI-SS.MS p.m.');
```

The output shows the time 5:06:07 a.m. with milliseconds.

```sql
      to_char      
-------------------
 05-06-07.080 a.m.
```

### Case 3: Time with Meridiem Indicator

This query format a timestamp to display time in a 12-hour clock format along with the meridiem indicator (`AM`).

```sql
SELECT TO_CHAR('2012-03-04 17:06:07.080910'::timestamp, 'HH-MI-SS AM');
```

The output presents the time '17:06:07' in the format 'HH-MI-SS AM': 5:06:07 PM.

```sql
  to_char   
-------------
 05-06-07 PM
```

### Case 4: Timestamp with Text

This example adds custom text to the timestamp output.

```sql
SELECT TO_CHAR('2012-03-04 17:06:07.080910'::timestamp, 'Text "HH24-MI-SS" {HH24-MI-SS}');
```

It will return the output below.

```sql
          to_char           
----------------------------
 Text HH24-MI-SS {17-06-07}
```


# TO_TIMESTAMP



## **Overview**

The `TO_TIMESTAMP()` function converts a string into a timestamp based on the provided format. It returns a `TIMESTAMP WITH TIME ZONE` type.

## **Syntax**

The syntax for using the `TO_TIMESTAMP()` function is as follows:

```sql
SELECT TO_TIMESTAMP('source', 'format'');
```

Let's analyze the above syntax:

*   `source`: The date/time value to be converted. The value type is `TIMESTAMP` (`YYYY-MM-DD HH:MM:SS`).

*   `format`: The format of the input string.&#x20;

## **Format**

Format string supports following template patterns (can be lowercase):

| **Pattern**                      | **Description**        | **Detail**                                                                      |
| -------------------------------- | ---------------------- | ------------------------------------------------------------------------------- |
| `YYYY`                           | Year (1-9999)          | - The lowest possible value is 1 AD<br />- 0001 is 1<br />- 1 is 1              |
| `MM`                             | Month number (1–12)    | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `DD`                             | Day of month (1–31)    | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `HH`                             | Hour of day (1–12)     | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `HH12`                           | Hour of day (1–12)     | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `HH24`                           | Hour of day (0–23)     | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `MI`                             | Minute (0–59)          | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `SS`                             | Second (0–59)          | - Up to 2 digits<br />- 01 is 1<br />- 1 is 1                                   |
| `MS`                             | Millisecond (0–999)    | - Up to 3 digits<br />- 001 is 1 millisecond<br />- 1 is 100 milliseconds       |
| `US`                             | Microsecond (0–999999) | - Up to 6 digits<br />- 000001 is 1 microsecond<br />- 1 is 100000 milliseconds |
| `AM`, `am`, `PM` or `pm`         | Meridiem indicator     | Without periods                                                                 |
| `A.M.`, `a.m.`, `P.M.` or `p.m.` | Meridiem indicator     | With periods                                                                    |

## Examples

### Case #1: Timestamp into YYYY-MM-DD HH24:MI

The `TO_TIMESTAMP()` function converts the provided string into a timestamp with the format `YYYY-MM-DD HH24:MI`.

```sql
select TO_TIMESTAMP('2020-03-04 14:30', 'YYYY-MM-DD HH24:MI');
```

The final output will be a timestamp with a timezone.

```sql
        to_timestamp          
-------------------------------
 2020-03-04 14:30:00.000000+00
```

### Case #2: Timestamp into MM-DD HH12:MI

The `TO_TIMESTAMP()` function converts the provided string into a timestamp with the format `MM-DD HH12:MI`.

```sql
select TO_TIMESTAMP('3-04 02:30', 'MM-DD HH12:MI');
```

The final output will be a timestamp with a timezone.

```sql
       to_timestamp        
----------------------------
 1-03-04 02:30:00.000000+00
```

### Case #3: Timestamp into YYYY-MM HH12:MI(AM/PM)

The `TO_TIMESTAMP()`\` function converts the provided string into a timestamp with the format `YYYY-MM HH12:MI` with meridiem indicator (AM/PM).

**Request 1**

```sql
select TO_TIMESTAMP('2020-02 12:30AM', 'YYYY-MM HH12:MIPM');
```

**Request 2**

```sql
select TO_TIMESTAMP('2020-02 12:30AM', 'YYYY-MM HH:MIAM');
```

The final output of both requests will have the same result. It changes the time into a 12-hour format, resulting in **12:30** being adjusted to **00:30**.

```sql
         to_timestamp          
-------------------------------
 2020-02-01 00:30:00.000000+00
```

### Case #4: Timestamp into YYYY-MM-DD HH24:MI:SS.MS.US

The `TO_TIMESTAMP()` function converts the provided string into a timestamp with `YYYY-MM-DD HH24:MI:SS.MS.US` format.

```sql
select TO_TIMESTAMP('1960-01-31 15:12:02.020.001230', 'YYYY-MM-DD HH24:MI:SS.MS.US');
```

The final output will be a timestamp with milliseconds and microseconds.

```sql
        to_timestamp          
-------------------------------
 1960-01-31 15:12:02.021230+00
```

### Case #5: Timestamp into YYYY-MM-DD HH24:MI:SS.MS

The `TO_TIMESTAMP()` function converts the provided string into a timestamp with `YYYY-MM-DD HH24:MI:SS.MS` format.

```sql
select TO_TIMESTAMP('1960-01-31 15:12:02.02', 'YYYY-MM-DD HH24:MI:SS.MS');
```

The final output will be a timestamp with milliseconds.

```sql
        to_timestamp          
-------------------------------
 1960-01-31 15:12:02.020000+00
```


# UNIX_MICROS



## Overview

The `UNIX_MICROS()` function returns a given timestamp into a UNIX timestamp in microseconds, from 1970-01-01 00:00:00-00 (can be negative). Its syntax is illustrated below:

```sql
SELECT UNIX_MICRO(TIMESTAMP)
```

Its input type is a TIMESTAMP expression, and the return data type is `int64` representing time in microseconds.

## Examples

### #Case 1: Basic `UNIX_MICROS()` function

The below example uses the `UNIX_MICROS()` function to convert a given timestamp into a UNIX timestamp in microseconds:

```sql
SELECT UNIX_MICRO(TIMESTAMP "2022-12-25 13:30:00+00") AS unix_microsvalues;
```

The final output will be as follows:

```sql
+-----------------------------+
| unix_microsvalues           |
+-----------------------------+
| 1671975000000000.000000     |
+-----------------------------+
```

### #Case 2: `UNIX_MICROS()` function using columns

Let’s suppose we have a table named **time\_example** with the following timestamp values:

```sql
CREATE TABLE time_example (
  time_stamp timestamp
);

INSERT INTO time_example VALUES 
('2022-12-25 13:30:00'),
('2021-10-02 06:30:00'),
('2020-09-25 07:25:00');
```

```sql
SELECT * FROM time_example;
```

The above query will show the following table:

```sql
+-------------------------+
| time_example            | 
+-------------------------+
| 2022-12-25 13:30:00     |
| 2021-10-02 06:30:00     |
| 2020-09-25 07:25:00     |
+-------------------------+
```

We want to convert all timestamp values into UNIX timestamp values in microseconds. To do that, we have to run the following query:

```sql
SELECT time_stamp, UNIX_MICROS(time_stamp)
AS time_micros
FROM time_example;
```

The output displays all the timestamp entries in the **time\_stamp** column and the converted UNIX timestamps in microseconds in the column **time\_micros**.

```sql
+-------------------------+--------------------------+
| time_stamp               | time_micros              |
+-------------------------+--------------------------+
| 2022-12-25 13:30:00     | 1671975000000000.000000  |
| 2021-10-02 06:30:00     | 1633156200000000.000000  |
| 2020-09-25 07:25:00     | 1601018700000000.000000  |
+-------------------------+--------------------------+
```


# UNIX_MILLIS



## Overview

The `UNIX_MILLIS()` function returns a given timestamp to a UNIX timestamp in milliseconds from 1970-01-01 00:00:00-00 (can be negative). Its syntax is illustrated below:

```sql
SELECT UNIX_MILLIS(TIMESTAMP)
```

Its input type is a TIMESTAMP expression, and the return data type is `int64` representing time in milliseconds.

## Examples

### #Case 1: Basic `UNIX_MILLIS()` function

The below example uses the `UNIX_MILLIS()` function to convert a given timestamp into a UNIX timestamp in milliseconds:

```sql
SELECT UNIX_MILLIS(TIMESTAMP "1996-5-02 7:15:00+00") AS unix_millisvalues;
```

The final output will be as follows:

```sql
+-----------------------------+
| unix_millisvalues           |
+-----------------------------+
| 831021300000.000000         |
+-----------------------------+
```

### #Case 2: `UNIX_MILLIS()` function using columns

Let’s suppose we have a table named **time\_example **with the following timestamp values in the** time\_stamp** column:

```sql
CREATE TABLE time_example (
  time_stamp timestamp
);

INSERT INTO time_example VALUES 
('2004-07-23 11:30:00+00'),
('2011-02-12 04:45:00+00'),
('1975-08-03 07:50:00+00');
```

```sql
SELECT * FROM time_example;
```

The above query will show the following table:

```sql
+-------------------------+
| time_example            | 
+-------------------------+
| 2004-07-23 11:30:00     |
| 2011-02-12 04:45:00     |
| 1975-08-03 07:50:00     |
+-------------------------+
```

We want to convert all timestamp values into UNIX timestamp values in milliseconds. To do that, we have to run the following query:

```sql
SELECT time_stamp, UNIX_MILLIS(time_stamp) AS time_millis FROM time_example;
```

The output displays all the timestamp entries of the table in the \*\*time\_stamp \*\*column and the converted UNIX milliseconds timestamp entries in the column **time\_millis**.

```sql
+-------------------------+-----------------------+
| time_stamp              | time_millis           |
+-------------------------+-----------------------+
| 2004-07-23 11:30:00     | 1090582200000.000000  |
| 2011-02-12 04:45:00     | 1297485900000.000000  |
| 1975-08-03 07:50:00     | 176284200000.000000   |
+-------------------------+-----------------------+
```


# UNIX_SECONDS



## Overview

The `UNIX_SECONDS()` function returns a given timestamp to a UNIX timestamp in seconds, from 1970-01-01 00:00:00-00. Its syntax is illustrated below:

```sql
SELECT UNIX_SECONDS(TIMESTAMP)
```

Its input type is a TIMESTAMP expression, and the return data type is `int64` representing time in seconds.

## Examples

### #Case 1: Basic `UNIX_SECONDS()` function

The below example uses the `UNIX_SECONDS()` function to convert a given timestamp into a UNIX timestamp in seconds:

```sql
SELECT UNIX_SECONDS(TIMESTAMP "2008-12-25 15:30:00+00") AS unix_secondsvalues;
```

The final output will be as follows:

```sql
+-----------------------------+
| unix_secondsvalues          |
+-----------------------------+
| 1230219000.000000           |
+-----------------------------+
```

### #Case 2: `UNIX_SECONDS()` function using columns

Let’s suppose we have a table named \*\*time\_example \*\*with the following timestamp values in the **time\_stampvalues** column:

```sql
CREATE TABLE time_example (
  time_stampvalues timestamp
);

INSERT INTO time_example VALUES 
('2022-12-25 13:30:00'),
('2020-09-25 07:25:00'),
('2008-12-25 15:30:00'),
('2021-10-02 06:30:00');
```

```sql
SELECT * FROM time_example;
```

The above query will return the following table:

```sql
+-------------------------+
| time_stampvalues        | 
+-------------------------+
| 2022-12-25 13:30:00     |
| 2020-09-25 07:25:00     |
| 2008-12-25 15:30:00     |
| 2021-10-02 06:30:00     | 
+-------------------------+
```

1.  We want to convert all timestamp values into UNIX timestamp values in seconds. To do that, we have to run the following query:

```sql
SELECT time_stampvalues, UNIX_SECONDS(time_stampvalues)
AS time_secondsvalues
FROM time_example;
```

2.  The output displays all the timestamp entries of the table in the **time\_stampvalues** column and the converted UNIX seconds timestamp entries in the column **time\_secondsvalues**.

```sql
+-------------------------+-----------------------+
| time_stampvalues        | time_secondsvalues    |
+-------------------------+-----------------------+
| 2022-12-25 13:30:00     | 1671975000.000000     |
| 2020-09-25 07:25:00     | 1601018700.000000     |
| 2008-12-25 15:30:00     | 1230219000.000000     |
| 2021-10-02 06:30:00     | 1633156200.000000     |
+-------------------------+-----------------------+
```


# IF Function



### Overview

This function returns the specified value if the condition is `TRUE` and another value if the condition is `FALSE`.  The syntax of the `IF()`function is shown below:

```sql
IF(expression, true_result, else_result)
```

<Warning>The `expression` must be a Boolean expression.</Warning>

### Examples

### Case #1: `IF()` with a table

In this example, we have the **test\_result** table. We want to know which participants passed and which failed from the table below:

```sql
CREATE TABLE test_result (
  applicant_id int,
  name text,
  score int
);

INSERT INTO test_result VALUES 
(78765,'Mike Aoki',677),
(78786,'Julie Grahams',650),
(78986,'Alexandra Jones',450),
(79742,'Lucas Moore',487),
(79769,'Augustine Harkness',572);
```

```sql
SELECT * FROM test_result;
```

The above query will display the following table:

```sql
+---------------+--------------------+--------+
| applicant_id  | name               | score  |
+---------------+--------------------+--------+
| 78765         | Mike Aoki          | 677    |
| 78786         | Julie Grahams      | 650    |
| 78986         | Alexandra Jones    | 450    |
| 79742         | Lucas Moore        | 487    |
| 79769         | Augustine Harkness | 572    |
+---------------+--------------------+--------+
```

1.  IF function in the query below states that *IF the score is equal to or greater than 500, then return “PASSED“. Otherwise, if the score is smaller than 500, return “NOT PASSED”*.

```sql
SELECT name, IF(score>=500, 'PASSED', 'NOT PASSED') FROM test_result; 
```

2.  It will return the following result:&#x20;

```sql
+--------------------+-------------+
| name	             | case        |
+--------------------+-------------+
| Mike Aoki	         | PASSED      |
| Julie Grahams	     | PASSED      |
| Alexandra Jones	 | NOT PASSED  |
| Lucas Moore	     | NOT PASSED  |
| Augustine Harkness | PASSED      |
+--------------------+-------------+
```

### Case #2: IF() with expressions as return value

In the second example, we have another table named “**deptcost**. We want to know which department exceeded the budget and which one did not from the following table.

```sql
CREATE TABLE deptcost (
  dept text,
  budget int,
  actual int,
  status text
);
INSERT INTO deptcost VALUES
('Finance', 800,677,'within budget'),
('HR', 700,930,'over budget'),
('Marketing', 500,677,'over budget'),
('Project', 720,700,'within budget'),
('Sales', 910,860,'within budget');
```

Run the following query to display the table:

```sql
SELECT * FROM deptcost;
```

We have **deptcost** table as seen below:

```sql
+-----------+--------+--------+---------------+
| dept      | budget | actual | status        |
+-----------+--------+--------+---------------+
| Finance   | 800	 | 677	  | within budget |
| HR	    | 700    | 930	  | over budget   |
| Marketing | 500    | 677	  | over budget   |
| Project	| 720    | 700	  | within budget |
| Sales	    | 910	 | 860    | within budget |
+-----------+--------+--------+---------------+
```

1.  The following IF function states that *IF the actual is less than the budget, then return the budget difference, otherwise return 0*.

```sql
SELECT dept, IF(actual < budget, budget - actual, 0) FROM deptcost;
```

2.  We get the following result using the `IF()` function:

```sql
+-----------+-----+
|   dept    |  f  |
+-----------+-----+
| Finance   | 123 |
| HR        |   0 |
| Marketing |   0 |
| Project   |  20 |
| Sales     |  50 |
+-----------+-----+
```


# IS DISTINCT FROM Operator



## **Overview**

The `IS DISTINCT FROM` operator compares two values, considering them distinct even when both are `NULL`. It returns `TRUE` if the two values are different and `FALSE` if they are the same, including the case where both values are `NULL`.&#x20;

## **Syntax**

The syntax for the operator is as follows:

```sql
value1 IS DISTINCT FROM value2
```

Where:

*   `value1` is the first value for comparison.

*   `value2` is the second value for comparison.

## **Examples**

### Case #1: Basic Usage

Consider the following example where we compare two values:

**Example 1**

```sql
SELECT NULL IS DISTINCT FROM NULL AS "Result";
```

The above query will return the following output:

```sql
 Result 
--------
 f
```

**Example 2**

```sql
SELECT 10 IS DISTINCT FROM 20 AS "Result";
```

The above query will return the following output:

```sql
 Result 
--------
 t
```

**Example 3**

```sql
SELECT 10 IS DISTINCT FROM 10 AS "Result";    
```

The above query will return the following output:

```sql
 Result 
--------
 f
```

### Case #2: Comparing NULL Values

In this example, we'll compare `NULL` values using the `IS DISTINCT FROM` operator:

**Example 1**

```sql
SELECT NULL IS DISTINCT FROM 10 AS "Result";  
```

The above query will return the following output:

```sql
 Result 
--------
 t
```

**Example 2**

```sql
SELECT 10 IS DISTINCT FROM NULL AS "Result";
```

The above query will return the following output:

```sql
 Result 
--------
 t
```

### Case #3: Tracking Inventory Variations

Suppose we have a table named `inventory_changes` that tracks changes in the quantities of products in a warehouse. The table has the following structure:

```sql
CREATE TABLE inventory_changes (
  product_id INT,
  change_date DATE,
  change_quantity INT
);

INSERT INTO inventory_changes VALUES
(101, '2023-08-01', 50),
(102, '2023-08-01', 0),
(101, '2023-08-02', -15),
(103, '2023-08-03', 30),
(102, '2023-08-04', 0);
```

We want to retrieve records where the change quantity is distinct from zero. In this scenario, the `IS DISTINCT FROM` operator can be used.

```sql
SELECT *
FROM inventory_changes
WHERE change_quantity IS DISTINCT FROM 0;
```

The result of the query will not include the 0 values as shown below:

```sql
 product_id | change_date | change_quantity 
------------+-------------+-----------------
        101 | 2023-08-01  |              50
        101 | 2023-08-02  |             -15
        103 | 2023-08-03  |              30
```


# IS NOT DISTINCT FROM Operator



## **Overview**

The `IS NOT DISTINCT FROM` operator is a counterpart to `IS DISTINCT FROM`.&#x20;

It compares two values, treating them as equal even when they are both `NULL`. This operator returns `TRUE` if the two values are the same, including the case where both values are `NULL` and `FALSE` if they are different.

## **Syntax**

The syntax for the operator is as follows:

```sql
value1 IS NOT DISTINCT FROM value2
```

Where:

*   `value1` is the first value for comparison.

*   `value2` is the second value for comparison.

## **Examples**

### Case #1: Basic Usage

Consider the following example where we compare two values:

**Example 1**

```sql
SELECT 45 IS NOT DISTINCT FROM 45 AS "Result";  
```

The above query will return the following output:

```sql
 Result 
--------
 t
```

**Example 2**

```sql
SELECT 60 IS NOT DISTINCT FROM 30 AS "Result";    
```

The above query will return the following output:

```sql
 Result 
--------
 f
```

**Example 3**

```sql
SELECT NULL IS NOT DISTINCT FROM NULL AS "Result";
```

The above query will return the following output:

```sql
 Result 
--------
 t
```

### Case #2: Comparing NULL Values

In this example, we'll compare NULL values using the IS NOT DISTINCT FROM operator:

**Example 1**

```sql
SELECT NULL IS NOT DISTINCT FROM 80 AS "Result";   
```

The above query will return the following output:

```sql
 Result 
--------
 f
```

**Example 2**

```sql
SELECT 5 IS NOT DISTINCT FROM NULL AS "Result";
```

The above query will return the following output:

```sql
 Result 
--------
 f
```

### Case #3: Analyzing Data Completeness

Suppose we have a table named customer\_contacts that stores customer contact information.&#x20;

```sql
CREATE TABLE customer_contacts (
  customer_id INT,
  email TEXT,
  phone TEXT
);

INSERT INTO customer_contacts VALUES
(101, 'john@example.com', NULL),
(102, NULL, '+1234567890'),
(103, 'jane@example.com', '+9876543210'),
(104, NULL, NULL),
(105, 'alex@example.com', '+5555555555');
```

Our objective is to retrieve records from this table where an email address or a phone number is available for contacting the customers.

```sql
SELECT *
FROM customer_contacts
WHERE email IS NOT DISTINCT FROM phone;
```

In this query, we retrieve all rows from the `customer_contacts table` where the email and phone are NULL. We can conclude that the customer with `customer_id 104` has no phone number or email address.

```sql
 customer_id | email | phone 
-------------+-------+-------
         104 |       | 
```


# JSON_ARRAY_EXTRACT



## **Overview**

The `JSON_ARRAY_EXTRACT()` function returns the JSON array as a set of JSON values. 

## **Syntax**

The `JSON_ARRAY_EXTRACT()` has the basic syntax as seen below.

```sql
JSON_ARRAY_EXTRACT('json_array'::JSON,id);
```

`JSON_ARRAY_EXTRACT()` requires the following parameters:

*   `json_array`: the array to be extracted.

*   `::JSON`: argument indicating that the query is of type JSON.

*   `id`: ID of the element that we want to extract. It is read in an array format that starts with 0.

### **Another Option**

`JSON_ARRAY_EXTRACT` can also be achieved with the `->` operator, as shown in the syntax below:

```sql
SELECT 'from_json'::JSON -> path;
```

*   `from_json`: the JSON value from which to extract.

*   `::JSON`: a symbol that casts the string literal to a JSON type.

*   `path`: key of the field that we want to extract.

## **Examples**

### **Case #1: Basic JSON\_ARRAY\_EXTRACT() function**

1.  In the below example, we will extract a JSON array as a JSON set.

```sql
SELECT JSON_ARRAY_EXTRACT('["Bougenvile", 2, 12, "Lily"]'::JSON,3);
```

**or**

```sql
SELECT ('["Bougenvile", 2, 12, "Lily"]'::JSON -> 3);
```

2.  The extracted array will look like the following.

```sql
+------------+
| f          |
+------------+
| "Lily"     |
+------------+
```

### Case #2: Extract element of JSON array as text

1.  In this case, we will extract the element of the JSON array as text with the `->>` operator.

```sql
SELECT ('["Bougenvile", 2, 12, "Lily"]'::JSON ->> 1);
```

2.  You will get the final output as follows:

```sql
+------------+
| f          |
+------------+
| 2.000000   |
+------------+
```


# JSON_ARRAY_LENGTH



## **Overview**

The `JSON_ARRAY_LENGTH()` function returns the length of a specified JSON array.

## **Syntax**

This function has the following basic syntax.

```sql
JSON_ARRAY_LENGTH(arrayval JSON)
```

The required argument for this function is `arrayval`. It represents the JSON array which we will count the length.

## **Examples**

### Case #1: Get a JSON array length with a JSON value

The following example returns the number of elements in the array:

```sql
SELECT JSON_ARRAY_LENGTH('[4, 7, 10, 11, 14, {"vegetables":"spinach","fruits":"melon"}, {"a":"b"}]');
```

The function above will return the following result:

```sql
+-------+
| f     |
+-------+
| 7     |
+-------+
```

### Case #2: Get a JSON array length with a number

The following example returns the number of elements in the array.

```sql
SELECT JSON_ARRAY_LENGTH('[1, 2, [3, 4]]');
```

You will get the final result as follows:

```sql
+-------+
| f     |
+-------+
| 3     |
+-------+
```

### Case #3: JSON array length where the array is NULL or empty

This example shows that an empty JSON array will return 0.

```sql
SELECT JSON_ARRAY_LENGTH('[]');
```

An empty array will return 0 in the final output:

```sql
+-------+
| f     |
+-------+
| 0     |
+-------+
```


# JSON_EXTRACT_PATH



## **Overview**

`JSON_EXTRACT_PATH()` function extracts JSON nested value from a specified path.&#x20;

## **Syntax**

The syntax of the `JSON_EXTRACT_PATH()` function can be seen below.

```sql
JSON_EXTRACT_PATH(from_json JSON, path TEXT[])
```

*   `from_json`: the JSON value from which to extract.

*   `path`: the path to extract.

### **Another Option**

Besides the syntax above, Oxla provides and supports the use of operators in queries.  See the syntax below:

```sql
SELECT 'from_json'::JSON -> 'path';
```

*   `from_json`: the JSON value from which to extract.

*   `::JSON`:  a symbol that casts the string literal to a JSON type.

*   `path`: key of the field that we want to extract.

## **Examples**

These examples display how `JSON_EXTRACT_PATH()` extracts the "oxla" JSON sub-object from the specified path.&#x20;

1.  Use the below query:

```sql
SELECT JSON_EXTRACT_PATH('{"f2":{"f3":1},"f4":{"f5":99,"f6":"oxla"}}', 'f4', 'f6');
```

**or**

```sql
SELECT '{"f2":{"f3":1},"f4":{"f5":99,"f6":"oxla"}}'::JSON -> 'f4' -> 'f6';
```

The query above will return the following result.

```sql
+---------+
| f       |
+---------+
| "oxla"  |
+---------+
```

2.  Run the query below:

```sql
SELECT
    JSON_EXTRACT_PATH('{"a": 1, "b": {"x": "subtract", "y": "plus"}}', 'b', 'x') AS "bx",
    JSON_EXTRACT_PATH('{"a": 1, "b": {"x": "multiply", "y": "divide"}}', 'b', 'y') AS "by";
```

You will get the following output:

```sql
+---------------+-------------+
| bx            | by          |
+---------------+-------------+
| "subtract"    | "divide"    |
+---------------+-------------+
```


# JSON_EXTRACT_PATH_TEXT



## **Overview**

The `JSON_EXTRACT_PATH_TEXT()` function extracts JSON nested value from a specified JSON value according to the defined path.&#x20;

<Info>This function may be similar to the `JSON_EXTRACT_PATH()`. This function returns a value of type string instead of type JSON.</Info>

## **Syntax**

The `JSON_EXTRACT_PATH_TEXT()` syntax is shown below:&#x20;

```sql
JSON_EXTRACT_PATH_TEXT(from_json JSON, path TEXT[])
```

The required arguments are explained below.

*   `from_json`: the JSON value to extract.

*   `path`: the path to extract.

### **Another Option**

Besides the syntax above, Oxla provides and supports the use of operators in queries. See the syntax below:

```sql
SELECT 'from_json'::JSON ->> 'path';
```

*   `from_json`: the JSON value from which to extract.

*   `::JSON`: a symbol that casts the string literal to a JSON type.

*   `path`: key of the field that we want to extract.

## **Example**

1.  This example shows how to use the `JSON_EXTRACT_PATH_TEXT()` function to extract values ​​from a JSON object at a specified index.&#x20;

Run the following query:

```sql
SELECT JSON_EXTRACT_PATH_TEXT('{"a": "Oxla", "b": {"x": 1.234, "y": 4.321}}', 'a') AS "result a";
```

**or**

```sql
SELECT '{"a": "Oxla", "b": {"x": 1.234, "y": 4.321}}'::JSON ->> 'a' AS "result a";
```

2.  The `JSON\_EXTRACT\_PATH\_TEXT()` function extracts the values and returns the output below:

```sql
+------------+
| result a   |
+------------+
| "Oxla"     |
+------------+
```


# Overview



To help you query JSON data, Oxla provides some functions that will be used to operate and manipulate the JSON data. The functions are as follows:

| **Functions**                                                                                                                      | **Description**                                                                        |
| ---------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| [JSON\_EXTRACT\_PATH()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-extract-path)﻿           | It extracts JSON sub-object at the specified path.                                     |
| [JSON\_EXTRACT\_PATH\_TEXT()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-extract-path-text) | It returns text referenced by a series of path elements in a JSON string or JSON body. |
| [JSON\_ARRAY\_LENGTH()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-array-length)            | It returns the number of elements in the outer array of a JSON string or JSON body.    |
| [JSON\_ARRAY\_EXTRACT()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-array-extract)          | It returns the JSON array as a set of JSON values.                                     |

Operators are used to specify conditions when using JSON functions. Oxla also supports JSON operators as listed below:

| **Operators** | **Description**                                          | **Example**                                          |
| ------------- | -------------------------------------------------------- | ---------------------------------------------------- |
| ->            | It gets & returns the element of the JSON array.         | `'[{"a":"cab"},{"b":"bac"},{"c":"abc"}]'::json -> 2` |
| ->            | It gets & returns the JSON object field.                 | `'{"a": {"b":"abc"}}'::json -> 'a'`                  |
| ->>           | It gets & returns the element of the JSON array as text. | `'[11,22,33]'::json ->> 2`                           |
| ->>           | It gets & returns the JSON object field as text.         | `'{"a":13,"b":33}'::json ->> 'b'`                    |


# COALESCE



## **Overview**

A table can hold empty (null) and filled (non-null) values. Yet, often, we prefer to overlook those empty values. This is where `COALESCE()` steps in.

`COALESCE()` function helps us when we want to ignore null values while processing data. It returns the first argument that is not null, while the remaining arguments from the first non-null argument are not evaluated.

<Info>If all arguments are null, the COALESCE function will return null.</Info>

## **Syntax**

The syntax for the `COALESCE()` function is as follows:

```sql
COALESCE (argument_1, argument_2, …);
```

Key points from the syntax:

*   `COALESCE()` requires a minimum of two inputs.

*   It can take an unlimited number of arguments.

*   Evaluation occurs sequentially from left to right, stopping at the first non-null value.

## **Examples**

Here are some examples to illustrate the application of `COALESCE()`:

### Case #1: **Returning the First Non-Null Value**

In this example, we have a set of values. By using the `COALESCE()` function, we're going to get the first non-null value from this set.

```sql
SELECT COALESCE(9, 3, 8, 7, 1);
```

The result will be `9`, the first value without null among the provided options.

```sql
 coalesce 
----------
        9
```

### Case #2: **Handling NULL Value as the Last Argument**

Let's include NULL as the final argument and check the query output.

```sql
Select COALESCE(3,4,5,9,10,NULL);
```

&#x20;The function output is `3` because it returns the first non-null value.

```sql
 coalesce 
----------
        3
```

### Case #3: **Handling NULL Value as the First Argument**

Consider NULL as the first argument in the following example.

```sql
Select COALESCE(NULL,1,5,7,9,2);
```

The output is `1`, as it is the first non-null value of the argument.

```sql
 coalesce 
----------
        1
```

### Case #4: **Handling Multiple NULL Values**

In the following query, NULL appears in the first, second, fourth, and last positions.

```sql
Select COALESCE(NULL, NULL ,3, NULL, 7,9,4,5, NULL);
```

The `COALESCE()` function ignores the first two NULLs and returns the first non-null value, `3`. It does not process the subsequent NULL values.

```sql
 coalesce 
----------
        3
```

### Case #5: **Handling All NULL Values**

Assume that the given values are entirely composed of nulls.

```sql
Select COALESCE(NULL, NULL ,NULL, NULL);
```

In this case, the `COALESCE()` function returns an empty value (null).

```sql
 coalesce 
----------
 
```

### Case #6: `COALESCE()`\*\* with Table Data\*\*

Imagine we have the `employee_absent` table, which comprises a mix of NULL and non-null values:

```sql
CREATE TABLE employee_absent (
    emp_name TEXT,
    emp_dept TEXT,
    absent TEXT
);

INSERT INTO employee_absent (emp_name, emp_dept, absent)
VALUES
    ('Alice', 'Finance', 'absent'),
    ('Bob', 'Operations', 'absent'),
    ('Carol', 'Finance', 'absent'),
    ('David', 'HR', NULL),
    ('Emily', 'HR', NULL);
```

Use the `SELECT` statement to display all the records:

```sql
SELECT * FROM employee_absent;
```

```sql
 emp_name |  emp_dept  | absent 
----------+------------+--------
 Alice    | Finance    | absent
 Bob      | Operations | absent
 Carol    | Finance    | absent
 David    | HR         | 
 Emily    | HR         | 
```

The query below uses the `COALESCE()` function on the `absent` column. It retrieves names and absences (with `out of office` for NULL values) for each employee.

```sql
SELECT emp_name, COALESCE(absent, 'out of office') AS DisplayAbsent FROM employee_absent;
```

```sql
 emp_name | displayabsent 
----------+---------------
 Alice    | absent
 Bob      | absent
 Carol    | absent
 David    | out of office
 Emily    | out of office
```

### Case #7: Error Output in `COALESCE()`

When specifying arguments with different datatypes, they should be convertible.&#x20;

```sql
Select Coalesce ('x',NULL,1);
```

If the datatypes cannot be converted, the `COALESCE()` function will generate an error, as shown below.

```sql
ERROR:  invalid input syntax for type integer: "x"
```


# CURRENT_DATABASE



## **Overview**

The `CURRENT_DATABASE()` returns the current database's name.&#x20;

## **Syntax**

The following syntax describes `CURRENT_DATABASE()` function.

```sql
SELECT CURRENT_DATABASE();
```

It does not require any argument to operate.

## **Example**

In the following example, we will obtain the database name to which we are currently connected. 

```sql
SELECT CURRENT_DATABASE();
```

The function will return the result with the database name:

```sql
+------------+
| f          |
+------------+
| Oxla       |
+------------+
```


# CURRENT_SCHEMA



## **Overview**

The `CURRENT_SCHEMA()` function returns the name of the first existing schema.

<Info>It will return NULL if none of the schemas from `search_path` exist. </Info>

## **Syntax**

`CURRENT_SCHEMA()` function has the following syntax:

```sql
SELECT CURRENT_SCHEMA();
```

Another method is to omit the parenthesis from the above syntax.

```sql
SELECT CURRENT_SCHEMA;
```

<Info>It does not require any argument to operate.</Info>

## **Example**

The following example shows how to get the current schema name using `CURRENT_SCHEMA()` function.

```sql
SELECT CURRENT_SCHEMA();
```

The final result will display the schema that you currently use:

```sql
+------------+
| f          |
+------------+
| public     |
+------------+
```


# HAS_SCHEMA_PRIVILEGE



## **Overview**

The `has_schema_privilege` function checks whether the current user has specific privileges on a schema.&#x20;

## **Syntax**

There are two versions of the `has_schema_privilege` function:

<CodeGroup>
  ```sql Version 1
  SELECT has_schema_privilege('user', 'schema', 'privilege');
  ```

  ```sql Version 2
  SELECT has_schema_privilege('schema', 'privilege');
  ```
</CodeGroup>

See the breakdown of both versions:

*   `schema`: The name of the schema for which you want to check privileges. It can be any string value or string columns from other tables.

*   `user`: The name of the user who has the privileges. It can be any string value.

*   `privilege`: The privilege parameter specifies the specific privilege you want to check for in the schema. Currently, the function supports `create` and `usage`.&#x20;

The comparison for the `privilege` is case-insensitive, so you can use lowercase or uppercase letters for the privilege name (e.g., `CREATE` or `create` are both valid).

## **Output**

Both versions of the `has_schema_privilege` function will always return a `TRUE (t)` value.

## **Examples**

### Case #1: Check for CREATE Privilege

In this example, we will use the `has_schema_privilege` function to determine if the current user has the `create` privilege on a schema named "public."

```sql
SELECT has_schema_privilege('public', 'create');
```

This query will return `TRUE`, which means the current user has a `create` privilege on the "public" schema.

```sql
 has_schema_privilege 
----------------------
 t
```

### Case #2: Check for USAGE Privilege

You can also use the `has_schema_privilege` function to check for the `usage` privilege on a schema. For example, to check if the current user can create objects in the "public" schema:

```sql
SELECT has_schema_privilege('cahyo', 'public', 'USAGE');
```

This query will return `TRUE`, which means the current user has usage privilege on the "public" schema.

```sql
 has_schema_privilege 
----------------------
 t
```


# NULLIF



## **Overview**

The `NULLIF()` function allows us to replace a given value with null if it matches a specific criterion.&#x20;

## **Syntax**

The following illustrates the syntax of the `NULLIF` function:

```sql
NULLIF(argument_1,argument_2);
```

From the syntax above, we learn that the `NULLIF` function takes two arguments:

*   The first argument is the value we want to evaluate.

*   The second argument is the value we want to treat as null if the first argument matches it.

<Tip>**The Output**: <br /> If the first argument matches the second argument, the `NULLIF()` function returns **NULL**. Otherwise, it returns the first argument as-is.</Tip>

## **Examples**

### Case #1: Handling Equal Values

In this case, the `NULLIF` function is used to compare the values 4 and 4.&#x20;

```sql
SELECT NULLIF (4, 4);
```

The result will be `NULL` since the two values being compared are equal (4 = 4).

```sql
 if 
----
   
```

### Case #2: Handing Different Values

In this example, we want to use the `NULLIF` function to manage different values.&#x20;

```sql
SELECT NULLIF (9, 0);
```

The result will be `9` because the second value in the `NULLIF` function is 0 (The two values are not equal).

```sql
 if 
----
  9
```

### Case #3: String Comparison

In this case, the `NULLIF` function compares the strings 'L' and 'O'.&#x20;

```sql
SELECT NULLIF ('L', 'O');
```

The result will be `L` because the two strings being compared ('L' and 'O') are not equal. Therefore, the function returns the first string.

```sql
 if 
----
 L
```

### Case #4: **Handling Default Values**

Suppose we have an `employees` table with columns for `name` and `salary`. This query retrieves employee names and their adjusted salaries, where a salary of 0 is replaced with NULL:

```sql
CREATE TABLE employees (
    name TEXT,
    salary INT
);

INSERT INTO employees (name, salary)
VALUES
    ('John', 50000),
    ('Jane', 0),
    ('Roy', 0),
    ('NEil', 0),
    ('Michael', 75000);
```

Display the records of the table:

```sql
SELECT * FROM employees;
```

```sql
  name   | salary 
---------+--------
 John    |  50000
 Jane    |      0
 Roy     |      0
 NEil    |      0
 Michael |  75000
```

This query retrieves employee names and their adjusted salaries, where a salary of 0 is replaced with NULL:

```sql
SELECT name, NULLIF(salary, 0) AS adjusted_salary
FROM employees;
```

The `NULLIF` function checks if the `salary` value is 0. If it is, the function returns NULL - otherwise, it returns the original `salary` value.&#x20;

```sql
  name   | adjusted_salary 
---------+-----------------
 John    |           50000
 Jane    |                
 Roy     |                
 NEil    |                
 Michael |           75000
```

### Case #5: **Avoiding Division by Zero**

Suppose we have a `fractions` table with columns, a `numerator` and a `denominator`.&#x20;

```sql
CREATE TABLE fractions (
    numerator INT,
    denominator INT
);

INSERT INTO fractions (numerator, denominator)
VALUES
    (10, 2),
    (20, 0),
    (15, 3),
    (75, 0),
    (15, 3);
```

Display the table using the `SELECT` statement:

```sql
SELECT * FROM fractions;
```

```sql
 numerator | denominator 
-----------+-------------
        10 |           2
        20 |           0
        15 |           3
        75 |           0
        15 |           3
```

Here, the `NULLIF` function is applied to the `denominator` column. If the `denominator` is 0, the function returns NULL, avoiding division by zero.

```sql
SELECT numerator, denominator, numerator / NULLIF(denominator, 0) AS "result" FROM fractions;
```

The result is shown in the result column.&#x20;

```sql
 numerator | denominator | result 
-----------+-------------+--------
        10 |           2 |      5
        20 |           0 |       
        15 |           3 |      5
        75 |           0 |       
        15 |           3 |      5
```


# Overview



Besides the timestamp, string, and numeric functions, we also provide other functions that can be used to support the use of our database. The functions are as follows:

| **Functions**                                                                                                                           | **Description**                                                                                                                   |
| --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [CURRENT\_SCHEMA()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/current-schema)﻿                      | It returns the schema's name first in the search path.                                                                            |
| [CURRENT\_DATABASE()](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/current-database)                   | It returns the current database's name.                                                                                           |
| [**NULLIF()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/nullif)                                    | It replaces a given value with null if it matches a specific criterion.                                                           |
| [**COALESCE()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/coalesce)                                | It returns the first argument that is not null, while the remaining arguments from the first non-null argument are not evaluated. |
| [**pg\_total\_relation\_size()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/pg-total-relation-size) | It retrieves the size of a table.                                                                                                 |
| [**has\_schema\_privilege()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/has-schema-privillege)     | It checks whether the current user has specific privileges on a schema.                                                           |
| [**pg\_get\_expr()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/pg-get-expr)                        | It retrieves the internal form of an individual expression, such as the default value for a column.                               |
| [**pg\_typeof()**](https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/pg-typeof)                             | It retrieves the data type of any given value.                                                                                    |


# PG_GET_EXPR



## **Overview**

The `pg_get_expr` function retrieves the internal form of an individual expression, such as the default value for a column.

## **Syntax**

There are two versions of the `pg_get_expr` function:

<CodeGroup>
  ```sql Version 1
  SELECT pg_get_expr('expr_text', relation_oid);
  ```

  ```sql Version 2
  SELECT pg_get_expr('expr_text', relation_oid, pretty_bool);
  ```
</CodeGroup>

Please see the breakdown of both versions:

*   `expr_text`: The expression for which you want to obtain the internal representation. It can be any string value.

*   `relation_oid`: The OID (Object Identifier) of the table the expression belongs to. It is in integer type.

*   `pretty_bool`: A boolean value determining whether to format the expression in a more human-readable format (TRUE) or not (FALSE).&#x20;

## **Output**

Both versions of the `pg_get_expr` function return an empty string `""`.

## **Example**

1.  First, create a sample table named **employees.**

```sql
CREATE TABLE employees (
    id INT,
    name TEXT,
    salary TEXT
);
```

2.  Get OID of the table.

```sql
SELECT oid FROM pg_class WHERE relname = 'employees';
```

You will get the OID of the table:

```sql
 oid  
------
 1018
```

3.  Retrieve the internal form for the `salary` column using `pg_get_expr`.

```sql
-- Version 1
SELECT pg_get_expr('salary', 1018);

-- Version 2
SELECT pg_get_expr('salary', 1018, TRUE);
```

Both return the same value, an empty string `""`.

```sql
 pg_get_expr 
-------------
 
```


# PG_TOTAL_RELATION_SIZE



## **Overview**

The `pg_total_relation_size` function allows you to retrieve the size of a table. This function is useful for monitoring the storage requirements.

## **Syntax**

The syntax for the `pg_total_relation_size` function is as follows:

```sql
pg_total_relation_size('relation_name');
```

Here, relation\_name is the name of the table for which you want to determine the size.

## **Output**

The `pg_total_relation_size` function returns the size of the specified table in bytes.

## **Example**

1.  First, let’s assume we have a table named \*\*users. \*\*Use the below query to create the table.

```sql
CREATE TABLE users (
    username TEXT,
    email TEXT
);
INSERT INTO users (username, email) VALUES
    ('john_doe', 'john.doe@example.com'),
    ('jane_smith', 'jane.smith@example.com'),
    ('alice_smith', 'alice.smith@example.com'),
    ('bob_jones', 'bob.jones@example.com'),
    ('susan_wilson', 'susan.wilson@example.com'),
    ('michael_jackson', 'michael.jackson@example.com'),
    ('lisa_johnson', 'lisa.johnson@example.com'),
    ('david_smith', 'david.smith@example.com');
```

2.  In this case, we will use the `pg_total_relation_size` function to determine the size of a **users** table.

```sql
SELECT pg_total_relation_size('users');
```

3.  This query will return the size of the **users** table in bytes.

```sql
 pg_total_relation_size 
------------------------
                    556
```


# PG_TYPEOF



## **Overview**

The `pg_typeof()` function allows you to retrieve the data type of any given value. It returns a string literal corresponding to the expression type.

## **Syntax**

The syntax of the `pg_typeof()` function is:

```sql
SELECT pg_typeof("any");
```

Here, any represents any value you want to determine the data type.

## **Example**

### Case #1: Type of Numeric

This case shows a basic example with a numeric value:

```sql
SELECT pg_typeof(100) as "data type";
```

It will return its data type, which is “integer”.

```sql
 data type 
-----------
 integer
```

### Case #2: Type of String

Here, we will use a string value as an input:

```sql
SELECT pg_typeof('event'::TEXT) as "data type";
```

It will return its data type, which is “text”.

```sql
 data type 
-----------
 text
```

### Case #3: Type of Interval

Another example is using an interval input:

```sql
SELECT pg_typeof(INTERVAL '1 day') as "data type";
```

It will return its data type in string literal.

```sql
 data type 
-----------
 interval
```

### Case #4: Work with Table

Suppose you have a sample table and want to use `pg_typeof()` to retrieve their data types.

1.  Create the table and insert some data into the table.

```sql
CREATE TABLE timestamp_example (
    id int,
    event_time timestamp,
    description text
);

INSERT INTO timestamp_example (event_time, description)
VALUES 
  ('2023-10-20 12:30:00', 'Event 1'),
  (NULL, 'Event 2');
```

2.  Now, use `pg_typeof()` to determine the data types of the event\_time and description columns for each row.

```sql
SELECT 
    pg_typeof(event_time) AS event_time_type,
    pg_typeof(description) AS description_type
FROM timestamp_example;
```

3.  The result will show that the data type of the event\_time column is a timestamp, and the data type of the description column is text:

```sql
       event_time_type       | description_type 
-----------------------------+------------------
 timestamp without time zone | text
 timestamp without time zone | text
```


# Overview



## What is a Function?

A function *(also known as stored procedures)* is a set of procedural operations stored in the database to carry out processes that usually take several queries; now, it only uses one single function.

***

In this section, we will understand how functions work in Oxla, how to create a function command and its input/return types and see examples of calling the function.

These are the functions that Oxla supports:

<CardGroup cols={4}>
  <Card title="Numeric Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-1-numeric-functions/numeric-functions">
    Learn more
  </Card>

  <Card title="Aggregate Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-2-aggregation-functions/aggregation-functions">
    Learn more
  </Card>

  <Card title="String Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-3-string-functions/string-functions">
    Learn more
  </Card>

  <Card title="Timestamp Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-4-timestamp-functions/timestamp-functions">
    Learn more
  </Card>

  <Card title="Boolean Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-5-boolean-functions/boolean-functions">
    Learn more
  </Card>

  <Card title="JSON Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-6-json-functions/json-functions">
    Learn more
  </Card>

  <Card title="Other Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/3-4-7-other-functions/other-function">
    Learn more
  </Card>

  <Card title="Trigonometric Functions" href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/trigonometric-functions">
    Learn more
  </Card>
</CardGroup>


# Trigonometric Functions



These trigonometric functions in Oxla take arguments and return values of type `double precision` and `real`.

| **Functions** | **Description**                                                                                  | **Syntax**                                                                    | **Example**                                                |
| ------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `acos`        | It calculates the inverse cosine of a given argument, where the output is expressed in radians.  | `acos(argument)`                                                              | `select acos(1);` It will return: `0`                      |
| `acosd`       | It calculates the inverse cosine of a given argument, where the output is expressed in degrees.  | `acosd(argument)`                                                             | `select acosd(0.5);` It will return: `60`                  |
| `asin`        | It calculates the inverse sine of a given argument, where the output is expressed in radians.    | `asin(argument)`                                                              | `select asin(1);` It will return: `1.5707963267948966`     |
| `asind`       | It calculates the inverse sine of a given argument, where the output is expressed in degrees.    | `asind(argument)`                                                             | `select asind(0.5);` It will return: `30`                  |
| `atan`        | It calculates the inverse tangent of a given argument, where the output is expressed in radians. | `atan(argument)`                                                              | `select atan(1);` It will return: `0.7853965`              |
| `atand`       | It calculates the inverse tangent of a given argument, where the output is expressed in degrees. | `atand(argument)`                                                             | `select atand(1);` It will return: `44.99990469434657`     |
| `atan2`       | It calculates the inverse tangent of y/x, where the output is expressed in radians.              | `atan2(y_value, x_value)``y_value` & `x_value` are in double precision type.  | `select atan2(1, 0);` It will return: `1.5707963267948966` |
| `atan2d`      | It calculates the inverse tangent of y/x, where the output is expressed in degrees.              | `atan2d(y_value, x_value)``y_value` & `x_value` are in double precision type. | `select atan2d(1, 0);` It will return: `90`                |
| `cos`         | It calculates the cosine of a given argument, where the argument is in radians.                  | `cos(argument)`                                                               | `select cos(0);` It will return: `1`                       |
| `cosd`        | It calculates the cosine of a given argument, where the argument is in degrees.                  | `cosd(argument)`                                                              | `select cosd(60);` It will return: `0.5000000000000001`    |
| `cot`         | It calculates the cotangent of a given argument, where the argument is in radians.               | `cot(argument)`                                                               | `select cot(0.5);` It will return: `1.8304877`             |
| `cotd`        | It calculates the cotangent of a given argument, where the argument is in degrees.               | `cotd(argument)`                                                              | `select cotd(45);` It will return: `1.0000000000000002`    |
| `sin`         | It calculates the sine of a given argument, where the argument is in radians.                    | `sin(argument)`                                                               | `select sin(1);` It will return: `0.8414709848078965`      |
| `sind`        | It calculates the sine of a given argument, where the argument is in degrees.                    | `sind(argument)`                                                              | `select sind(30);` It will return: `0.49999999999999994`   |
| `tan`         | It calculates the tangent of a given argument, where the argument is in radians.                 | `tan(argument)`                                                               | `select tan(1);` It will return: `1.5574077246549023`      |
| `tand`        | It calculates the tangent of a given argument, where the argument is in degrees.                 | `tand(argument)`                                                              | `select tand(45);` It will return: `0.9999999999999999`    |


# Comment Support



## Overview

OXLA fully supports comments in your queries. Comments provide a way to add explanatory notes and improve the readability of queries, making it easier for developers and stakeholders to understand complex queries.&#x20;

There are two types of comments in OXLA: **single-line** and **multi-line (block)**.

## Single Line Comments

A single-line comment in OXLA starts with two consecutive hyphens (--) and extends to the end of the line. These comments are used to annotate specific parts of a query, providing brief explanations or notes to assist in understanding the query.

**Syntax:**

```sql
-- This is an example single line comment
```

## Multi-Line (Block) Comments

OXLA also supports multi-line comments, often referred to as block comments. These comments begin with /\* and end with \*/, allowing for multi-line explanations or temporarily disabling sections of the query.

**Syntax:**

```sql
/*
This is an example multi-line comment.
It can span multiple lines and is useful for providing detailed explanations.
*/
```

## Comment Placement

In OXLA, single-line comments should always be placed at the end of the line they refer to, whereas multi-line comments can be positioned anywhere within the query.&#x20;

**Example - Comment on Single Line:**

```sql
SELECT column1, column2 -- This is an example single line comment
FROM table_name;
```

**Example - Comment on Multiple Lines:**

```sql
SELECT /* comment 1 */ column1, column2
FROM table_name /* comment 2 */
WHERE column3 = 42 /* comment 3 */ ;
```

## Best Practices for Commenting

To maximize the benefits of comments in OXLA queries, follow these best practices:

<CardGroup cols={2}>
  <Card title="Be Concise" icon="square-1">
    Write clear and concise comments that provide meaningful insights into the specific parts of the query.
  </Card>

  <Card title="Update Comments During Code Changes" icon="square-2">
    Whenever the query is modified, update the associated comments to reflect the changes accurately.
  </Card>

  <Card title="Avoid Over-Commenting" icon="square-3">
    While comments are helpful, excessive commenting can clutter the code and reduce.
  </Card>
</CardGroup>


# Schema



# **What is Schema?**

Have you ever wondered how to work with your fellows in one database without interfering with each other? Is it possible to organize the database objects into logical groups which do not collide with the other objects' names?

We can do those things with **Schema**.&#x20;

A **schema** is a collection of tables. A schema also contains views, indexes, sequences, data types, operators, and functions. We support multiple schemas. For example, you can have a database named `oxla` and have multiple schemas based on your needs, like `auth`, `model`, `business`, etc.

![](https://archbee-image-uploads.s3.amazonaws.com/S_lGBDD7H53z1OcF8Kc79/dwZKCnYfbiCnec6P1XYsK_schema.png)

# **Default Schema in Oxla**

By default, the `public` schema is used in Oxla.&#x20;

When unqualified `table_name` is used, that `table_name` is equivalent to `public.table_name`. It also applies to `CREATE`, `DROP`, and `SELECT TABLE` statements.

<Info>Furthermore, you can create multiple schemas per your needs.</Info>

# **Schema Usage Scenarios**

## **#1 - Create a Schema**

The basic syntax of creating a schema is as follows:

```sql
CREATE SCHEMA [IF NOT EXISTS] schema_name;
```

*   `schema_name` is the schema name you are going to create.
*   `IF NOT EXISTS` is an optional parameter to avoid errors if the schema already exists.

## **#2 - Create a Table in Schema**

The syntax to create a table in a specified schema is as follows:

```sql
CREATE TABLE schema_name.table_name(
...
);
```

*   `schema_name` is the schema that you have created.

*   `table_name` is the table name you are going to create.

## **#3 - Select a Table in Schema**

After creating the table and inserting some data, display all rows with the syntax below:&#x20;

```sql
SELECT * FROM schema_name.table_name;
```

*   `schema_name` is the name of the schema.

*   `table_name` is the name of the table you want to display.

## **#4 - Drop the Schema**

**Option 1**: To drop an empty schema where no objects remain in it, use the command below:

```sql
DROP SCHEMA [IF EXISTS] schema_name;
```

*   `schema_name` is the schema name you are going to create.
*   `IF EXISTS` is an optional parameter to avoid errors if the schema does not exist.

**Option 2**: Tables reside in a schema, so it is impossible to drop a schema without also dropping the tables. With the command below, you will also drop the schema with the tables.

```sql
DROP SCHEMA schema_name CASCADE;
```

# Examples

## Example #1: Creating Schema

1.  First, connect to Oxla and create a schema as shown below:

```sql
CREATE SCHEMA oxlarefs;
```

2.  Next, create a table in the above schema with the following details:

```sql
CREATE TABLE oxlarefs.functions(
  id int,
  function_name string,
  active bool
);

INSERT INTO oxlarefs.functions(id, function_name, active)
VALUES 
('1111', 'Numeric', 'TRUE'),
('2222', 'String', 'TRUE'),
('3333', 'Timestamp', 'TRUE'),
('4444', 'JSON', 'TRUE'),
('5555', 'Boolean', 'TRUE');
```

3.  You can verify and show the table made with the command below:

```sql
SELECT * FROM oxlarefs.functions;
```

4.  You will get the following result:

```sql
+------+---------------+---------+
| id   | function_name | active  |
+------+---------------+---------+
| 1111 | Numeric       | t       |
| 2222 | String        | t       |
| 3333 | Timestamp     | t       |
| 4444 | JSON          | t       |
| 5555 | Boolean       | t       |
+------+---------------+---------+
```

## Example #2: Creating Schema Using IF NOT EXISTS

To avoid errors when the schema already exists, use the `IF NOT EXISTS` option. Here is how it works:

### Example without IF NOT EXISTS

1.  First, create the schema without using the `IF NOT EXISTS` option.

```sql
CREATE SCHEMA oxladb;
```

Output:

```sql
CREATE SCHEMA
```

2.  If you attempt to create the schema again without using `IF NOT EXISTS`, it will result in an error.

```sql
CREATE SCHEMA oxladb;
```

Output:

```sql
ERROR:  Schema: oxladb already exists
```

### Example with IF NOT EXISTS

Now, create the schema using the `IF NOT EXISTS` option to avoid the error.

```sql
CREATE SCHEMA IF NOT EXISTS oxladb;
```

Using `IF NOT EXISTS` allows the query to create a schema even if it already exists.

```sql
CREATE
```

## Example #3: Dropping Schema

Use the command below to delete the schema and also the tables in it.

```sql
DROP SCHEMA oxlarefs CASCADE;
```

Another case is if there is no table or object created inside the schema, you can use the following command to drop the schema.

```sql
DROP SCHEMA oxlarefs;
```

## Example #4: Dropping Schema using IF EXISTS

### Example without IF EXISTS

1.  First, drop the schema without using the `IF EXISTS` option.

```sql
DROP SCHEMA oxladb;
```

Output:

```sql
DROP
```

2.  If you attempt to drop the schema again without using `IF EXISTS`, it will result in an error.

```sql
DROP SCHEMA oxladb;
```

Output:

```sql
ERROR:  schema "oxladb" does not exist
```

### Example with IF EXISTS

Now, drop the schema using the `IF EXISTS` option.

```sql
DROP SCHEMA IF EXISTS oxladb;
```

Using `IF` EXISTS allows the query to succeed even if the schema does not exist.

```sql
DROP
```


# Overview



This section provides information about the syntax and semantics of SQL queries, clauses, data types, and functions that Oxla supports. The information in this section is divided into groups according to the kind of operation they perform as follows:

<CardGroup cols={3}>
  <Card
    title="SQL Statements"
    icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 144.9 145.97">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <g class="cls-1">
             <path
               class="cls-2"
               d="M91.94,106.25a2,2,0,0,1-2-2V73.36A5.35,5.35,0,0,0,84.6,68H51.87a2,2,0,1,1,0-4H84.6a9.35,9.35,0,0,1,9.34,9.34v30.89A2,2,0,0,1,91.94,106.25Z"
             />
           </g>
           <g class="cls-1">
             <path
               class="cls-2"
               d="M69.9,96a7.94,7.94,0,1,1,7.94-7.94A7.95,7.95,0,0,1,69.9,96Zm0-11.88a3.94,3.94,0,1,0,3.94,3.94A3.95,3.95,0,0,0,69.9,84.14Z"
             />
           </g>
           <path d="M87.36,22.33a2,2,0,0,1-2-2V5.52A1.52,1.52,0,0,0,83.84,4H5.52A1.52,1.52,0,0,0,4,5.52V20.33a2,2,0,0,1-4,0V5.52A5.53,5.53,0,0,1,5.52,0H83.84a5.53,5.53,0,0,1,5.52,5.52V20.33A2,2,0,0,1,87.36,22.33Z" />
           <path d="M2,51.37a2,2,0,0,1-2-2V34.56A5.53,5.53,0,0,1,5.52,29H83.84a5.53,5.53,0,0,1,5.52,5.52V47.24a2,2,0,0,1-4,0V34.56A1.52,1.52,0,0,0,83.84,33H5.52A1.52,1.52,0,0,0,4,34.56V49.37A2,2,0,0,1,2,51.37Z" />
           <path d="M2,80.42a2,2,0,0,1-2-2V63.61a5.53,5.53,0,0,1,5.52-5.52H45a2,2,0,0,1,0,4H5.52A1.52,1.52,0,0,0,4,63.61V78.42A2,2,0,0,1,2,80.42Z" />
           <path d="M84.62,126.1A40.36,40.36,0,0,1,56,114.29h0a40.5,40.5,0,0,1,0-57.18,40.43,40.43,0,0,1,57.19,0,40.42,40.42,0,0,1-28.59,69ZM58.85,111.45A36.44,36.44,0,1,0,84.62,49.24h0a36.44,36.44,0,0,0-25.77,62.21Z" />
           <path d="M142.9,146a2,2,0,0,1-1.41-.59l-31.09-31.1a2,2,0,0,1,2.82-2.82l31.09,31.1A2,2,0,0,1,142.9,146Z" />
         </g>
       </g>
     </svg>}
    href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/sql-statement-overview"
  >
    Learn how to create a request for data or information from one or more database tables using our supported statements.
  </Card>

  <Card
    title="SQL Clauses"
    icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142.87 143.38">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path d="M84.35,123.92H6a6,6,0,0,1-6-6V6A6,6,0,0,1,6,0H93.92a6,6,0,0,1,6,6V57.92a2,2,0,0,1-4,0V6a2,2,0,0,0-2-2H6A2,2,0,0,0,4,6V117.92a2,2,0,0,0,2,2H84.35a2,2,0,0,1,0,4Z" />
           <path d="M97.79,143.38a2,2,0,0,1-.82-.18,2,2,0,0,1-1.18-1.82l0-33a3.32,3.32,0,0,0-1.35-2.69L73.75,90.12a7.39,7.39,0,0,1-2.94-5.88V73.34A5.38,5.38,0,0,1,76.19,68h61.3a5.38,5.38,0,0,1,5.38,5.38v10.9a7.39,7.39,0,0,1-2.94,5.88L119.2,105.66a3.36,3.36,0,0,0-1.34,2.68v17a2,2,0,0,1-.67,1.49L99.12,142.87A2,2,0,0,1,97.79,143.38ZM76.19,72a1.38,1.38,0,0,0-1.38,1.38v10.9a3.36,3.36,0,0,0,1.34,2.68l20.72,15.54a7.32,7.32,0,0,1,2.94,5.89l0,28.57,14.07-12.51V108.34a7.39,7.39,0,0,1,2.94-5.88l20.73-15.54a3.32,3.32,0,0,0,1.34-2.68V73.34A1.38,1.38,0,0,0,137.49,72Z" />
           <path
             class="cls-1"
             d="M83.85,28H16.06a2,2,0,1,1,0-4H83.85a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M67.47,99.92H16.06a2,2,0,1,1,0-4H67.47a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M83.85,52H16.06a2,2,0,1,1,0-4H83.85a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M58.81,76H16.06a2,2,0,1,1,0-4H58.81a2,2,0,0,1,0,4Z"
           />
         </g>
       </g>
     </svg>}
    href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/sql-clauses-overview"
  >
    This sub-section show you how to write user-friendly queries and analyze data using different
    constraints and conditions.
  </Card>

  <Card
    title="SQL Data Types"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 148.23 144.14">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path d="M33.16,140.27A30.88,30.88,0,1,1,64,109.39,30.91,30.91,0,0,1,33.16,140.27Zm0-57.76A26.88,26.88,0,1,0,60,109.39,26.91,26.91,0,0,0,33.16,82.51Z" />
           <path d="M139.6,56.32H87.78a2,2,0,0,1-2-2V2.5a2,2,0,0,1,2-2H139.6a2,2,0,0,1,2,2V54.32A2,2,0,0,1,139.6,56.32Zm-49.82-4H137.6V4.5H89.78Z" />
           <path
             class="cls-1"
             d="M113.7,144.14a2,2,0,0,1-1.42-.58L79.75,111a2,2,0,0,1,0-2.83l32.53-32.53a2,2,0,0,1,2.83,0l32.54,32.53a2,2,0,0,1,0,2.83l-32.54,32.54A2,2,0,0,1,113.7,144.14ZM84,109.61l29.71,29.7,29.7-29.7L113.7,79.9Z"
           />
           <path d="M63,56.81H2a2,2,0,0,1-1.73-3L30.76,1a2,2,0,0,1,3.46,0L64.71,53.81a2,2,0,0,1-1.73,3Zm-57.52-4H59.52L32.49,6Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/data-types-overview"
  >
    This sub-section will guide you through implementing our supported data types to run your operations, such as string, timestamp, numeric, and many more…💨
  </Card>

  <Card
    title="SQL Functions"
    icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 125.77 134.57">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path
             class="cls-1"
             d="M62.88,71.38A2,2,0,0,1,61.69,71a39.66,39.66,0,0,1,0-62.58,1.94,1.94,0,0,1,2.39,0,39.68,39.68,0,0,1,0,62.58A2,2,0,0,1,62.88,71.38Zm0-59a35.79,35.79,0,0,0,0,54.52,35.79,35.79,0,0,0,0-54.52Z"
           />
           <path d="M86.09,79.36a1.94,1.94,0,0,1,0-3.88,35.8,35.8,0,0,0,0-71.6,35.43,35.43,0,0,0-22,7.58l-1.19.93-1.19-.93a35.43,35.43,0,0,0-22-7.58,35.8,35.8,0,1,0,0,71.6,35.43,35.43,0,0,0,22-7.58L62.88,67l1.19.93a36.39,36.39,0,0,0,4.51,3,1.94,1.94,0,0,1-1.89,3.39,40,40,0,0,1-3.81-2.43,39.25,39.25,0,0,1-23.2,7.5A39.68,39.68,0,1,1,39.69,0a39.25,39.25,0,0,1,23.2,7.5A39.27,39.27,0,0,1,86.09,0a39.68,39.68,0,0,1,0,79.36Z" />
           <path d="M54,134.57H48.89a1.94,1.94,0,1,1,0-3.88H54a8.08,8.08,0,0,0,7.83-6.07L74.94,73.93a12,12,0,0,1,11.59-9h5.09a1.94,1.94,0,0,1,0,3.88H86.53A8.08,8.08,0,0,0,78.7,74.9L65.57,125.6A12,12,0,0,1,54,134.57Z" />
           <path d="M79,101.7H61.48a1.94,1.94,0,0,1,0-3.88H79a1.94,1.94,0,0,1,0,3.88Z" />
           <path d="M110.45,123.33a1.94,1.94,0,0,1-1.37-.57L95,108.64a1.94,1.94,0,0,1,2.74-2.74L111.82,120a1.94,1.94,0,0,1-1.37,3.31Z" />
           <path d="M96.33,123.33A1.94,1.94,0,0,1,95,120l14.12-14.12a1.94,1.94,0,0,1,2.74,2.74L97.7,122.76A1.92,1.92,0,0,1,96.33,123.33Z" />
           <path d="M90.11,132.16a1.9,1.9,0,0,1-1.45-.66,25.88,25.88,0,0,1,0-34.33,1.94,1.94,0,1,1,2.9,2.58,22,22,0,0,0,0,29.19,1.94,1.94,0,0,1-1.45,3.22Z" />
           <path d="M116.66,132.16a1.9,1.9,0,0,1-1.28-.49,1.92,1.92,0,0,1-.17-2.73,22,22,0,0,0,0-29.19,1.94,1.94,0,1,1,2.9-2.58,25.88,25.88,0,0,1,0,34.33A1.9,1.9,0,0,1,116.66,132.16Z" />
         </g>
       </g>
     </svg>}
    href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/sql-functions-overview"
  >
    See how you can combine the statements, data types, and other references into specific functions for particular tasks.
  </Card>

  <Card title="Schema" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 158.36 157.3"><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path d="M79.18,60.74c-15.92,0-32-4-32-11.52s16.12-11.52,32-11.52,32,4,32,11.52S95.1,60.74,79.18,60.74Zm0-19c-17.12,0-28,4.45-28,7.52s10.92,7.52,28,7.52,28-4.45,28-7.52S96.3,41.7,79.18,41.7Z"/><path d="M79.18,80.36c-15.92,0-32-4-32-11.52V49.22a2,2,0,0,1,4,0V68.84c0,3.06,10.92,7.52,28,7.52s28-4.46,28-7.52V49.22a2,2,0,0,1,4,0V68.84C111.22,76.4,95.1,80.36,79.18,80.36Z"/><path class="cls-1" d="M65,69.73l-.29,0a30.61,30.61,0,0,1-6.85-1.78,2,2,0,0,1,1.55-3.69,26.74,26.74,0,0,0,5.87,1.51,2,2,0,0,1-.28,4Z"/><path d="M79.18,100c-15.92,0-32-4-32-11.52V68.84a2,2,0,0,1,4,0V88.46c0,3.06,10.92,7.52,28,7.52s28-4.46,28-7.52V68.84a2,2,0,0,1,4,0V88.46C111.22,96,95.1,100,79.18,100Z"/><path class="cls-1" d="M65,89.34a1.32,1.32,0,0,1-.28,0,30.3,30.3,0,0,1-6.86-1.77,2,2,0,0,1,1.55-3.69,26.83,26.83,0,0,0,5.87,1.5,2,2,0,0,1-.28,4Z"/><path d="M79.18,119.59c-15.92,0-32-4-32-11.51V88.46a2,2,0,0,1,4,0v19.62c0,3.06,10.92,7.51,28,7.51s28-4.45,28-7.51V88.46a2,2,0,0,1,4,0v19.62C111.22,115.64,95.1,119.59,79.18,119.59Z"/><path class="cls-1" d="M65,109a1.46,1.46,0,0,1-.29,0,30.3,30.3,0,0,1-6.85-1.77,2,2,0,0,1,1.55-3.69,26.42,26.42,0,0,0,5.87,1.5,2,2,0,0,1-.28,4Z"/><path d="M140.75,80.65H109.22a2,2,0,0,1,0-4h31.53a2,2,0,0,1,0,4Z"/><path d="M131.61,54.68H109.22a2,2,0,0,1,0-4h20.39V17.61a2,2,0,0,1,4,0V52.68A2,2,0,0,1,131.61,54.68Z"/><path class="cls-1" d="M131.61,19.61a9.81,9.81,0,1,1,9.81-9.8A9.81,9.81,0,0,1,131.61,19.61Zm0-15.61a5.81,5.81,0,1,0,5.81,5.81A5.81,5.81,0,0,0,131.61,4Z"/><path d="M131.61,141.68a2,2,0,0,1-2-2V106.62H109.22a2,2,0,0,1,0-4h22.39a2,2,0,0,1,2,2v35.06A2,2,0,0,1,131.61,141.68Z"/><path class="cls-1" d="M131.61,157.3a9.81,9.81,0,1,1,9.81-9.81A9.81,9.81,0,0,1,131.61,157.3Zm0-15.62a5.81,5.81,0,1,0,5.81,5.81A5.81,5.81,0,0,0,131.61,141.68Z"/><path d="M49.14,80.65H17.61a2,2,0,0,1,0-4H49.14a2,2,0,0,1,0,4Z"/><path d="M26.75,141.68a2,2,0,0,1-2-2V104.62a2,2,0,0,1,2-2H49.14a2,2,0,0,1,0,4H28.75v33.06A2,2,0,0,1,26.75,141.68Z"/><path class="cls-1" d="M26.75,157.3a9.81,9.81,0,1,1,9.8-9.81A9.82,9.82,0,0,1,26.75,157.3Zm0-15.62a5.81,5.81,0,1,0,5.8,5.81A5.82,5.82,0,0,0,26.75,141.68Z"/><path d="M49.14,54.68H26.75a2,2,0,0,1-2-2V17.61a2,2,0,0,1,4,0V50.68H49.14a2,2,0,0,1,0,4Z"/><path class="cls-1" d="M26.75,19.61a9.81,9.81,0,1,1,9.8-9.8A9.82,9.82,0,0,1,26.75,19.61ZM26.75,4a5.81,5.81,0,1,0,5.8,5.81A5.81,5.81,0,0,0,26.75,4Z"/><path class="cls-1" d="M156.36,88.45H140.75a2,2,0,0,1-2-2V70.84a2,2,0,0,1,2-2h15.61a2,2,0,0,1,2,2V86.45A2,2,0,0,1,156.36,88.45Zm-13.61-4h11.61V72.84H142.75Z"/><path class="cls-1" d="M17.61,88.45H2a2,2,0,0,1-2-2V70.84a2,2,0,0,1,2-2H17.61a2,2,0,0,1,2,2V86.45A2,2,0,0,1,17.61,88.45ZM4,84.45H15.61V72.84H4Z"/></g></g></svg>} href="https://docs.oxla.com/3-sql-reference/schema">
    Learn about a logical container that holds database objects and relationships of data in a database.
  </Card>

  <Card
    title="Comment Support"
    icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 152.34 144.24">
    <g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="cls-1" d="M115.26,85.94a2,2,0,0,1-.85-.19L92.92,75.66A2,2,0,1,1,94.62,72l21.49,10.09a2,2,0,0,1-.85,3.81Z"/><path class="cls-1" d="M143.06,26.71a2,2,0,0,1-.85-.19L120.73,16.44a2,2,0,0,1,1.7-3.63L143.91,22.9a2,2,0,0,1-.85,3.81Z"/><path class="cls-1" d="M63.43,55.21H34.15a2,2,0,0,1,0-4H63.43a2,2,0,1,1,0,4Z"/><path class="cls-1" d="M82.35,71.27H34.15a2,2,0,1,1,0-4h48.2a2,2,0,0,1,0,4Z"/><path class="cls-1" d="M82.35,87.32H34.15a2,2,0,0,1,0-4h48.2a2,2,0,0,1,0,4Z"/><path class="cls-1" d="M94,103.38H34.15a2,2,0,0,1,0-4H94a2,2,0,0,1,0,4Z"/><path d="M19.54,144.24a2,2,0,0,1-1.09-.32,2,2,0,0,1-.91-1.75l.92-23.95A56,56,0,0,1,5.18,100.39,55.43,55.43,0,0,1,55.39,21.56H97a55.3,55.3,0,0,1,19.53,3.55,2,2,0,1,1-1.42,3.74A51.21,51.21,0,0,0,97,25.56H55.39A51.44,51.44,0,0,0,8.8,98.7a52,52,0,0,0,13,17.13,2,2,0,0,1,.69,1.59L21.67,139l22.91-11.34a2,2,0,0,1,1.26-.17,52.64,52.64,0,0,0,9.55.89h11.5a2,2,0,1,1,0,4H55.39a56.37,56.37,0,0,1-9.63-.84L20.43,144A2,2,0,0,1,19.54,144.24Z"/><path d="M97,132.34H77.45a2,2,0,0,1,0-4H97A51.38,51.38,0,0,0,134.3,41.66a2,2,0,1,1,2.9-2.75A55.38,55.38,0,0,1,97,132.34Z"/><path d="M94,103.38a2.19,2.19,0,0,1-.86-.19,2,2,0,0,1-1.14-1.8l-.19-27.52A2.16,2.16,0,0,1,92,73l9.27-19.74a2,2,0,0,1,3.62,1.7L95.78,74.29l.15,22.89,17.71-14.5,31.88-67.91a4.13,4.13,0,0,0-2-5.5L133.15,4.4a4.12,4.12,0,0,0-5.49,2l-19,40.46a2,2,0,1,1-3.62-1.7L124,4.68A8.12,8.12,0,0,1,134.85.78l10.39,4.87a8.15,8.15,0,0,1,3.91,10.82L117.07,84.79a2.06,2.06,0,0,1-.54.7L95.22,102.93A2,2,0,0,1,94,103.38Z"/><path d="M103.12,95.87a2.1,2.1,0,0,1-.84-.19L93,91.33a2,2,0,1,1,1.7-3.62L104,92.05a2,2,0,0,1-.86,3.82Z"/></g></g></svg>}
    href="https://docs.oxla.com/3-sql-reference/comment-support"
  >
    Adding comments in your queries for better documentation and collaboration.
  </Card>
</CardGroup>


# Mutation - DELETE



## **Overview**

The `DELETE` mutation deletes one or more records from a table based on specified conditions. This support has limitations:

*   Only one data mutation (DELETE or UPDATE) at a given moment is possible, trying to run another one will fail.
*   Data mutations rewrite all files containing the data from the UPDATE/DELETE condition. Running `DELETE from the table` without any condition is possible, but it will be much slower than the `DROP TABLE table`.
*   The syntax is simplified in comparison to Postgres. For example, the `SET column=<value>` operation doesn't support sub-SELECT as the value, and the `WHERE` clause cannot contain sub-SELECT.

## **Syntax**

The syntax for `DELETE` mutation is as follows:

```sql
DELETE FROM table
WHERE conditions;
```

In this syntax:

*   `table`: The table name from which you want to delete records.
*   `WHERE` conditions (**Optional**): The conditions must be met for the deletion to execute. If no conditions are provided, all records from the table will be deleted.

## **Example**

1.  Let's create a sample table named `orders` that track customer orders.

```sql
CREATE TABLE orders (
    order_id INT,
    customer_name TEXT,
    product_id INT,
    quantity INT,
    order_status TEXT
);

INSERT INTO orders (order_id, customer_name, product_id, quantity, order_status)
VALUES
    (101, 'Alice Johnson', 1, 3, 'shipped'),
    (102, 'Bob Smith', 2, 1, 'pending'),
    (103, 'Charlie Brown', 3, 2, 'completed'),
    (104, 'David White', 1, 1, 'pending'),
    (105, 'Eva Davis', 4, 4, 'shipped');
```

2.  This creates a table named orders and inserts some sample data.

```sql
SELECT * FROM orders;
```

3.  You'll get the following table:

```sql
 order_id | customer_name | product_id | quantity | order_status 
----------+---------------+------------+----------+--------------
      101 | Alice Johnson |          1 |        3 | shipped
      102 | Bob Smith     |          2 |        1 | pending
      103 | Charlie Brown |          3 |        2 | completed
      104 | David White   |          1 |        1 | pending
      105 | Eva Davis     |          4 |        4 | shipped
```

4.  Let's say we want to delete orders with a quantity less than or equal to 2.

```sql
DELETE FROM orders
WHERE quantity <= 2;
```

5.  The output shows that the order with `order_id`: `102`, `103`, and `104` are deleted because they have a quantity less than 2.

```sql
 order_id | customer_name | product_id | quantity | order_status 
----------+---------------+------------+----------+--------------
      101 | Alice Johnson |          1 |        3 | shipped
      105 | Eva Davis     |          4 |        4 | shipped
```


# Overview



## What are Mutations? 🤔

A mutation refers to a change made to data stored in a database. Several commands are provided for data manipulation, such as `INSERT` (adds new records), `UPDATE` (modifies existing records), and `DELETE` (deletes records).

This support has limitations:

*   Only **one data mutation (DELETE or UPDATE)** at a given moment is possible. Trying to run another one will fail.

*   Data mutations rewrite all files containing the data from the UPDATE/DELETE condition. Running `DELETE from the table` without any condition is possible, but it will be much slower than the `DROP TABLE table`.

*   The syntax is simplified in comparison to Postgres. For example, the `SET column=<value>` operation doesn't support sub-SELECT as the value, and the `WHERE` clause cannot contain sub-SELECT.

***

Currently, Oxla supports the following SQL mutations:

<CardGroup cols={2}>
  <Card title="UPDATE" href="https://docs.oxla.com/4-sql-mutations/update-mutations">
    Learn more
  </Card>

  <Card title="DELETE" href="https://docs.oxla.com/4-sql-mutations/del-mutation">
    Learn more
  </Card>
</CardGroup>


# Mutation - UPDATE



## **Overview**

The `UPDATE` mutation is used to modify the existing records in a table. This support has limitations:

*   Only **one data mutation (DELETE or UPDATE)** at given moment is possible, trying to run another one will result in failure.

*   Data mutations rewrite all files containing the data from the UPDATE/DELETE condition. Please note that running `DELETE from table` without any condition is possible, but it will be much slower than just `DROP TABLE table`.

*   The syntax is simplified in comparison to Postgres. For example, the `SET column=<value>` operation doesn’t support sub-SELECT as the value, also the `WHERE` clause cannot contain sub-SELECT.

<Check>**Feature Update: Initial Release**. <br />
This marks the initial release of our new Mutation feature, providing you with the ability to update data. The Mutations involve rewriting entire files which take several minutes and could generate infrastructure costs. We are aiming to enhance and optimize this feature in future updates!</Check>

## **Syntax**

The syntax for `UPDATE` mutation is as follows:

```sql
UPDATE table
SET column1 = expression1,
    column2 = expression2
    ...
WHERE conditions;
```

In this syntax:

*   `table`: The name of the table you want to update.

*   `column1, column2`: The columns that you wish to update.

*   `expression1, expression2`: The new values to assign to column1, column2, and so on. Each column is set to its corresponding expression.

*   `WHERE conditions` **(Optional)**: The conditions that must be met for the update to execute. If no conditions are provided, all table records will be updated.

## **Examples**

Let's create a sample table called tasks:

```sql
CREATE TABLE tasks (
    task_id INT,
    task_name TEXT,
    status TEXT
);

INSERT INTO tasks (task_id, task_name, status)
VALUES
    (1001, 'Task A', 'pending'),
    (1002, 'Task B', 'in-progress'),
    (1003, 'Task C', 'pending');
```

The tasks table will be created as shown below:

```sql
 task_id | task_name |   status    
---------+-----------+-------------
    1001 | Task A    | pending
    1002 | Task B    | in-progress
    1003 | Task C    | pending
```

Now, let's see the following cases for updating the table:

### Case #1: Update a Single Column

1.  In this case, we want to update the `status` column to “completed” for the record where `task_id` is 1001.

```sql
UPDATE tasks
SET status = 'completed'
WHERE task_id = 1001;
```

2.  The output below shows that the update was successful.

```sql
UPDATE
```

3.  Check the updated table by running the `SELECT` query below:

```sql
SELECT * FROM tasks;
```

4.  The `UPDATE` mutation updates the status to “completed” for the task with ID 1001.

```sql
 task_id | task_name |   status    
---------+-----------+-------------
    1001 | Task A    | completed
    1002 | Task B    | in-progress
    1003 | Task C    | pending
```

### Case #2: Update Multiple Columns

1.  Let’s assume we want to update the `task_name` and `status` columns for the record where `task_id` is 1002.

```sql
UPDATE tasks
SET task_name = 'Updated Task B',
    status = 'completed'
WHERE task_id = 1002;
```

2.  The output below shows that the update was successful.

```sql
UPDATE
```

3.  Check the updated table by running the `SELECT` query below:

```sql
SELECT * FROM tasks;
```

4.  Here, the task name and status columns are updated for the task with ID 1002.

```sql
 task_id |   task_name    |  status   
---------+----------------+-----------
    1001 | Task A         | completed
    1002 | Updated Task B | completed
    1003 | Task C         | pending
```


# Error Handling



Learn more about the common errors and how to resolve them.

Below is the list of the common errors and its resolutions you might encounter while connecting or running the Oxla server.

### Undefined volume and invalid compose project

🚧 If you encounter an error like this:
` service "oxla_node" refers to undefined volume local_csvs: invalid compose project`

✅ Follow these steps:

1.  Change the directory where you store the docker-compose configuration file by executing this command:

```typescript
cd your_folder_name
```

2.  Open the docker-compose configuration file by executing this command:

```typescript
vim your_file_name.yml
```

3.  Remove `local_csvs:/local_csvs`in your docker compose file.

### Too many open files

🚧 If you encounter an error as follows when deploying Oxla servers

```typescript
Jan 24 13:58:26 server[XXXXXX]: 2023-01-24 13:58:26.301 ERROR [229223] [network::StateHandlerManager>::start@241] could not accept incoming connection because:
Jan 24 13:58:26 server[XXXXXX]: --------------------------------------------------------------------------------
Jan 24 13:58:26 server[XXXXXX]: Too many open files
```

✅ Follow these steps:

1.  Change the directory where you store the docker compose configuration file by executing this command:

```typescript
cd your_folder_name
```

2.  Open the docker compose configuration file by executing this command:

```typescript
vim your_file_name.yml
```

3.  Ensure that your docker compose file has the correct limit as follows:

```typescript
ulimits:
      nofile:
        soft: 40000
        hard: 40000
```

### Command not recognized - psql

🚧 If you encounter an error like this:
`'psql' is not recognized as an internal or external command, operable program, or batch file`

✅ Follow these steps:

**For windows**:

1.  Open the **PostgreSQL** folder > \*\*scripts \*\*folder and open the command prompt on your computer:

![open command prompt](https://archbee-image-uploads.s3.amazonaws.com/S_lGBDD7H53z1OcF8Kc79/80jZhU63tk1pglP_V-Oti_ezcom-maker-26.gif)

```typescript
(c) Microsoft Corporation. All rights reserved.

C:\Program Files\PostgreSQL\14\scripts>
```

2.  Run the following command: cd "C:\Program Files\PostgreSQL\14\bin"\`\`

```typescript
(c) Microsoft Corporation. All rights reserved.

C:\Program Files\PostgreSQL\14\scripts> cd "C:\Program Files\PostgreSQL\14\bin"
```

3.  Last but not least, execute the following command to run the Oxla server: psql -h 44.210.23.203\`\`

```typescript
(c) Microsoft Corporation. All rights reserved. 

C:\Program Files\PostgreSQL\14\scripts> cd "C:\Program Files\PostgreSQL\14\bin" 

C:\Program Files\PostgreSQL\14\bin> psql.exe -h 44.210.23.203
```

### Encoding is not supported

🚧 If you encounter an error like this:
`Psql: error: connection to server at "44.210.23.203", port 5432 failed: FATAL: WIN1252 encoding is not supported`

✅ Follow these steps:

1.  Run the following command:

```typescript
SET PGCLIENTENCODING=UTF8
```

2.  Then, activate the code page with the command below:

```typescript
chcp 65001Command
```

You will get the following output:

```typescript
Active code page: 65001
```

3.  Execute the following command to run the Oxla server: psql -h 44.210.23.203﻿\`\`

```typescript
C:\Program Files\PostgreSQL\14\bin>SET PGCLIENTENCODING=UTF8

C:\Program Files\PostgreSQL\14\bin>chcp 65001
Active code page: 65001

C:\Program Files\PostgreSQL\14\bin>psql.exe -h 44.210.23.203
```

### Missing argument

🚧 If you encounter an error like this:
`Psql: warning: extra command-line argument "44.210.23.203" ignored`

✅ Re-check the command. Keep an eye on each component, even the symbols and uppercase/lowercase words.

### Command not found - psql

🚧 If you encounter an error like this:
`Psql.exe: command not found`

✅ Download and install PostgreSQL on your computer:

*   **For windows,** download PostgreSQL from [here](https://www.postgresql.org/download/).
*   **For linux**, install PostgreSQL by following the steps [here](https://www.postgresql.org/download/linux/ubuntu/).
*   **For mac**, install PostgreSQL using the brew in terminal: `mac$ brew install postgresql`.

![Installing PostgreSQL](https://archbee-image-uploads.s3.amazonaws.com/S_lGBDD7H53z1OcF8Kc79/l5eN2BdKhfjiciegK3d1P_imageedit24068984245.png)


# Differences Between Oxla vs. PostgreSQL



## **1. Functions**

### a) Mathematical

A mathematical function operates on input values provided as arguments and returns a numeric value as the operation's output.

| **Mathematical** | **Description**                                                                                          | **Example**           | **Available in Oxla** |
| ---------------- | -------------------------------------------------------------------------------------------------------- | --------------------- | --------------------- |
| ABS              | Returns the absolute value of a number.                                                                  | `SELECT  ABS(-11);`   | Available             |
| CEIL             | Returns the value after rounding up any positive or negative value to the nearest largest integer.       | `SELECT CEIL(53.7);`  | Available             |
| FLOOR            | Returns the value after rounding up any positive or negative decimal value as smaller than the argument. | `SELECT FLOOR(53.6);` | Available             |
| LN               | Returns the natural logarithm of a given number.                                                         | `SELECT LN(3);`       | Available             |
| RANDOM           | Returns the random value between 0 and 1.                                                                | `SELECT RANDOM();`    | Available             |
| SQRT             | Returns the square root of a given positive number.                                                      | `SELECT SQRT(225);`   | Available             |

### b) Trigonometric

| **Trigonometric** | **Description**                           | **Example**        | **Available in Oxla** |
| ----------------- | ----------------------------------------- | ------------------ | --------------------- |
| SIN               | Returns the sine of the specified radian. | `SELECT sin(0.2);` | Available             |

## **2. Operators**

### a) Mathematical Operators

Below is a list of mathematical operators available in PostgreSQL:

| **Operators** | **Description** | **Example**       | **Result** | **Available in Oxla** |
| ------------- | --------------- | ----------------- | ---------- | --------------------- |
| `+`           | Addition        | `SELECT 5 + 8;`   | `13`       | Available             |
| `-`           | Subtraction     | `SELECT 2 - 3;`   | `\-1`      | Available             |
| `-`           | Negation        | `SELECT -4;`      | `\-4`      | Available             |
|               |                 | `SELECT -(-4);`   | `4`        | Available             |
|               |                 | `SELECT 5+(-2);`  | `3`        | Available             |
|               |                 | `SELECT 5-(-2);`  | `7`        | Available             |
| `*`           | Multiplication  | `SELECT 3 * 3;`   | `9`        | Available             |
| `/`           | Division        | `SELECT 10 / 2;`  | `5`        | Available             |
| `%`           | Modulo          | `SELECT 20 % 3;`  | `2`        | Available             |
| `&`           | Bitwise AND     | `SELECT 91 & 15;` | `11`       | Available             |
| `#`           | Bitwise XOR     | `SELECT 17 # 5;`  | `20`       | Available             |

### b) JSON Operators

Oxla supports operators for handling JSON data. One such operator is:

#### Equal Operator (`=`)

This operator checks if two JSON values are identical. In Oxla, this operator is order-sensitive which means that for two JSON objects to be considered equal, their key-value pairs must appear in the exact same order.

```sql
SELECT '{"a":1, "b":"c"}'::json = '{"b":"c", "a":1}'::json;
```

**Result**:

```sql
 ?column? 
----------
 f
(1 row)
```

<Note>In PostgreSQL, this operator is not order-sensitive, so the order of key-value pairs does not affect the comparison result.</Note>

## **3. Behaviors Difference**

### a) Output Header

Missing function name in output header, PostgreSQL shows the function name, like in this example:

```sql
SELECT COS(0),LN(1);
```

```sql
cos  | ln 
-----+-----
 1   | 0
```

Oxla does not show the function name, like in this example:

```sql
SELECT COS(0),LN(1);
```

```sql
 f | f_1 
---+-----
 1 | 0
```

### b) ABS Output

Differences are also found in the ABS function, where there are differences in decimal results.&#x20;

***For example:***

The example below will return the absolute value of -1.0

```sql
SELECT ABS(-1.0);
```

It returns 1 in Oxla, while in PostgreSQL, it produces 1.0

## **4. Errors Difference**

| **Functions** | **Input**                            | **Output - Oxla**                        | **Output - PostgreSQL**                                   |
| ------------- | ------------------------------------ | ---------------------------------------- | --------------------------------------------------------- |
| LN            | `LN(0)`                              | *Infinity*                               | *ERROR: cannot take the logarithm of zero*                |
|               | `LN(0.0)`                            | *Infinity*                               | *ERROR: cannot take the logarithm of zero*                |
| SQRT          | `SQRT(-1)`                           | *NaN*                                    | *ERROR: cannot take the square root of a negative number* |
| RANDOM        | `SELECT floor(random()*(10-1+1))+1;` | *ERROR: syntax error, unexpected INTVAL* | working as expected                                       |
| SIN           | `SELECT sin(pi()/2);`                | *unknown function pi*                    | working as expected                                       |
| /             | `1/0`                                | *error division(s) by zero*              | *error division(s) by zero*                               |
|               | `1/0.0`                              | *Infinity*                               | *error division(s) by zero*                               |
|               | `0/0.0`                              | *NaN*                                    | *error division(s) by zero*                               |


# Understanding Transactions



## **1. Overview**

The transactions are supported only on the syntax level to allow integration with tools that requires it. While the syntax is accepted, all the queries are executed immediately and with no transactional guarantees.

## **2. Commands**

These commands are used to manage transactions:

### **2.1. BEGIN**

Initiates a new transaction by calling one of the syntax below.

<CodeGroup>
  ```sql BEGIN
  BEGIN;
  ```

  ```sql BEGIN TRANSACTION
  BEGIN TRANSACTION;
  ```
</CodeGroup>

### **2.2. COMMIT**

Saves the changes made in a transaction to the database. It simply ends the transaction.
<br /> Call one of the syntax below.

<CodeGroup>
  ```sql COMMIT
  COMMIT;
  ```

  ```sql END TRANSACTION
  END TRANSACTION;
  ```
</CodeGroup>

### **2.3. ROLLBACK**

In Oxla, when you issue a ROLLBACK command, it doesn't undo changes made in the current transaction. It simply finishes the transaction without any rollback action.

```sql
ROLLBACK;
```

## **3. Example**

1.  Let's define a table named `products` with columns: `product_name`, `price`, and `stock_quantity`.

```sql
CREATE TABLE productsnew(
    product_name TEXT,
    price INT,
    stock_quantity INT
);
```

Upon successful creation, you will get the output below.

```sql
CREATE
```

2.  Next, we want to insert product data into a `products` table.&#x20;

```sql
BEGIN;
INSERT INTO productsnew(product_name, price, stock_quantity) VALUES ('Tab', 8000, 20);
```

<Warning>- Transactions cannot include anything more than one statement. <br /> - The `INSERT` statement is executed immediately without waiting for the end of the transaction or until a COMMIT is issued.</Warning>

You will get the following output:

```sql
BEGIN
INSERT 0 1
```

3.  View the changes by displaying the products table:

```sql
SELECT * FROM productsnew;
COMMIT;
```

The product data is now added to the table.

```sql
 product_name | price | stock_quantity 
--------------+-------+----------------
 Harddisk     | 12000 |             14
(1 row)

COMMIT
```


# Public Metrics



## Overview

Metrics play a crucial role in monitoring and analyzing the performance of Oxla, enabling users to gain valuable insights into their data processing and analytics workflows. The metrics are specific to a single node.

This documentation will guide you on how to access and leverage the metrics.

<Note>All metrics exposed by Oxla have a `label_node_id` with a node ID set. This is the same `node_id` that can be found in logs and on data storage.</Note>

## Accessing Metrics

Once you have successfully deployed Oxla, you can access the comprehensive metrics that provide valuable insights into the performance and health of your database. To access the metrics, follow the steps below:

1.  Open your preferred web browser and enter the following URL:&#x20;

```typescript
<ip>:8080/metrics
```

2.  Replace `<ip>` with the actual IP address of your Oxla deployment. For example, if your Oxla instance is hosted on IP address 128.128.1.1, the URL would be:

```typescript
128.128.1.1:8080/metrics
```

3.  If you are running Oxla locally on your machine, you can use localhost as the IP address. In that case, the URL would be:

```typescript
localhost:8080/metrics
```

4.  Upon accessing the URL, you will be presented with various metrics as shown below:&#x20;

```typescript
# HELP exposer_transferred_bytes_total Transferred bytes to metrics services
# TYPE exposer_transferred_bytes_total counter
exposer_transferred_bytes_total 0
# HELP exposer_scrapes_total Number of times metrics were scraped
# TYPE exposer_scrapes_total counter
exposer_scrapes_total 0
# HELP exposer_request_latencies Latencies of serving scrape requests, in microseconds
# TYPE exposer_request_latencies summary
exposer_request_latencies_count 0
exposer_request_latencies_sum 0
exposer_request_latencies{quantile="0.5"} Nan
exposer_request_latencies{quantile="0.9"} Nan
exposer_request_latencies{quantile="0.99"} Nan
# HELP oxla_net_postgres_client_queries_count Number of queries received from clients
# TYPE oxla_net_postgres_client_queries_count counter
oxla_net_postgres_client_queries_count{_node_id="oxla_node_1",query_type="SELECT"} 0
oxla_net_postgres_client_queries_count{_node_id="oxla_node_1",query_type="COPY"} 0
oxla_net_postgres_client_queries_count{_node_id="oxla_node_1",query_type="INSERT"} 0
oxla_net_postgres_client_queries_count{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_client_queries_successful_count Number of successful queries received from clients
# TYPE oxla_net_postgres_client_queries_successful_count counter
oxla_net_postgres_client_queries_successful_count{_node_id="oxla_node_1",query_type="SELECT"} 0
oxla_net_postgres_client_queries_successful_count{_node_id="oxla_node_1",query_type="COPY"} 0
oxla_net_postgres_client_queries_successful_count{_node_id="oxla_node_1",query_type="INSERT"} 0
oxla_net_postgres_client_queries_successful_count{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_client_queries_failed_count Number of failed queries received from clients
# TYPE oxla_net_postgres_client_queries_failed_count counter
oxla_net_postgres_client_queries_failed_count{_node_id="oxla_node_1",error_type="OTHER"} 0
oxla_net_postgres_client_queries_failed_count{_node_id="oxla_node_1",error_type="CANCELED"} 0
oxla_net_postgres_client_queries_failed_count{_node_id="oxla_node_1",error_type="EXECUTION ERROR"} 0
oxla_net_postgres_client_queries_failed_count{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_command_count Number of queries received from clients
# TYPE oxla_net_postgres_command_count counter
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="TERMINATE"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="EXECUTE"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="DESCRIBE"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="BIND"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="SYNC"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="PARSE"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1",query_type="QUERY"} 0
oxla_net_postgres_command_count{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_nonlocalhost_connections_count Total number of non localhost cennections
# TYPE oxla_net_postgres_nonlocalhost_connections_count counter
oxla_net_postgres_nonlocalhost_connections_count{_node_id="oxla_node_1"} 0
# HELP receipts_received_total Number of data task receipts received being executed on the node
# TYPE receipts_received_total counter
receipts_received_total{_node_id="oxla_node_1",receipts_status="rejected",scheduler_role="leader"} 0
receipts_received_total{_node_id="oxla_node_1",receipts_status="accepted",scheduler_role="leader"} 0
receipts_received_total{_node_id="oxla_node_1",receipts_status="rejected",scheduler_role="inserter"} 0
receipts_received_total{_node_id="oxla_node_1",receipts_status="accepted",scheduler_role="inserter"} 0
# HELP file_flushed_total Number of files flushed when inserting rows
# TYPE file_flushed_total counter
file_flushed_total{_node_id="oxla_node_1"} 0
# HELP tasks_executed_total Number of tasks executed on a node
# TYPE tasks_executed_total counter
tasks_executed_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="leader",task_status="failed"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="leader",task_status="succeeded"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="inserter",task_status="succeeded"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="inserter",task_status="succeeded"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="leader",task_status="succeeded"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="leader",task_status="failed"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="inserter",task_status="failed"} 0
tasks_executed_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="inserter",task_status="failed"} 0
# HELP tasks_result_received_total Number of tasks results received on a node
# TYPE tasks_result_received_total counter
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="merge",receiver_role="leader",task_status="canceled"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="compact",receiver_role="leader",task_status="canceled"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="compact",receiver_role="leader",task_status="succeeded"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="merge",receiver_role="leader",task_status="failed"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="compact",receiver_role="leader",task_status="failed"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="merge",receiver_role="inserter",task_status="succeeded"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="merge",receiver_role="inserter",task_status="failed"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="compact",receiver_role="inserter",task_status="canceled"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="merge",receiver_role="leader",task_status="succeeded"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="merge",receiver_role="inserter",task_status="canceled"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="compact",receiver_role="inserter",task_status="succeeded"} 0
tasks_result_received_total{_node_id="oxla_node_1",file_task_type="compact",receiver_role="inserter",task_status="failed"} 0
# HELP tasks_received_total Number of task a node has received to be executed
# TYPE tasks_received_total counter
tasks_received_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="leader",was_accepted="rejected"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="leader",was_accepted="rejected"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="leader",was_accepted="accepted"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="inserter",was_accepted="rejected"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="leader",was_accepted="accepted"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="inserter",was_accepted="rejected"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="inserter",was_accepted="accepted"} 0
tasks_received_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="inserter",was_accepted="accepted"} 0
# HELP tasks_scheduled_total Number of task the leader has send to nodes and are being executed
# TYPE tasks_scheduled_total counter
tasks_scheduled_total{_node_id="oxla_node_1",file_task_type="compact"} 0
tasks_scheduled_total{_node_id="oxla_node_1",file_task_type="merge"} 0
# HELP thread_pool_tasks_finished_total Number of tasks finished by the thread pool
# TYPE thread_pool_tasks_finished_total counter
thread_pool_tasks_finished_total{_node_id="oxla_node_1"} 0
# HELP thread_pool_tasks_started_total Number of tasks started by the thread pool
# TYPE thread_pool_tasks_started_total counter
thread_pool_tasks_started_total{_node_id="oxla_node_1"} 33
# HELP readers_closed_total Total number of readers closed since Oxla process creation
# TYPE readers_closed_total counter
readers_closed_total{_node_id="oxla_node_1"} 0
# HELP readers_opened_total Total number of readers opened since Oxla process creation
# TYPE readers_opened_total counter
readers_opened_total{_node_id="oxla_node_1"} 0
# HELP writers_closed_total Total number of writers closed since Oxla process creation
# TYPE writers_closed_total counter
writers_closed_total{_node_id="oxla_node_1"} 4
# HELP writers_opened_total Total number of writers opened since Oxla process creation
# TYPE writers_opened_total counter
writers_opened_total{_node_id="oxla_node_1"} 4
# HELP aws_requests Type and state of requests sent to the aws s3
# TYPE aws_requests counter
aws_requests{_node_id="oxla_node_1",state="succeeded",type="LIST"} 0
aws_requests{_node_id="oxla_node_1",state="retry",type="POST"} 0
aws_requests{_node_id="oxla_node_1",state="failed",type="POST"} 0
aws_requests{_node_id="oxla_node_1",state="started",type="POST"} 0
aws_requests{_node_id="oxla_node_1",state="started",type="GET"} 0
aws_requests{_node_id="oxla_node_1",state="finished",type="GET"} 0
aws_requests{_node_id="oxla_node_1",state="started",type="LIST"} 0
aws_requests{_node_id="oxla_node_1",state="failed",type="DELETE"} 0
aws_requests{_node_id="oxla_node_1",state="succeeded",type="POST"} 0
aws_requests{_node_id="oxla_node_1",state="retry",type="PUT"} 0
aws_requests{_node_id="oxla_node_1",state="failed",type="LIST"} 0
aws_requests{_node_id="oxla_node_1",state="retry",type="HEAD"} 0
aws_requests{_node_id="oxla_node_1",state="succeeded",type="PUT"} 0
aws_requests{_node_id="oxla_node_1",state="finished",type="DELETE"} 0
aws_requests{_node_id="oxla_node_1",state="started",type="PUT"} 0
aws_requests{_node_id="oxla_node_1",state="finished",type="HEAD"} 0
aws_requests{_node_id="oxla_node_1",state="retry",type="LIST"} 0
aws_requests{_node_id="oxla_node_1",state="finished",type="LIST"} 0
aws_requests{_node_id="oxla_node_1",state="succeeded",type="GET"} 0
aws_requests{_node_id="oxla_node_1",state="failed",type="PUT"} 0
aws_requests{_node_id="oxla_node_1",state="failed",type="GET"} 0
aws_requests{_node_id="oxla_node_1",state="succeeded",type="HEAD"} 0
aws_requests{_node_id="oxla_node_1",state="retry",type="GET"} 0
aws_requests{_node_id="oxla_node_1",state="started",type="DELETE"} 0
aws_requests{_node_id="oxla_node_1",state="finished",type="PUT"} 0
aws_requests{_node_id="oxla_node_1",state="retry",type="DELETE"} 0
aws_requests{_node_id="oxla_node_1",state="finished",type="POST"} 0
aws_requests{_node_id="oxla_node_1",state="failed",type="HEAD"} 0
aws_requests{_node_id="oxla_node_1",state="succeeded",type="DELETE"} 0
aws_requests{_node_id="oxla_node_1",state="started",type="HEAD"} 0
# HELP s3_connections_finished_total Number of s3 connections finished
# TYPE s3_connections_finished_total counter
s3_connections_finished_total{_node_id="oxla_node_1"} 0
# HELP s3_connections_started_total Number of s3 connections started
# TYPE s3_connections_started_total counter
s3_connections_started_total{_node_id="oxla_node_1"} 0
# HELP file_cache_use_total Number of hits and misses on our file cache
# TYPE file_cache_use_total counter
file_cache_use_total{_node_id="oxla_node_1",use_type="cant_get_descriptor"} 0
file_cache_use_total{_node_id="oxla_node_1",use_type="miss"} 4
file_cache_use_total{_node_id="oxla_node_1",use_type="hit_on_retry"} 0
file_cache_use_total{_node_id="oxla_node_1",use_type="hit"} 0
# HELP oxla_net_postgres_connections Number of clients connected using the postgres protocol
# TYPE oxla_net_postgres_connections gauge
oxla_net_postgres_connections{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_last_nonlocalhost_connection Last non local host connection
# TYPE oxla_net_postgres_last_nonlocalhost_connection gauge
oxla_net_postgres_last_nonlocalhost_connection{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_last_nonlocalhost_disconnection Last non local host disconnection
# TYPE oxla_net_postgres_last_nonlocalhost_disconnection gauge
oxla_net_postgres_last_nonlocalhost_disconnection{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_last_query_finished Last query finished
# TYPE oxla_net_postgres_last_query_finished gauge
oxla_net_postgres_last_query_finished{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_last_query_started Last query started
# TYPE oxla_net_postgres_last_query_started gauge
oxla_net_postgres_last_query_started{_node_id="oxla_node_1"} 0
# HELP oxla_net_postgres_queries_ongoing Number of currently running queries
# TYPE oxla_net_postgres_queries_ongoing gauge
oxla_net_postgres_queries_ongoing{_node_id="oxla_node_1"} 0
# HELP cluster_has_leader_bool Is true iff cluster has a leader.
# TYPE cluster_has_leader_bool gauge
cluster_has_leader_bool{_node_id="oxla_node_1"} 1
# HELP current_max_capacity Current max capacity per node
# TYPE current_max_capacity gauge
current_max_capacity{_node_id="oxla_node_1"} 32
# HELP num_nodes_connected Number of nodes connected
# TYPE num_nodes_connected gauge
num_nodes_connected{_node_id="oxla_node_1"} 1
# HELP node_is_degraded_bool Is true if node is degraded
# TYPE node_is_degraded_bool gauge
node_is_degraded_bool{_node_id="oxla_node_1"} 0
# HELP node_is_leader_bool Is true iff node is a leader.
# TYPE node_is_leader_bool gauge
node_is_leader_bool{_node_id="oxla_node_1"} 1
# HELP num_open_connections Number of open connections (StateHandler instances)
# TYPE num_open_connections gauge
num_open_connections{_node_id="oxla_node_1"} 2
# HELP tasks_ongoing_total Number of task currently being executed on the node
# TYPE tasks_ongoing_total gauge
tasks_ongoing_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="leader"} 0
tasks_ongoing_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="leader"} 0
tasks_ongoing_total{_node_id="oxla_node_1",file_task_type="merge",scheduler_role="inserter"} 0
tasks_ongoing_total{_node_id="oxla_node_1",file_task_type="compact",scheduler_role="inserter"} 0
# HELP thread_pool_size_total Number of threads used by the thread pool
# TYPE thread_pool_size_total gauge
thread_pool_size_total{_node_id="oxla_node_1"} 33
# HELP file_flush_duration_ms how long does it take to flush a file
# TYPE file_flush_duration_ms histogram
file_flush_duration_ms_count{_node_id="oxla_node_1"} 0
file_flush_duration_ms_sum{_node_id="oxla_node_1"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="10"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="20"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="30"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="40"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="50"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="60"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="70"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="80"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="90"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="100"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="110"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="125"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="150"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="200"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="250"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="300"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="400"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="500"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="600"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="700"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="750"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="800"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="900"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="1000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="1500"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="2000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="2500"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="3000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="3500"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="4000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="5000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="6000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="7000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="8000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="9000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="10000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="15000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="20000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="30000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="40000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="50000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="60000"} 0
file_flush_duration_ms_bucket{_node_id="oxla_node_1",le="+Inf"} 0
# HELP oxla_jemalloc_mallctl_stats Information about jemalloc internal statistics via mallctl*
# TYPE oxla_jemalloc_mallctl_stats gauge
oxla_jemalloc_mallctl_stats{elem="stats.allocated",_node_id="oxla_node_1"} 10005776
oxla_jemalloc_mallctl_stats{elem="stats.active",_node_id="oxla_node_1"} 11104256
oxla_jemalloc_mallctl_stats{elem="stats.metadata",_node_id="oxla_node_1"} 12341008
oxla_jemalloc_mallctl_stats{elem="stats.metadata_thp",_node_id="oxla_node_1"} 0
oxla_jemalloc_mallctl_stats{elem="stats.resident",_node_id="oxla_node_1"} 23797760
oxla_jemalloc_mallctl_stats{elem="stats.mapped",_node_id="oxla_node_1"} 77090816
oxla_jemalloc_mallctl_stats{elem="stats.retained",_node_id="oxla_node_1"} 58699776
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.small.allocated",_node_id="oxla_node_1"} 5045520
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.small.nmalloc",_node_id="oxla_node_1"} 54779
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.small.ndalloc",_node_id="oxla_node_1"} 7901
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.large.allocated",_node_id="oxla_node_1"} 4960256
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.large.nmalloc",_node_id="oxla_node_1"} 76
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.large.ndalloc",_node_id="oxla_node_1"} 27
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.dead.small.allocated",_node_id="oxla_node_1"} 0
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.dead.small.nmalloc",_node_id="oxla_node_1"} 0
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.dead.small.ndalloc",_node_id="oxla_node_1"} 0
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.dead.large.allocated",_node_id="oxla_node_1"} 0
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.dead.large.nmalloc",_node_id="oxla_node_1"} 0
oxla_jemalloc_mallctl_stats{elem="stats.arenas.all.dead.large.ndalloc",_node_id="oxla_node_1"} 0
# HELP oxla_memory_usage_bytes Memory used by Oxla
# TYPE oxla_memory_usage_bytes gauge
oxla_memory_usage_bytes{value="memory_consumption_total",_node_id="oxla_node_1"} 33554432
oxla_memory_usage_bytes{value="orphaned_memory_consumption_total",_node_id="oxla_node_1"} 0
oxla_memory_usage_bytes{value="cache_memory_consumption_total",_node_id="oxla_node_1"} 33554432
oxla_memory_usage_bytes{value="cache_memory_total_evictions",_node_id="oxla_node_1"} 0
oxla_memory_usage_bytes{value="query_memory_consumption_total",_node_id="oxla_node_1"} 0
oxla_memory_usage_bytes{value="privileged_query_memory_consumption_total",_node_id="oxla_node_1"} 0
oxla_memory_usage_bytes{value="privileged_tag",_node_id="oxla_node_1"} 65535
oxla_memory_usage_bytes{value="tags_in_use",_node_id="oxla_node_1"} 0
oxla_memory_usage_bytes{value="memory_limit_total",_node_id="oxla_node_1"} 60381200384
```

The following is a list of parameters available in the Public Metrics:

| **Parameters**                                      | **Description**                                                               |
| --------------------------------------------------- | ----------------------------------------------------------------------------- |
| `exposer_prefix`                                    | The component responsible for exposing metrics.                               |
| `exposer_transferred_bytes_total`                   | Total size of bytes transferred out by the endpoint.                          |
| `exposer_scrapes_total`                             | Number of times metrics were scraped.                                         |
| `exposer_request_latencies`                         | Latencies of serving scrape requests, in microseconds.                        |
| `exposer_request_latencies_count`                   | Count of latencies.                                                           |
| `exposer_request_latencies_sum`                     | Sum of latencies.                                                             |
| `client_sql_successful_queries_total`               | Number of successful queries received from clients.                           |
|                                                     | The available queries are:                                                    |
|                                                     | - `label="COPY"`, successful COPY queries.                                    |
|                                                     | - `label="SELECT"`, successful SELECT queries.                                |
|                                                     | - `label="INSERT"`, successful INSERT queries.                                |
|                                                     | The available label is `query_type`.                                          |
| `client_sql_queries_total`                          | Number of queries received from clients.                                      |
|                                                     | The available queries are:                                                    |
|                                                     | - `label="COPY"`, total COPY queries.                                         |
|                                                     | - `label="SELECT"`, total SELECT queries.                                     |
|                                                     | - `label="INSERT"`, total INSERT queries.                                     |
|                                                     | The available label is `query_type`.                                          |
| `file_flushed_total`                                | Number of files flushed when inserting rows.                                  |
| `tasks_executed_total`                              | Number of tasks executed on the cluster.                                      |
| `tasks_received_total`                              | Number of tasks a node has received to be executed.                           |
|                                                     | The available task types are:                                                 |
|                                                     | - `file_task_type="compact"`, total compact tasks received.                   |
|                                                     | - `file_task_type="merge"`, total merge tasks received.                       |
| `tasks_scheduled_total`                             | Number of tasks the leader has sent to nodes and are being executed.          |
|                                                     | The available task types are:                                                 |
|                                                     | - `file_task_type="compact"`, total compact tasks scheduled.                  |
|                                                     | - `file_task_type="merge"`, total merge tasks scheduled.                      |
| `thread_pool_tasks_finished_total`                  | Number of tasks finished by the thread pool.                                  |
| `thread_pool_tasks_started_total`                   | Number of tasks started by the thread pool.                                   |
| `readers_closed_total`                              | Total number of readers closed since Oxla process creation.                   |
| `readers_opened_total`                              | Total number of readers opened since Oxla process creation.                   |
| `writers_closed_total`                              | Total number of writers closed since Oxla process creation.                   |
| `writers_opened_total`                              | Total number of writers opened since Oxla process creation.                   |
| `cluster_has_leader_bool`                           | Indicates if the cluster has a leader or not.                                 |
| `num_nodes_connected`                               | Number of nodes connected.                                                    |
| `node_is_leader_bool`                               | Indicates if the node is a leader.                                            |
| `num_open_connections`                              | Number of open connections.                                                   |
| `postgres_connections_total`                        | Number of clients connected using the Postgres protocol.                      |
| `tasks_capacity_total`                              | Number of task capacity on the cluster.                                       |
| `tasks_ongoing_total`                               | Number of tasks currently being executed on the node.                         |
|                                                     | The available task types are:                                                 |
|                                                     | - `file_task_type="compact"`, total ongoing compact tasks.                    |
|                                                     | - `file_task_type="merge"`, total ongoing merge tasks.                        |
| `thread_pool_size_total`                            | Number of threads used by the thread pool.                                    |
| `oxla_memory_usage_bytes`                           | Memory used by Oxla.                                                          |
|                                                     | The available values are:                                                     |
|                                                     | - `value="system_memory_consumption_total"`, total system memory consumption. |
|                                                     | - `value="cache_memory_consumption_total"`, total cache memory consumption.   |
|                                                     | - `value="query_memory_consumption_total"`, total query memory consumption.   |
| `oxla_mallinfo`                                     | Information about glibc's malloc() internal state.                            |
| `s3_connections_started`                            | Number of S3 connections started.                                             |
| `s3_connections_finished`                           | Number of S3 connections finished.                                            |
| `tasks_result_received`                             | Number of task results received.                                              |
| `oxla_net_postgres_connections_count`               | Total number of network connections.                                          |
| `oxla_net_postgres_nonlocalhost_connections_count`  | number of active non-localhost connections.                                   |
| `oxla_net_postgres_queries_ongoing`                 | Number of currently running client queries.                                   |
| `oxla_net_postgres_command_count`                   | Total number of commands.                                                     |
| `oxla_net_postgres_last_nonlocalhost_connection`    | Timestamp of last non-localhost connection event \[In seconds].               |
| `oxla_net_postgres_last_nonlocalhost_disconnection` | Timestamp of last non-localhost disconnection event \[In seconds]             |
| `oxla_net_postgres_last_query_finished`             | Timestamp of last client query finished event \[In seconds].                  |
| `oxla_net_postgres_last_query_started`              | Timestamp of last client query started event \[In seconds].                   |

<Tip>By regularly monitoring these metrics, you can gain valuable insights into the efficiency of your database operations, identify potential bottlenecks, and make data-driven optimizations to enhance the overall performance and reliability of your analytical workflows.</Tip>


# Oxla Configuration File



## **1. Overview**

The configuration of Oxla is managed through a configuration file. The configuration file defining various aspects of Oxla's behavior and its usage is helpful for both development and deployment.

When Oxla is run as a docker container, the config file is generated automatically inside a container in `/oxla/startup_config` based on environment variables passed and default values.

## **2. Mounting Config Directory**

The `/oxla/startup_config` config directory can be mounted using `-v /path/to/mount:/oxla/startup_config` to access the config file directly:

```shell
docker run --rm -it -p 5432:5432 -v /path/to/mount:/oxla/startup_config public.ecr.aws/oxla/release:latest
```

### **2.1. Config File Handling**

<AccordionGroup>
  <Accordion title="Automatic Generation from Defaults">
    If no configuration is found in the specified directory, Oxla generates one using default values. The default name would be `config.yml`. During generation, Oxla takes into account [environment variables](https://docs.oxla.com/oxla-configuration-file#rweBJ) passed. When the environment variable is passed, this value is written to the generated config instead of the default one.
  </Accordion>

  <Accordion title="Modifying Default Config Path">
    To modify the default config path inside the Oxla Docker container, pass the `OXLA_CONFIG_FILE=path/to/config.yml` environment variable to the `docker run` command. Passing an empty path indicates the intent to use default values only.
  </Accordion>

  <Accordion title="Partial Variable Specification">
    When creating a custom configuration file, it is not required to pass all the possible variables. If a variable is not passed, it assumes the default value. So, an empty configuration file can be used, but Oxla will use defaults for everything.
  </Accordion>

  <Accordion title="Regenerating the Config File">
    The best way to regenerate the config file is to remove or rename the existing config file, so there's no `/oxla/startup_config/config.yml`. Oxla will then automatically generate a new configuration file based on default values.
  </Accordion>
</AccordionGroup>

## 3. Configuration Variables

The yaml below is the default configuration file in Oxla:

```yaml
network:
  port: 5769
  postgresql_port: 5432
  prometheus_port: 8080
  nodes:
    - "localhost"
  cluster_name: "cluster_1"
  host_name: "oxla_node_1"

metrics:
  no_prometheus_exposer: false

insertion:
  buffer_size_limit: 42M
  buffer_timeout: 100 ms

logging:
  level: "INFO"

storage:
  oxla_home: "/oxla/data"
  s3:
    enable_discovery: true
    use_dual_stack: true
    endpoint: ""
```

Below is a list of key configuration variables:

| **Variable**                    | **Description**                                                                                                  |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `network.port`                  | Port on which Oxla listens for connections from nodes in the cluster.                                            |
| `network.postgresql_port`       | Port on which the node listens for TCP connections to the Postgres client.                                       |
| `network.prometheus_port`       | Port on which the process listens for HTTP connections for Prometheus metrics.                                   |
| `network.nodes`                 | List of IP addresses or DNS addresses to which Oxla connects.                                                    |
| `network.cluster_name`          | Common cluster name used for node connection validation.                                                         |
| `network.host_name`             | Unique name of a single node in the cluster.                                                                     |
| `metrics.no_prometheus_exposer` | Disable the Prometheus exposer.                                                                                  |
| `insertion.buffer_size_limit`   | Threshold for data or time before dumping data from memory to the filesystem.                                    |
|                                 | **Possible units:**                                                                                              |
|                                 | - `G`                                                                                                            |
|                                 | - `M`                                                                                                            |
|                                 | - `K`                                                                                                            |
|                                 | **Default value:** interpreted as bytes.                                                                         |
| `insertion.buffer_timeout`      | Timeout for dumping data from memory to the filesystem.                                                          |
|                                 | **Possible units:**                                                                                              |
|                                 | - `h`                                                                                                            |
|                                 | - `min`                                                                                                          |
|                                 | - `s`                                                                                                            |
|                                 | - `ms`                                                                                                           |
|                                 | **Default value:** value in `ms` unit.                                                                           |
| `logging.info`                  | Logging level.                                                                                                   |
|                                 | **Possible values:**                                                                                             |
|                                 | - `VERBOSE`                                                                                                      |
|                                 | - `DEBUG`                                                                                                        |
|                                 | - `INFO`                                                                                                         |
|                                 | - `WARNING`                                                                                                      |
|                                 | - `ERROR`                                                                                                        |
|                                 | - `FATAL`                                                                                                        |
|                                 | - `NONE`                                                                                                         |
| `storage.oxla_home`             | Directory for data. Either on local disk (path inside the container), or on S3.                                  |
| `storage.s3.enable_discovery`   | By default, regional or overridden endpoints are used. To enable endpoint discovery, set the variable to `true`. |
| `storage.s3.use_dual_stack`     | Enable or disable dual-stack IPv4 and IPv6 endpoints.                                                            |
|                                 | **Note:** not all AWS services support IPv6 in all Regions.                                                      |
| `storage.s3.endpoint`           | Endpoint for the S3 protocol. If not provided, the default AWS endpoint is used.                                 |

### **3.1. Environment Variables**

Values in the configuration file take precedence over environment variables and default values.&#x20;

Naming conventions for environment variables are derived from the configuration variable names, with `__` (double underscores) replacing YAML hierarchy levels. For example:

```yaml
network:
  port: 5769
```

<Note>The port is expressed as the `NETWORK__PORT` environment variable.</Note>

Environment variables can be passed using the `-e` parameter in the `docker run` command, as illustrated below:

```shell
docker run --rm -it -p 5432:5432 -e INSERTION__BUFFER_TIMEOUT=1ms public.ecr.aws/oxla/release:latest
```


# Database Files Virtual Table



## Overview

The `oxla_home_files` virtual table lists all files associated with a specific table in the oxla home directory. This approach offers a more reliable way to retrieve data than simply scanning files directly.

## Fields

| Field          | Content                                       | Type          |
| -------------- | --------------------------------------------- | ------------- |
| `path`         | Absolute path from the oxla working directory | TEXT          |
| `byte_size`    | Size of the file in bytes                     | BIGINT        |
| `start_index`  | First index in the file, if applicable        | NULLABLE TEXT |
| `end_index`    | Last index in the file, if applicable         | NULLABLE TEXT |
| `row_count`    | Number of rows in the file                    | BIGINT        |
| `batch_count`  | Number of batches the file is divided into    | BIGINT        |
| `table_id`     | ID of the related table                       | BIGINT        |
| `namespace_id` | ID of the related namespace                   | BIGINT        |
| `database_id`  | ID of the related database                    | BIGINT        |

## Example Query

This example shows how to query the `oxla_home_files` table in an Oxla instance.

### Scenario 1: Empty Result

1.  Run the `oxla_home_files` query below.

```sql
SELECT * FROM oxla_internal.oxla_home_files;
```

2.  When the `oxla_home_files` table is empty, the query returns an empty result set.

```sql
 path | byte_size | start_index | end_index | row_count | batch_count | table_id | namespace_id | database_id 
------+-----------+-------------+-----------+-----------+-------------+----------+--------------+-------------
(0 rows)
```

### Scenario 2: After Data Insertion

1.  Create and insert data to the table.

```sql
CREATE TABLE orders (
  order_id INT,
  order_date DATE,
  total_amount INT,
  shipping_address TEXT,
  status TEXT
);

INSERT INTO orders 
    (order_id, order_date, total_amount, shipping_address, status) 
VALUES 
    (1001, '2024-07-13', 150.75, '123 Main St, Anytown, USA', 'Shipped'),
    (1002, '2024-07-12', 200.50, '456 Elm St, Othertown, USA', 'Delivered'),
    (1003, '2024-07-12', 350.25, '789 Oak St, Anotherplace, USA', 'Processing'),
    (1001, '2024-07-11', 100.00, '321 Pine St, Somewhere, USA', 'Cancelled'),
    (1004, '2024-07-10', 500.00, '555 Maple St, Nowhere, USA', 'Pending');
```

2.  Run the `oxla_home_files` query below.

```sql
SELECT * FROM oxla_internal.oxla_home_files;
```

3.  After inserting data into the table, the query lists the file metadata stored in Oxla.

```sql
                                                                                          path                                                                                          | byte_size | start_index | end_index | row_count | batch_count | table_id | namespace_id | database_id 
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+-------------+-----------+-----------+-------------+----------+--------------+-------------
 s3://regional-providers-eu-central-1-dp/production/2jyd1o7D6CBCKyU2gWafDfEawmP/oxla_data/hack_on_oxla_non_empty_storage/0/0/16385/buffers/cluster-2jyd1jzvhgequov20igkxe4peyl-oxla-0/0 |       978 |             |           |         5 |           1 |    16385 |            0 |           0
(1 row)
```


# Handling Oxla Degraded State



## Overview

Node degradation refers to the condition in which a node cannot perform most queries. If Oxla is misconfigured or faces a startup issue, it will enter a degraded state, return an error and reject all requests. This state can be temporary or permanent, affecting a single node or the entire cluster. This guide explains when degradation occurs and its impact on the node or cluster.

## Cluster State

In Oxla, most errors that would crash a server should instead put it into a degraded state. Below are the key terms related to the node / cluster state:

*   **Liveness**: node serves incoming client connections, e.g. via psql. It does not have to allow the user to connect to the database - returning an error on connection attempt still meets liveness condition.
*   **Readiness**: cluster can execute queries. It requires leader node to be in a proper state. If the leader node is degraded, the cluster is not ready to execute queries.

<Warning>**Exception** <br /> Invalid `postgresql_port` is an exception to the degraded state. Without it being properly set, even liveness condidtion is not met.</Warning>

## Degradation State Period

The degradation state of a node can be either **permanent** or **temporary**.

### Permanent Degradation

Permanent degradation occurs when a node encounters an error from which it cannot recover. The server logs the reason for this error and each query returns the error reason. As a result, the node goes into a degraded state. In order to resolve the issue, the node requires a reboot. Here are a few error examples that can put an Oxla node in a permanently degraded state:

*   Invalid configuration file
*   Invalid `OXLA_HOME` layout or version
*   An error occurred while reading the database state on the leader node

### Temporary Degradation

Temporary degradation occurs when a node cannot perform queries because it waits for specific conditions. Below you can find errors that are related to a temporary degraded state:

*   Unelected Leader (default starting state of each node)
*   The node is the Leader, but it has not been initialized yet

## Effects of Degraded State

| Effects             | Details                                                                                                                                                                                                                                                              |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Database connection | If the Leader is degraded, user cannot connect to the database and all connection attempts will return degradation error.                                                                                                                                            |
| Query Handling      | - When a degraded node receives a query, it responds with a degradation error and cannot process it. - If the Leader is degraded, the whole cluster is considered degraded and most queries are not processed.                                                       |
| Degradation Types   | - **Permanent Degradation**: Nodes permanently degraded are excluded from query planning. <br /> - **Temporary Degradation**: Nodes temporarily degraded are assumed to recover and are not considered in query planning.                                            |
| Query Execution     | The `SHOW NODES` query requires the cluster to be ready and the scheduling node to not be degraded. It allows you to check the degradation status of each node in the cluster. A non-degraded leader collects data on every connected node, including degraded ones. |


# How to Connect Oxla Cloud with Looker Studio



## **Connect to Oxla Cloud**

1.  You need a running cluster to connect it with Looker Studio.

    *   If you don’t have one, create one by following the steps [here](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas).
    *   If you already have an existing cluster that you want to connect, click the three dots next to the cluster and click **Connect**.

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/looker1.png" />
    </Frame>

2.  For the cluster conection details please head to **Connect info** you can find in cluster context menu. Here youl'll find:

    *   **Address**: The cluster address.
    *   **Port**: The port number.
    *   **Username**: The username of the user/role that has access to the cluster.
    *   **Server certificate**: A certificate of the server that you can download to be uploaded to Looker Studio.

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/looker2.png" />
    </Frame>

## **Access Looker Studio**

1.  Open [https://lookerstudio.google.com/](https://lookerstudio.google.com/) and login to your account.
2.  Click on the **Create** button and choose the **Report** option.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/looker3.png" />
</Frame>

3.  Configure Looker Studio connection with a Google-provided PostgreSQL connector.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/looker4.png" />
</Frame>

4.  To connect with Looker Studio connection, please enter the following details:
    *   **Host Name or IP**: Your host’s address from the **Address** field on the **Oxla Cloud Connect** view.
    *   **Port**: Enter the port number
    *   **Database**: Enter `oxla`.
    *   **Username**: Your username from the **Username** field on **Oxla Cloud Connect** view.
    *   **Password**: Your cluster’s password.
    *   Check **Enable SSL** checkbox.
    *   Next to **PostgreSQL SSL Configuration Files**, click the **Upload** icon arrow and upload the certificate you downloaded from Oxla Cloud.
5.  Click on **Authenticate** to proceed.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/looker5.png" />
</Frame>

6.  Select a table from the list of tables.

<Frame>
  <img height="150" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/looker6.png" />
</Frame>

<Check>That’s all! The data source is connected.</Check>


# How to Connect Oxla Cloud with PowerBI



## Setting up your Oxla Cloud cluster

In order to connect [Power BI](https://www.microsoft.com/en-us/power-platform/products/power-bi) with [Oxla Cloud](https://oxla.cloud/), you need to have a running cluster. If you don't have one yet, you can easily create it by following our step by step [Oxla Cloud: Quickstart Guide](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas).

*   If you already have an existing cluster that you want to use with Power BI, click the three dots next to it and select **Start**

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_cluster_list.png" />
    </Frame>

*   For viewing the connection details please select **Connect info** from the menu available next to the running cluster:
    *   **Address**: cluster address
    *   **Port**: port number
    *   **Username**: username of the user/role that has access to the cluster
    *   **Server certificate**: certificate of the server that you can download to be uploaded to the Certificate Store if needed

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_connection_info.png" />
</Frame>

## Connecting Power BI with Oxla Cloud

Right now, that you've successfully gone through Oxla Cloud cluster creation flow and have its connection information, it's time to set up Power BI

*   Firstly, start your [Power BI Desktop](https://www.microsoft.com/pl-pl/power-platform/products/power-bi/desktop) application and click on **Get Data**

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_get_data.png" />
    </Frame>

*   Then you need to look for `PostgreSQL database` connector

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_connector.png" />
    </Frame>

*   Configure the connector with your cluster address and use `oxla` as a database name

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_connect.png" />
    </Frame>

<Warning>For the Data Connectivity mode we highly recommend `Import` option as `DirectQuery` support is experimental for now</Warning>

*   Fill in the credentials for your cluster and click **Connect**

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_credentials.png" />
    </Frame>

5.  Select the desired tables from the list and click **Load**

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_tables_list.png" />
    </Frame>

<Check>That’s it! The data source is connected.</Check>

## Troubleshooting

If you encounter an `invalid certficiate` error on connection attempt, about remote certificate being invalid, please download Server Certificate from connection details of your cluster and follow this [official tutorial](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/trusted-root-certification-authorities-certificate-store) for adding the certificate to the Certificate Store.

<Info>Oxla Cloud certificate is in `.pem` format, while importing it to Certificate Store, make sure that file selector is set to `All files (*.*)` as shown on screenshot below</Info>

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_cert.png" />
</Frame>

Once it's done, `Oxla Root CA` should be visible in the Certificate Store

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/how-to-connect-to-oxla-cloud-with-powerbi/powerbi_cert_store.png" />
</Frame>


# How to Connect Oxla Cloud with TablePlus



## **Connect to Oxla Cloud**

1.  You need a running cluster to connect it with TablePlus.

    *   If you don’t have one, create one by following the steps [here](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas).
    *   If you already have an existing cluster that you want to connect, click the three dots next to the cluster and click **Connect**.

    <Frame>
      <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/tableplus1.png" />
    </Frame>

2.  You will see the following details in the **Oxla Cloud Connect** view:

    *   **Address**: The host’s address to be used to connect with TablePlus.
    *   **Port**: The port number.
    *   **Username**: The username of the user/role that has access to the cluster.
    *   **Password**: The password that you set up during the cluster creation.
    *   **Server certificate**: A certificate of the server that you can download to be uploaded to TablePlus.

    <Frame>
      <img height="150" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/tableplus2.png" />
    </Frame>

## **Access TablePlus**

1.  Download and install the TablePlus with your chosen OS [here](https://tableplus.com/download).
2.  Open the TablePlus app. From the welcome screen, click **Create a New Connection** at the bottom, or right-click on the connection view and choose **New**.
3.  Choose the database type and click **Create**.
4.  To connect with TablePlus connection, please enter the following details:
    *   **Connection's name**: You can enter any random or unique identifier of the connection.
    *   Select **PostgreSQL**. You can select any tag.
    *   **Database host/socket**: Your host’s address from the **Address** field on the **Oxla Cloud Connect** view.
    *   **Port**: Enter the port number.
    *   **Database's user**: Your host’s address from the **Address** field on **Oxla Cloud Connect** view.
    *   **Password**: Your password.
    *   **Database's name**: Enter `oxla`.
    *   **Connection type**: Select PREFERRED.
    *   Click on **CA Cert** and upload the certificate you downloaded from Oxla Cloud.
5.  Click **Connect** to proceed.

<Frame>
  <img height="150" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/tableplus3.png" />
</Frame>

<Check>That’s all! The data source is connected.</Check>


# Introduction to Oxla Cloud



## **Introduction**

Oxla's Cloud is our cloud-based service that provides instant access to the Oxla data processing engine. It offers easy cluster management where you can deploy the cluster instantly, monitor the cost and utilization, and help you build faster. You can use this product to:

<Icon icon="check" iconType="solid" /> Perform and optimize your data analysis and processing without worrying about infrastructure complexities. <br />

<Icon icon="check" iconType="solid" /> Have a pay-as-you-go model with flexible pricing that caters to projects of all sizes. <br />

<Icon icon="check" iconType="solid" /> Have a dedicated and reliable support team available to assist you with any questions or issues. <br />

<Icon icon="check" iconType="solid" /> Have easy cluster management, where you can spin cluster only for the time needed, with adjustable size per use case. <br />

<Icon icon="check" iconType="solid" /> Have full workload observability with usage insights.

## **Key Features**

Experience the ease and flexibility of Oxla Cloud with its key features:

<CardGroup cols={2}>
  <Card title="Instant Cluster Deployment" icon="square-1">
    Deploy clusters instantly to get your data operations up and running.
  </Card>

  <Card title="Cost and Utilization Monitoring" icon="square-2">
    Keep track of your spending with real-time cost and utilization monitoring.
  </Card>

  <Card title="PostgreSQL Protocol Compliance" icon="square-3">
    Oxla adheres to PostgreSQL protocol standards for easy integration and compatibility.
  </Card>

  <Card title="Decoupled Storage and Compute" icon="square-4">
    The data storage lifecycle is decoupled from clusters. You only pay for computing resources when the cluster is running. Even if the cluster is stopped or deleted, your data remains intact, and you only pay for the storage you use.
  </Card>

  <Card title="Maintenance-free" icon="square-5">
    Enjoy a fully managed service by Oxla, which will free you from maintenance tasks and allow you to focus on your business.
  </Card>
</CardGroup>


# Quickstart - Oxla SaaS



This quickstart guide will help you start with Oxla Cloud by setting up workloads using a sample dataset.

## **Step 1. Create an Account**

Create an account [here](https://oxla.cloud/) or login using your credentials.

## **Step 2. Set Up Data Storage with Sample Data**

1.  Once logged in, go to the **Overview** or **Data** section and choose the **Create Data Storage** button. Specify the data storage name and select one of the pre-loaded datasets. In this case, we’ll use the eCommerce dataset.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart1.png" />
</Frame>

2.  Please wait a moment until your data storage is created.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart2.png" />
</Frame>

## **Step 3. Initiate a Cluster**

Now, create a cluster to query the sample database stored in the data storage we've just set up.

1.  Go to the **Clusters** section and click the **Start a new Cluster** button. Alternatively, access the "**Use to create cluster**" option directly.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart3.png" />
</Frame>

2.  Fill in the required fields, and choose a single node for simpler environments.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart4.png" />
</Frame>

3.  Click "**Start Cluster**" and wait for it to be up and running.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart5.png" />
</Frame>

## **Step 4. Connect to Oxla SaaS**

Once your cluster is up and running, connect to Oxla SaaS using the command you got when you created the cluster or in the connection details modal. This command logs you into the Oxla database using your connection details.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart6.png" />
</Frame>

<Note>You can also connect to Oxla SaaS using Looker Studio Studio or Tableplus, which offer distinct features and interfaces that can meet your specific needs. For example, you can use Looker Studio Studio to convert data into graphs and charts based on a query's results.</Note>

## **Step 5. Querying Data**

Once connected to Oxla SaaS, you can perform queries using your chosen dataset. For example, below is a sample query to find the Top 3 Sold Parts in the eCommerce dataset.

```sql
SELECT p.p_name AS part_name, 
       SUM(l.lo_quantity) AS total_quantity_sold, 
       SUM(l.lo_revenue) AS total_revenue
FROM lineorder l
JOIN part p ON l.lo_partkey = p.p_partkey
GROUP BY p.p_name
ORDER BY total_revenue DESC
LIMIT 3;
```

The result displays the three most sold parts based on the quantity sold.

```sql
     part_name     | total_quantity_sold | total_revenue 
-------------------+---------------------+---------------
 aquamarine beige  |             3871448 |  562986438412
 aquamarine black  |             3662718 |  521680920074
 aquamarine bisque |             3692528 |  519083669350
(3 rows)
```

<Tip>Next, you can explore other datasets and run other sample queries. Please refer to the [Introduction](https://docs.oxla.com/oxla-cloud-saas/oxla-datasets/introduction-datasets) page.</Tip>

## **Step 6. Manage Your Cluster**

While your cluster is active, you can stop its operations whenever necessary. Once you stop the cluster, it won't consume any credits or funds.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart7.png" />
</Frame>

When you’re finished with your tests you can also delete the cluster. Deleting the cluster only releases the compute resources and doesn’t remove the data itself.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/quickstart8.png" />
</Frame>

<Warning>Deleting a cluster is only possible for clusters in a **STOPPED** or **FAILED** state.</Warning>


# eCommerce Dataset



## **Overview**

In this guide, you'll learn how to use the Oxla database with eCommerce datasets through various sample queries. These datasets include information about sales transactions, such as customer details, supplier data, and order details.

You'll explore how to analyze data by joining related tables and running queries to support informed decision-making for your business.

**Data Source**: [https://github.com/apache/doris/tree/master/tools/ssb-tools](https://github.com/apache/doris/tree/master/tools/ssb-tools) .

<Tip>**Prerequisite** <br /> Ensure you've created the Data Storage with the appropriate demo dataset, the Cluster is running, and you’re connected to it using the PostgreSQL client. For more details, refer to the [Quickstart - Oxla SaaS](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas) page.</Tip>

## **Datasets Structure**

Let's explore the tables and their structures to understand better and fully utilize the eCommerce dataset.

<AccordionGroup>
  <Accordion title="customer Table">
    | Attribute Name | Type    |
    | -------------- | ------- |
    | c\_custkey     | Integer |
    | c\_name        | Text    |
    | c\_address     | Text    |
    | c\_city        | Text    |
    | c\_nation      | Text    |
    | c\_region      | Text    |
    | c\_phone       | Text    |
    | c\_mktsegment  | Text    |
  </Accordion>

  <Accordion title="lineorder Table">
    | Attribute Name    | Type    |
    | ----------------- | ------- |
    | lo\_orderkey      | Integer |
    | lo\_linenumber    | Integer |
    | lo\_custkey       | Integer |
    | lo\_partkey       | Integer |
    | lo\_suppkey       | Integer |
    | lo\_orderdate     | Date    |
    | lo\_orderpriority | Text    |
    | lo\_shippriority  | Integer |
    | lo\_quantity      | Integer |
    | lo\_extendedprice | Integer |
    | lo\_ordtotalprice | Integer |
    | lo\_discount      | Integer |
    | lo\_revenue       | Integer |
    | lo\_supplycost    | Integer |
    | lo\_tax           | Integer |
    | lo\_commitdate    | Date    |
    | lo\_shipmode      | Text    |
  </Accordion>

  <Accordion title="supplier Table">
    | Attribute Name | Type    |
    | -------------- | ------- |
    | s\_suppkey     | Integer |
    | s\_name        | Text    |
    | s\_address     | Text    |
    | s\_city        | Text    |
    | s\_nation      | Text    |
    | s\_region      | Text    |
    | s\_phone       | Text    |
  </Accordion>

  <Accordion title="part Table">
    | Attribute Name | Type    |
    | -------------- | ------- |
    | p\_partkey     | Integer |
    | p\_name        | Text    |
    | p\_mfgr        | Text    |
    | p\_category    | Text    |
    | p\_brand       | Text    |
    | p\_color       | Text    |
    | p\_type        | Text    |
    | p\_size        | Integer |
    | p\_container   | Text    |
  </Accordion>
</AccordionGroup>

## **Sample Queries**

### **Sample 1: Find Customers with the Most Total Order**

This example calculates the total order quantity for each customer by joining the `customer` and `lineorder` tables.

```sql
SELECT c.c_name AS customer_name, SUM(l.lo_quantity) AS total_order_quantity
FROM customer c
JOIN lineorder l ON c.c_custkey = l.lo_custkey
GROUP BY c.c_name
ORDER BY total_order_quantity DESC
LIMIT 10;
```

The result displays the 10 customer names with the highest total order quantity.

```sql
   customer_name    | total_order_quantity 
--------------------+----------------------
 Customer#002750845 |                15982
 Customer#002399458 |                15912
 Customer#001711105 |                15809
 Customer#001709917 |                15740
 Customer#000274669 |                15682
 Customer#001900141 |                15637
 Customer#001435495 |                15574
 Customer#002980366 |                15567
 Customer#000184897 |                15494
 Customer#002495023 |                15491
(10 rows)
```

### **Sample 2: Average Order Quantity and Revenue per Customer**

In this example, we aim to retrieve the average order quantity and revenue per customer. We will use the `LIMIT` clause to find the top 5 customers based on their revenue.

```sql
SELECT c.c_name AS customer_name, 
       AVG(l.lo_quantity) AS avg_order_quantity, 
       AVG(l.lo_revenue) AS avg_order_revenue
FROM customer c
JOIN lineorder l ON c.c_custkey = l.lo_custkey
GROUP BY c.c_name
ORDER BY avg_order_revenue DESC
LIMIT 5;
```

This query displays the average order quantities and revenues for the top 5 customers.

```sql
   customer_name    | avg_order_quantity | avg_order_revenue 
--------------------+--------------------+-------------------
 Customer#002535380 | 31.348148148148148 |  4482488.65925926
 Customer#002547308 | 31.519083969465647 | 4419699.503816794
 Customer#002906426 | 29.959798994974875 | 4371241.924623116
 Customer#000640106 | 29.676470588235293 | 4370783.544117647
 Customer#002794070 | 29.681528662420384 | 4370103.968152867
(5 rows)
```

### **Sample 3: Find the Top 3 Sold Parts**

This query lists the top 3 parts by total revenue and total quantity sold.

```sql
SELECT p.p_name AS part_name, 
       SUM(l.lo_quantity) AS total_quantity_sold, 
       SUM(l.lo_revenue) AS total_revenue
FROM lineorder l
JOIN part p ON l.lo_partkey = p.p_partkey
GROUP BY p.p_name
ORDER BY total_revenue DESC
LIMIT 3;
```

It displays the 3 parts that are most sold based on the quantity sold.

```sql
     part_name     | total_quantity_sold | total_revenue 
-------------------+---------------------+---------------
 aquamarine beige  |             3871448 |  562986438412
 aquamarine black  |             3662718 |  521680920074
 aquamarine bisque |             3692528 |  519083669350
(3 rows)
```

### **Sample 4: Monthly Revenue and Order Count per Supplier**

This example shows how to calculate each supplier's monthly revenue and order count.

```sql
SELECT s.s_name AS supplier_name, 
       EXTRACT(YEAR FROM l.lo_orderdate) AS order_year,
       EXTRACT(MONTH FROM l.lo_orderdate) AS order_month,
       COUNT(*) AS order_count,
       SUM(l.lo_revenue) AS total_revenue
FROM lineorder l
JOIN supplier s ON l.lo_suppkey = s.s_suppkey
JOIN part p ON l.lo_partkey = p.p_partkey
GROUP BY s.s_name, order_year, order_month
ORDER BY order_year, order_month, total_revenue DESC
LIMIT 10;
```

You will get the total revenue for each supplier during the respective period.

```sql
   supplier_name    | order_year | order_month | order_count | total_revenue 
--------------------+------------+-------------+-------------+---------------
 Supplier#000178170 |       1992 |           1 |          61 |     272171509
 Supplier#000024596 |       1992 |           1 |          64 |     261609404
 Supplier#000056984 |       1992 |           1 |          55 |     260734222
 Supplier#000163429 |       1992 |           1 |          56 |     259933505
 Supplier#000054770 |       1992 |           1 |          59 |     259102073
 Supplier#000141166 |       1992 |           1 |          63 |     259080854
 Supplier#000005060 |       1992 |           1 |          61 |     258319232
 Supplier#000065417 |       1992 |           1 |          59 |     256780075
 Supplier#000040250 |       1992 |           1 |          59 |     256695041
 Supplier#000171886 |       1992 |           1 |          56 |     255549592
(10 rows)
```


# Introduction



## **Background**

At Oxla, we offer preloaded sample datasets as a feature of our SaaS platform. These datasets allow users to easily test our solution with practical examples from various use cases.

### **Datasets in the Onboarding Flow**

On the first login or during onboarding, users can use our custom "**Create Cluster**" form. It simplifies the initial setup and allows you to create your first cluster with sample datasets.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/intro1.png" />
</Frame>

This form includes the data storage setup and showcases pre-existing datasets available for testing so you can quickly access and play around with the sample data.

After onboarding, you can still access the demo datasets upon **Data Storage** creation to explore different options.

<Frame>
  <img height="200" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/intro2.png" />
</Frame>

## **Datasets Overview**

Check out how our database works in real-life cases with the sample data we provide. The datasets include:

### 1) eCommerce

This dataset is suitable to explore sales trends, customer behaviour, and product performance to inform business decisions.

*   **Size**: 16.41 GB.
*   **Technical Evaluation**: This dataset consists of 4 tables related to transactions such as orders, parts, suppliers, and customers. It is ideal for evaluating Oxla's capability to manage complex join queries for analytics, assessing its efficiency in indexing, performing joins, and calculating sales aggregates.

### 2) Web Traffic

Filtering, aggregation, and joins for analyzing web traffic logs and user interactions.

*   **Size**: 16.6 GB
*   **Technical Evaluation**: This dataset enables analysis by providing filtered data, ensuring smooth parsing and loading. It provides use cases for queries such as log analysis and event processing.

### 3) Urban Mobility

Access data for in-depth analysis of urban mobility trends and scalability.

*   **Size**: 41.07 GB
*   **Technical Evaluation**: Real-time data from New York's taxi service, demonstrating the use case for Urban Mobility. This dataset focuses on resource optimization through Oxla queries.

### 4) Social Media

This dataset contains records of activity and events published by social media users.

*   **Size**: 528.93 MB
*   **Technical Evaluation**: This dataset represents user activity and interactions, including posts, comments, user relationships, and engagement metrics. It helps analyze and understand user behaviour and online trends.


# Social Media Dataset



## **Overview**

In this guide, you'll learn how to use the Oxla database with Social Media datasets through various sample queries. In this case, we'll utilize the GitHub datasets, from which you can retrieve events in all GitHub repositories since 2011 in a structured format.

**Data Source**: [https://github.com/igrigorik/gharchive.org](https://github.com/igrigorik/gharchive.org) .

<Tip>**Prerequisite** <br /> Ensure you've created the Data Storage with the appropriate demo dataset, the Cluster is running, and you’re connected to it using the PostgreSQL client. For more details, refer to the [Quickstart - Oxla SaaS](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas) page.</Tip>

## **Datasets Structure**

Let's explore the tables and their structures to better understand and fully utilize the Web Traffic dataset.

<AccordionGroup>
  <Accordion title="github_events Table">
    | Attribute Name | Type                        |
    | -------------- | --------------------------- |
    | event\_id      | Bigint                      |
    | event\_type    | Text                        |
    | event\_public  | Boolean                     |
    | repo\_id       | Bigint                      |
    | payload        | JSON                        |
    | repo           | JSON                        |
    | user\_id       | Bigint                      |
    | org            | JSON                        |
    | created\_at    | Timestamp without time zone |
  </Accordion>

  <Accordion title="github_users Table">
    | Attribute Name | Type   |
    | -------------- | ------ |
    | user\_id       | Bigint |
    | url            | Text   |
    | login          | Text   |
    | avatar\_url    | Text   |
    | gravatar\_id   | Text   |
    | display\_login | Text   |
  </Accordion>
</AccordionGroup>

## **Sample Queries**

### **Sample 1: Identify the Most Active Users**

This example identifies the 10 most active users on GitHub by counting their triggered events.

```sql
SELECT u.user_id, u.login, COUNT(e.event_id) AS event_count
FROM github_users u
JOIN github_events e ON u.user_id = e.user_id
GROUP BY u.user_id, u.login
ORDER BY event_count DESC
LIMIT 10;
```

It joins the `github_users` table with the `github_events` table to show ten active users.

```sql
 user_id  |        login         | event_count 
----------+----------------------+-------------
  8517910 | LombiqBot            |       16605
 14175800 | OpenLocalizationTest |       11963
 10810283 | direwolf-github      |        4774
  3226435 | digimatic            |        2596
    57483 | tmtmtmtm             |        2338
    53164 | avsm                 |        1747
  2354108 | coveralls            |        1648
 13653959 | k8s-merge-robot      |        1458
 12490588 | suzutan0s2           |        1431
   406518 | davecramer           |        1417
(10 rows)
```

### **Sample 2: Find the Most and Least Used Events**

We want to identify the most used event and the least used event in the `github_events` table.

```sql
(
  SELECT event_type, COUNT(event_id) AS event_count, 'most used' AS usage_type
  FROM github_events
  GROUP BY event_type
  LIMIT 1
)
UNION ALL
(
  SELECT event_type, COUNT(event_id) AS event_count, 'least used' AS usage_type
  FROM github_events
  GROUP BY event_type
  LIMIT 1
);
```

This output indicates that the `PushEvent` is the most used event and `PublicEvent` is the least used event.

```sql
 event_type  | event_count | usage_type 
-------------+-------------+------------
 PushEvent   |      587617 | most used
 PublicEvent |        1140 | least used
(2 rows)
```

### **Sample 3: Analyzing Event Types Distribution per User**

In this example, we calculates the distribution of different event types each user has participated in. It’s useful for understanding what types of activities users are most involved in, which can inform decision-making.

```sql
SELECT 
    gu.user_id, 
    gu.login, 
    ge.event_type, 
    COUNT(ge.event_id) AS event_count
FROM 
    github_users gu
JOIN 
    github_events ge ON gu.user_id = ge.user_id
GROUP BY 
    gu.user_id, 
    gu.login, 
    ge.event_type
ORDER BY 
    gu.user_id, 
    event_count DESC LIMIT 20;
```

The query returns a list of users along with the types of events they used and the count of each event type.

```sql
 user_id |    login     |    event_type     | event_count 
---------+--------------+-------------------+-------------
      21 | technoweenie | IssueCommentEvent |           6
      21 | technoweenie | IssuesEvent       |           5
      21 | technoweenie | ReleaseEvent      |           1
      21 | technoweenie | CreateEvent       |           1
      22 | macournoyer  | IssueCommentEvent |           1
      22 | macournoyer  | PullRequestEvent  |           1
      22 | macournoyer  | PushEvent         |           1
      38 | atmos        | PushEvent         |           1
      45 | mojodna      | WatchEvent        |           2
      69 | rsanheim     | IssuesEvent       |           2
      78 | indirect     | IssueCommentEvent |           3
      78 | indirect     | PushEvent         |           1
      78 | indirect     | PullRequestEvent  |           1
      78 | indirect     | DeleteEvent       |           1
      81 | engineyard   | ForkEvent         |           1
      81 | engineyard   | MemberEvent       |           1
      82 | jsierles     | IssueCommentEvent |           3
      82 | jsierles     | PushEvent         |           3
      82 | jsierles     | PullRequestEvent  |           3
      85 | brixen       | IssueCommentEvent |           2
(20 rows)
```


# Urban Mobility Dataset



## **Overview**

In this guide, you'll learn how to use the Oxla database with Urban Mobility datasets through various sample queries. These datasets include time-series data from New York City Taxi and For-Hire Vehicle Data. It contains several tables, such as trips, taxi zones, and weather observations.

**Data Source**: [https://github.com/toddwschneider/nyc-taxi-data](https://github.com/toddwschneider/nyc-taxi-data) .

<Tip>**Prerequisite** <br /> Ensure you've created the Data Storage with the appropriate demo dataset, the Cluster is running, and you’re connected to it using the PostgreSQL client. For more details, refer to the [Quickstart - Oxla SaaS](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas) page.</Tip>

## **Datasets Structure**

Let's explore the tables and their structures to better understand and fully utilize the Urban Mobility dataset.

<AccordionGroup>
  <Accordion title="cab_types Table">
    | Attribute Name | Type   |
    | -------------- | ------ |
    | id             | Bigint |
    | type           | Text   |
  </Accordion>

  <Accordion title="central_park_weather_observations Table">
    | Attribute Name       | Type             |
    | -------------------- | ---------------- |
    | station\_id          | Text             |
    | station\_name        | Text             |
    | date                 | Date             |
    | precipitation        | Double precision |
    | snow\_depth          | Double precision |
    | snowfall             | Double precision |
    | max\_temperature     | Double precision |
    | min\_temperature     | Double precision |
    | average\_wind\_speed | Double precision |
  </Accordion>

  <Accordion title="fhv_bases Table">
    | Attribute Name | Type |
    | -------------- | ---- |
    | base\_number   | Text |
    | base\_name     | Text |
    | dba            | Text |
    | dba\_category  | Text |
  </Accordion>

  <Accordion title="fhv_trips Table">
    | Attribute Name         | Type                        |
    | ---------------------- | --------------------------- |
    | id                     | Bigint                      |
    | hvfhs\_license\_num    | Text                        |
    | dispatching\_base\_num | Text                        |
    | originating\_base\_num | Text                        |
    | request\_datetime      | Timestamp without time zone |
    | on\_scene\_datetime    | Timestamp without time zone |
    | pickup\_datetime       | Timestamp without time zone |
    | dropoff\_datetime      | Timestamp without time zone |
    | pickup\_location\_id   | Bigint                      |
    | dropoff\_location\_id  | Bigint                      |
    | trip\_miles            | Double precision            |
    | trip\_time             | Double precision            |
    | base\_passenger\_fare  | Double precision            |
    | tolls                  | Double precision            |
    | black\_car\_fund       | Double precision            |
    | sales\_tax             | Double precision            |
    | congestion\_surcharge  | Double precision            |
    | airport\_fee           | Double precision            |
    | tips                   | Double precision            |
    | driver\_pay            | Double precision            |
    | shared\_request        | Boolean                     |
    | shared\_match          | Boolean                     |
    | access\_a\_ride        | Boolean                     |
    | wav\_request           | Boolean                     |
    | wav\_match             | Boolean                     |
    | legacy\_shared\_ride   | Bigint                      |
    | affiliated\_base\_num  | Text                        |
  </Accordion>

  <Accordion title="fhv_trips_staging Table">
    | Attribute Name             | Type                        |
    | -------------------------- | --------------------------- |
    | hvfhs\_license\_num        | Text                        |
    | dispatching\_base\_num     | Text                        |
    | originating\_base\_num     | Text                        |
    | request\_datetime          | Timestamp without time zone |
    | on\_scene\_datetime        | Timestamp without time zone |
    | pickup\_datetime           | Timestamp without time zone |
    | dropoff\_datetime          | Timestamp without time zone |
    | pickup\_location\_id       | Bigint                      |
    | dropoff\_location\_id      | Bigint                      |
    | trip\_miles                | Double precision            |
    | trip\_time                 | Double precision            |
    | base\_passenger\_fare      | Double precision            |
    | tolls                      | Double precision            |
    | black\_car\_fund           | Double precision            |
    | sales\_tax                 | Double precision            |
    | congestion\_surcharge      | Double precision            |
    | airport\_fee               | Double precision            |
    | tips                       | Double precision            |
    | driver\_pay                | Double precision            |
    | shared\_request\_flag      | Text                        |
    | shared\_match\_flag        | Text                        |
    | access\_a\_ride\_flag      | Text                        |
    | wav\_request\_flag         | Text                        |
    | wav\_match\_flag           | Text                        |
    | shared\_ride\_flag         | Text                        |
    | affiliated\_base\_num      | Text                        |
    | legacy\_shared\_ride\_flag | Text                        |
  </Accordion>

  <Accordion title="green_tripdata_staging Table">
    | Attribute Name          | Type                        |
    | ----------------------- | --------------------------- |
    | id                      | Bigint                      |
    | vendor\_id              | Bigint                      |
    | lpep\_pickup\_datetime  | Timestamp without time zone |
    | lpep\_dropoff\_datetime | Timestamp without time zone |
    | store\_and\_fwd\_flag   | Text                        |
    | rate\_code\_id          | Bigint                      |
    | dropoff\_location\_id   | Bigint                      |
    | congestion\_surcharge   | Double precision            |
    | passenger\_count        | Bigint                      |
    | trip\_distance          | Double precision            |
    | fare\_amount            | Double precision            |
    | extra                   | Double precision            |
    | mta\_tax                | Double precision            |
    | tip\_amount             | Double precision            |
    | tolls\_amount           | Double precision            |
    | ehail\_fee              | Double precision            |
    | improvement\_surcharge  | Double precision            |
    | total\_amount           | Double precision            |
    | payment\_type           | Bigint                      |
    | trip\_type              | Bigint                      |
    | pickup\_location\_id    | Bigint                      |
  </Accordion>

  <Accordion title="hvfhs_licenses Table">
    | Attribute Name  | Type |
    | --------------- | ---- |
    | license\_number | Text |
    | company\_name   | Text |
  </Accordion>

  <Accordion title="nyct2010 Table">
    | Attribute Name | Type             |
    | -------------- | ---------------- |
    | gid            | Bigint           |
    | ctlabel        | Text             |
    | borocode       | Text             |
    | boroname       | Text             |
    | ct2010         | Text             |
    | boroct2010     | Text             |
    | cdeligibil     | Text             |
    | ntacode        | Text             |
    | ntaname        | Text             |
    | puma           | Text             |
    | shape\_leng    | Double precision |
    | shape\_area    | Double precision |
    | geom           | Text             |
  </Accordion>

  <Accordion title="nyct2010_taxi_zones_mapping Table">
    | Attribute Name           | Type             |
    | ------------------------ | ---------------- |
    | nyct2010\_gid            | Bigint           |
    | taxi\_zone\_location\_id | Integer          |
    | overlap                  | Double precision |
  </Accordion>

  <Accordion title="spatial_ref_sys Table">
    | Attribute Name | Type   |
    | -------------- | ------ |
    | srid           | Bigint |
    | auth\_name     | Text   |
    | auth\_srid     | Bigint |
    | srtext         | Text   |
    | proj4text      | Text   |
  </Accordion>

  <Accordion title="trips Table">
    | Attribute Name         | Type                        |
    | ---------------------- | --------------------------- |
    | id                     | Bigint                      |
    | cab\_type\_id          | Bigint                      |
    | vendor\_id             | Bigint                      |
    | pickup\_datetime       | Timestamp without time zone |
    | dropoff\_datetime      | Timestamp without time zone |
    | store\_and\_fwd\_flag  | Boolean                     |
    | rate\_code\_id         | Bigint                      |
    | pickup\_longitude      | Double precision            |
    | pickup\_latitude       | Double precision            |
    | dropoff\_longitude     | Double precision            |
    | dropoff\_latitude      | Double precision            |
    | passenger\_count       | Bigint                      |
    | trip\_distance         | Double precision            |
    | fare\_amount           | Double precision            |
    | extra                  | Double precision            |
    | mta\_tax               | Double precision            |
    | tip\_amount            | Double precision            |
    | tolls\_amount          | Double precision            |
    | ehail\_fee             | Double precision            |
    | improvement\_surcharge | Double precision            |
    | congestion\_surcharge  | Double precision            |
    | airport\_fee           | Double precision            |
    | total\_amount          | Double precision            |
    | payment\_type          | Bigint                      |
    | trip\_type             | Bigint                      |
    | pickup\_nyct2010\_gid  | Bigint                      |
    | dropoff\_nyct2010\_gid | Bigint                      |
    | pickup\_location\_id   | Bigint                      |
    | dropoff\_location\_id  | Bigint                      |
  </Accordion>

  <Accordion title="taxi_zones Table">
    | Attribute Name | Type             |
    | -------------- | ---------------- |
    | gid            | Bigint           |
    | objectid       | Bigint           |
    | shape\_leng    | Double precision |
    | shape\_area    | Double precision |
    | zone           | Text             |
    | locationid     | Integer          |
    | borough        | Text             |
    | geom           | Text             |
  </Accordion>

  <Accordion title="uber_trips_2014 Table">
    | Attribute Name    | Type                        |
    | ----------------- | --------------------------- |
    | id                | Bigint                      |
    | pickup\_datetime  | Timestamp without time zone |
    | pickup\_latitude  | Double precision            |
    | pickup\_longitude | Double precision            |
    | base\_code        | Text                        |
  </Accordion>

  <Accordion title="yellow_tripdata_staging Table">
    | Attribute Name          | Type                        |
    | ----------------------- | --------------------------- |
    | id                      | Bigint                      |
    | vendor\_id              | Text                        |
    | tpep\_pickup\_datetime  | Timestamp without time zone |
    | tpep\_dropoff\_datetime | Timestamp without time zone |
    | passenger\_count        | Bigint                      |
    | trip\_distance          | Double precision            |
    | pickup\_longitude       | Double precision            |
    | pickup\_latitude        | Double precision            |
    | rate\_code\_id          | Text                        |
    | store\_and\_fwd\_flag   | Text                        |
    | dropoff\_longitude      | Double precision            |
    | dropoff\_latitude       | Double precision            |
    | pickup\_location\_id    | Bigint                      |
    | dropoff\_location\_id   | Bigint                      |
    | payment\_type           | Text                        |
    | fare\_amount            | Double precision            |
    | extra                   | Double precision            |
    | mta\_tax                | Double precision            |
    | tip\_amount             | Double precision            |
    | tolls\_amount           | Double precision            |
    | improvement\_surcharge  | Double precision            |
    | total\_amount           | Double precision            |
    | congestion\_surcharge   | Double precision            |
    | airport\_fee            | Double precision            |
  </Accordion>
</AccordionGroup>

## **Sample Queries**

### **Sample 1: Number of Trips by Payment Type**

This example shows the number of trips for each payment type used in the dataset.

```sql
SELECT payment_type, count(*) AS count
FROM trips
GROUP BY payment_type
ORDER BY count DESC;
```

The query displays number of trips grouped by payment type.

```sql
 payment_type |   count   
--------------+-----------
            1 | 147533966
            2 | 147159834
            3 |    752296
            4 |    242825
            5 |    150926
              |     14580
(6 rows)
```

### **Sample 2: Calculate Revenue per Pickup Point**

This example calculates the top 10 pickup locations with the highest revenue.

```sql
SELECT t.pickup_location_id AS pickup_location_id, 
       tz."zone" AS location_name,
       COUNT(*) AS trip_count,
       SUM(t.total_amount) AS total_revenue 
FROM trips t
JOIN taxi_zones tz ON t.pickup_location_id = tz.locationid 
GROUP BY t.pickup_location_id, tz."zone" 
ORDER BY total_revenue DESC 
LIMIT 10;
```

The result displays the top 10 pickup locations, with JFK Airport having the highest revenue.

```sql
 pickup_location_id |       location_name       | trip_count |   total_revenue    
--------------------+---------------------------+------------+--------------------
                132 | JFK Airport               |    4781775 | 240929978.91028678
                138 | LaGuardia Airport         |    5935988 | 219636305.66008496
                161 | Midtown Center            |    9978810 | 125652682.01979701
                 79 | East Village              |    9407751 | 119170547.52983798
                162 | Midtown East              |    9297167 | 118483924.92982587
                 48 | Clinton East              |    8872713 | 112228413.58982424
                170 | Murray Hill               |    9161159 | 111683576.97983585
                237 | Upper East Side South     |   10378670 | 111360934.71979024
                234 | Union Sq                  |    9156879 | 109465941.75984423
                230 | Times Sq/Theatre District |    9522197 | 109449951.09985997
(10 rows)
```

### **Sample 3: Manhattan's Most Popular Cabs**

This example provides insights into Manhattan's most popular cabs by showing key statistics for each cab type.

```sql
SELECT c.type AS cab_type,
       MIN(t.trip_distance) AS shortest_distance,
       MAX(t.trip_distance) AS farthest_distance,
       AVG(t.trip_distance) AS average_distance,
       AVG(t.fare_amount) AS average_fare,
       SUM(t.fare_amount) AS total_fare
FROM trips t
JOIN cab_types c ON t.cab_type_id = c.id
GROUP BY c.type
ORDER BY c.type;
```

The result shows the shortest and farthest trip distances, average trip distance, and average fare for each cab type.

```sql
 cab_type | shortest_distance | farthest_distance | average_distance  |    average_fare    |    total_fare     
----------+-------------------+-------------------+-------------------+--------------------+-------------------
 green    |                 0 |               640 | 2.846760430722446 | 12.214111199481835 | 154370169.6499999
 yellow   |         -21474834 |          16200370 | 5.955657407792438 | 11.567361225195867 |  3276058919.61685
(2 rows)
```

### **Sample 4: How Weather Impacts the Transportation Demand Analysis**

Here we analyze the average temperature and wind speed from January to April on the 1st and 2nd of each month.

```sql
SELECT
    w."date" AS pickup_date,
    (w.max_temperature + w.min_temperature) / 2 AS average_temperature,
    w.average_wind_speed,
    COUNT(t.id) AS number_of_trips
FROM
    central_park_weather_observations w
LEFT JOIN
    trips t ON w."date" = t.pickup_datetime::date
WHERE
    w."date" IN (
        '2009-01-01', '2009-01-02',
        '2009-02-01', '2009-02-02',
        '2009-03-01', '2009-03-02',
        '2009-04-01', '2009-04-02'
    )
GROUP BY
    w."date", w.max_temperature, w.min_temperature, w.average_wind_speed
ORDER BY
    w."date";
```

The output helps us understand how weather conditions from January to April impact the number of trips taken on specific dates. It shows that days with higher temperatures and stronger winds see more trips happening.

```sql
 pickup_date | average_temperature | average_wind_speed | number_of_trips 
-------------+---------------------+--------------------+-----------------
 2009-01-01  |                20.5 |              11.18 |           65888
 2009-01-02  |                28.5 |               6.26 |           75481
 2009-02-01  |                  39 |               7.61 |           86019
 2009-02-02  |                43.5 |               5.14 |           80808
 2009-03-01  |                  32 |               9.84 |           86320
 2009-03-02  |                  22 |              10.96 |           65607
 2009-04-01  |                  46 |               6.71 |           77604
 2009-04-02  |                  54 |               5.59 |           99310
(8 rows)
```


# Web Traffic Dataset



## **Overview**

In this guide, you'll learn how to use the Oxla database with Web Traffic datasets through various sample queries. These datasets contain essential traffic information, including user activity, device, and browser information.

**Data Source**: [https://github.com/ClickHouse/ClickBench](https://github.com/ClickHouse/ClickBench) .

<Tip>**Prerequisite** <br /> Ensure you've created the Data Storage with the appropriate demo dataset, the Cluster is running, and you’re connected to it using the PostgreSQL client. For more details, refer to the [Quickstart - Oxla SaaS](https://docs.oxla.com/oxla-cloud-saas/quickstart-oxla-saas) page.</Tip>

## **Datasets Structure**

Let's explore the tables and their structures to understand better and fully utilize the Web Traffic dataset.

<Accordion title="hits Table">
  | Attribute Name      | Type                        |
  | ------------------- | --------------------------- |
  | watchid             | Bigint                      |
  | javaenable          | Integer                     |
  | title               | Text                        |
  | goodevent           | Integer                     |
  | eventtime           | Timestamp without time zone |
  | eventdate           | Date                        |
  | counterid           | Integer                     |
  | clientip            | Integer                     |
  | regionid            | Integer                     |
  | userid              | Bigint                      |
  | counterclass        | Integer                     |
  | os                  | Integer                     |
  | useragent           | Integer                     |
  | url                 | Text                        |
  | referer             | Text                        |
  | isrefresh           | Integer                     |
  | referercategoryid   | Integer                     |
  | refererregionid     | Integer                     |
  | urlcategoryid       | Integer                     |
  | urlregionid         | Integer                     |
  | resolutionwidth     | Integer                     |
  | resolutionheight    | Integer                     |
  | resolutiondepth     | Integer                     |
  | flashmajor          | Integer                     |
  | flashminor          | Integer                     |
  | flashminor2         | Text                        |
  | netmajor            | Integer                     |
  | netminor            | Integer                     |
  | useragentmajor      | Integer                     |
  | useragentminor      | Text                        |
  | cookieenable        | Integer                     |
  | javascriptenable    | Integer                     |
  | ismobile            | Integer                     |
  | mobilephone         | Integer                     |
  | mobilephonemodel    | Text                        |
  | params              | Text                        |
  | ipnetworkid         | Integer                     |
  | traficsourceid      | Integer                     |
  | searchengineid      | Integer                     |
  | searchphrase        | Text                        |
  | advengineid         | Integer                     |
  | isartifical         | Integer                     |
  | windowclientwidth   | Integer                     |
  | windowclientheight  | Integer                     |
  | clienttimezone      | Integer                     |
  | clienteventtime     | Timestamp without time zone |
  | silverlightversion1 | Integer                     |
  | silverlightversion2 | Integer                     |
  | silverlightversion3 | Integer                     |
  | silverlightversion4 | Integer                     |
  | pagecharset         | Text                        |
</Accordion>

## **Sample Queries**

### **Sample 1: Top 10 Pages by Hits**

This query selects the top 10 pages based on the number of hits they received.

```sql
SELECT title, COUNT(*) AS TotalHits
FROM hits
GROUP BY title
ORDER BY TotalHits DESC
LIMIT 10;
```

This result displays the top 10 pages along with the total number of hits each page received.

```sql
                                                                            title                                                                             | totalhits 
--------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------
                                                                                                                                                              |  14910417
 Djunglish.RU > Приобрете и б/у. Стихи                                                                                                                        |   1652089
 Прог                                                                                                                                                         |   1158515
 Яндекс.Видео дня. Лента новый - сравных. Автопоиск по лучшей цены - Форум клуба Chevrolett, номера Соборудованном участные товая ул., д. 17, 3.5 - Свободная |    961538
 FLATY.RU - Лучшей цене, в пообедитино — Trashbox.ru#photograd.info: фут-фетиш, женщин - Яндекс.Афиша, 28 - Cherofloor=#ff99> <br>кто хорошее планшетные      |    832991
 Новостровск, ФОТО - Форум Амур.инфо, 8 из 15 ярко-розочках - сравнение                                                                                       |    809519
 Шарарту п.... Москве                                                                                                                                         |    730100
 Поиск по продажа                                                                                                                                             |    572331
 Участи NEWSru                                                                                                                                                |    486009
 Шарарансляция коду                                                                                                                                           |    420539
(10 rows)
```

### **Sample 2: Find Most Active Regions**

This query extracts the most active regions ordered by the total number of hits.

```sql
SELECT regionid, COUNT(*) AS TotalHits
FROM hits
GROUP BY regionid
ORDER BY TotalHits DESC
LIMIT 10;
```

This helps to pinpoint regions where the highest volume of interactions or activities has occurred.

```sql
 regionid | totalhits 
----------+-----------
      229 |  18295832
        2 |   6687587
      208 |   4261812
      169 |   3320229
       32 |   1843518
       34 |   1792369
      184 |   1755192
       42 |   1542717
      107 |   1516690
       51 |   1435578
(10 rows)
```

### **Sample 3: Hourly Activity Analysis**

This query uses the `DATE_TRUNC` function to aggregate user activity by hour.

```sql
SELECT DATE_TRUNC('hour', EventTime) AS HourlyActivity,
COUNT(*) AS TotalHits
FROM hits
GROUP BY HourlyActivity
ORDER BY TotalHits DESC LIMIT 30;
```

The result displays the total hits aggregated by hour, which can help you determine the peak usage times.

```sql
   hourlyactivity    | totalhits 
---------------------+-----------
 2013-07-21 00:00:00 |    698815
 2013-07-20 22:00:00 |    698653
 2013-07-20 20:00:00 |    697103
 2013-07-21 19:00:00 |    696980
 2013-07-20 21:00:00 |    696781
 2013-07-21 16:00:00 |    696039
 2013-07-21 15:00:00 |    694468
 2013-07-21 18:00:00 |    694037
 2013-07-21 12:00:00 |    693485
 2013-07-21 07:00:00 |    693146
 2013-07-21 04:00:00 |    693142
 2013-07-21 11:00:00 |    693106
 2013-07-21 13:00:00 |    692814
 2013-07-21 03:00:00 |    692689
 2013-07-21 05:00:00 |    692160
 2013-07-21 02:00:00 |    691713
 2013-07-21 17:00:00 |    691100
 2013-07-21 06:00:00 |    690457
 2013-07-21 10:00:00 |    689752
 2013-07-21 14:00:00 |    689493
 2013-07-20 23:00:00 |    689349
 2013-07-21 01:00:00 |    689090
 2013-07-21 09:00:00 |    688810
 2013-07-21 08:00:00 |    685090
 2013-07-09 18:00:00 |    573479
 2013-07-09 17:00:00 |    573035
 2013-07-08 21:00:00 |    572060
 2013-07-09 00:00:00 |    565040
 2013-07-08 22:00:00 |    564743
 2013-07-09 12:00:00 |    564698
(30 rows)
```


# pg_attrdef



## Overview

The `pg_attrdef` stores information about column default values. It mimics the PostgreSQL system catalog [pg\_attrdef](https://www.postgresql.org/docs/current/catalog-pg-attrdef.html).

<Warning>Please note that Oxla doesn’t support the custom types.</Warning>

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_attrdef` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_attrdef`:

| Column    | Type     | Description                                                      |
| --------- | -------- | ---------------------------------------------------------------- |
| `oid`     | `int`    | This column represents the row identifier                        |
| `adrelid` | `int`    | This column represents the table to which this column belongs    |
| `adnum`   | `int`    | This column represents the number of the column within the table |
| `adbin`   | `string` | This column represents the default value for the column          |


# pg_constraint



## Overview

The `pg_constraint` stores information about table constraints. It mimics the PostgreSQL system catalog [pg\_constraint](https://www.postgresql.org/docs/current/catalog-pg-constraint.html).

<Warning>Please note that Oxla doesn’t support the custom types.</Warning>

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_constraint` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_constraint`:

| Column           | Type     | Description                                                        |
| ---------------- | -------- | ------------------------------------------------------------------ |
| `oid`            | `int`    | This column represents the row identifier                          |
| `conname`        | `string` | This column represents the constraint name                         |
| `connamespace`   | `int`    | This column represents the namespace that contains this constraint |
| `contype`        | `string` | **unused**                                                         |
| `condeferrable`  | `bool`   | **unused**                                                         |
| `condeferred`    | `bool`   | **unused**                                                         |
| `convalidated`   | `bool`   | **unused**                                                         |
| `conrelid`       | `int`    | **unused**                                                         |
| `contypid`       | `int`    | **unused**                                                         |
| `conindid`       | `int`    | **unused**                                                         |
| `conparentid`    | `int`    | **unused**                                                         |
| `confrelid`      | `int`    | **unused**                                                         |
| `confupdtype`    | `string` | **unused**                                                         |
| `confdeltype`    | `string` | **unused**                                                         |
| `confmatchtype`  | `string` | **unused**                                                         |
| `conislocal`     | `bool`   | **unused**                                                         |
| `coninhcount`    | `int`    | **unused**                                                         |
| `connoinherit`   | `bool`   | **unused**                                                         |
| `conkey`         | `string` | **unused**                                                         |
| `confkey`        | `string` | **unused**                                                         |
| `conpfeqop`      | `string` | **unused**                                                         |
| `conppeqop`      | `string` | **unused**                                                         |
| `conffeqop`      | `string` | **unused**                                                         |
| `confdelsetcols` | `string` | **unused**                                                         |
| `conexclop`      | `string` | **unused**                                                         |
| `conbin`         | `string` | **unused**                                                         |


# pg_depend



## Overview

The `pg_depend` tracks relationships between database objects, such as tables, columns, constraints, and indexes. It mimics the PostgreSQL system catalog [pg\_depend](https://www.postgresql.org/docs/current/catalog-pg-depend.html).

<Warning>Please note that Oxla doesn’t support the custom types.</Warning>

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_depend` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_depend`:

| Column        | Type     | Description                                                                      |
| ------------- | -------- | -------------------------------------------------------------------------------- |
| `classid`     | `int`    | This column represents the OID of the system catalog the dependent object is in  |
| `objid`       | `int`    | This column represents the OID of the specific dependent object                  |
| `objsubid`    | `int`    | This column represents the column number for a table column                      |
| `refclassid`  | `int`    | This column represents the OID of the system catalog the referenced object is in |
| `refobjid`    | `int`    | This column represents the OID of the specific referenced object                 |
| `refobjsubid` | `int`    | This column represents the column number for a table column                      |
| `deptype`     | `string` | **unused**                                                                       |


# pg_description



## Overview

The `pg_description` stores descriptions (comments) for each database object. It mimics the PostgreSQL system catalog [pg\_description](https://www.postgresql.org/docs/current/catalog-pg-description.html).

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_description` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_description`:

| Column        | Type   | Description                                                                                                                              |
| ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `objoid`      | `int`  | This column represents the OID (Object ID) of the object for which the description is stored                                             |
| `classoid`    | `int`  | This column represents the OID of the table that the object belongs to                                                                   |
| `objsubid`    | `int`  | If an object has multiple parts (for example, columns in a table), `objsubid` specifies the column number. If not used, this is set to 0 |
| `description` | `text` | This column represents the description for the specified object                                                                          |


# pg_index



## Overview

The `pg_index` stores information about indexes on tables. It mimics the PostgreSQL system catalog [pg\_index](https://www.postgresql.org/docs/current/catalog-pg-index.html).

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_index` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_index`:

| Column                | Type   | Description                                                                       |
| --------------------- | ------ | --------------------------------------------------------------------------------- |
| `indexrelid`          | `int`  | This column represents OID of the index                                           |
| `indrelid`            | `int`  | This column represents OID (Object ID) of the table on which the index is defined |
| `indnatts`            | `int`  | This column represents number of columns in the index                             |
| `indnkeyatts`         | `int`  | This column represents number of key columns in the index                         |
| `indisunique`         | `bool` | The default value is `false`                                                      |
| `indnullsnotdistinct` | `bool` | *unused*                                                                          |
| `indisprimary`        | `bool` | *unused*                                                                          |
| `indisexclusion`      | `bool` | *unused*                                                                          |
| `indimmediate`        | `bool` | *unused*                                                                          |
| `indisclustered`      | `bool` | *unused*                                                                          |
| `indisvalid`          | `bool` | *unused*                                                                          |
| `indcheckxmin`        | `bool` | *unused*                                                                          |
| `indisready`          | `bool` | *unused*                                                                          |
| `indislive`           | `bool` | *unused*                                                                          |
| `indisreplident`      | `bool` | *unused*                                                                          |
| `indkey`              | `int`  | *unused*                                                                          |
| `indcollation`        | `int`  | *unused*                                                                          |
| `indclass`            | `int`  | *unused*                                                                          |
| `indoption`           | `int`  | *unused*                                                                          |
| `indexprs`            | `int`  | *unused*                                                                          |
| `indpred`             | `int`  | *unused*                                                                          |


# pg_namespace



## Overview

The `pg_namespace` contains information about schema definitions. It mimics the PostgreSQL system catalog [pg\_namespace](https://www.postgresql.org/docs/current/catalog-pg-namespace.html).

<Note>To learn more about Schema and how it is managed in Oxla, please refer to the [Schema documentation](https://docs.oxla.com/3-sql-reference/schema).</Note>

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_namespace` are applicable to every type of relation.</Note>

The `pg_namespace` catalog has the following key columns:

| Column     | Type   | Description                                                                          |
| ---------- | ------ | ------------------------------------------------------------------------------------ |
| `oid`      | `int`  | This column represents the Object ID, a unique identifier assigned to each namespace |
| `nspname`  | `text` | This column represents the name of the namespace                                     |
| `nspowner` | `int`  | This column represents the owner of the namespace                                    |
| `nspacl`   | `text` | *unused*                                                                             |

## Example

### 1. Create a Schema

In this example, we create "sales" and "hr" schemas using the query below:

```sql
CREATE SCHEMA sales;
CREATE SCHEMA hr;
```

The successful result would look like this:

```sql
COMPLETE
COMPLETE
```

### 2. View Schema Definitions

We then use a `SELECT` statement on the `pg_namespace` catalog to show the schema definitions.

```sql
SELECT nspname AS schema_name, oid AS schema_oid
FROM pg_namespace;
```

The result shows the list of schemas and its ID, as shown below:

```sql
 schema_name | schema_oid 
-------------+------------
 public      |          0
 sales       |          3
 hr          |          4
```


# pg_settings



## Overview

The `pg_settings` displays the configuration settings for the current session. It mimics the PostgreSQL system catalog [pg\_settings](https://www.postgresql.org/docs/current/catalog-pg-db-role-setting.html).

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_settings` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_settings`:

| Column            | Type   | Description                                                      |
| ----------------- | ------ | ---------------------------------------------------------------- |
| `name`            | `text` | This column represents the run-time configuration parameter name |
| `setting`         | `text` | This column represents the current value of the parameter        |
| `unit`            | `text` | *Unused*.                                                        |
| `category`        | `text` | *Unused*.                                                        |
| `short_desc`      | `text` | *Unused*.                                                        |
| `extra_desc`      | `text` | *Unused*.                                                        |
| `context`         | `text` | *Unused*.                                                        |
| `vartype`         | `text` | *Unused*.                                                        |
| `source`          | `text` | *Unused*.                                                        |
| `min_val`         | `text` | *Unused*.                                                        |
| `max_val`         | `text` | *Unused*.                                                        |
| `enumvals`        | `text` | *Unused*.                                                        |
| `boot_val`        | `text` | *Unused*.                                                        |
| `reset_val`       | `text` | *Unused*.                                                        |
| `sourcefile`      | `text` | *Unused*.                                                        |
| `sourceline`      | `int`  | *Unused*.                                                        |
| `pending_restart` | `bool` | *Unused*.                                                        |

## Example

To retrieve information from the pg\_settings catalog, you can execute a query like:

```sql
SELECT name, setting FROM pg_settings;
```

You will get the run-time configuration values as shown below.

```sql
     name      | setting 
----------------+---------
 max_index_keys | 32
```


# pg_statio_user_tables



## Overview

The `pg_statio_user_tables` contains one row for each user table in the current database, showing statistics columns filled with zeros.

## Columns

<Note>This table is designed for compatibility with tools that require PostgreSQL system tables, so it mostly has dummy data. Please note that not all columns in `pg_statio_user_tables` are applicable to every type of relation.</Note>

The following columns are available for querying in `pg_statio_user_tables` :

| Column            | Type   | Description                                                  |
| ----------------- | ------ | ------------------------------------------------------------ |
| `relid`           | `int`  | This column represents the table ID                          |
| `relname`         | `text` | This column represents the table name                        |
| `schemaname`      | `text` | This column represents the schema name that this table is in |
| `heap_blks_read`  | `int`  | *unused*                                                     |
| `heap_blks_hit`   | `int`  | *unused*                                                     |
| `idx_blks_read`   | `int`  | *unused*                                                     |
| `idx_blks_hit`    | `int`  | *unused*                                                     |
| `toast_blks_read` | `int`  | *unused*                                                     |
| `toast_blks_hit`  | `int`  | *unused*                                                     |
| `tidx_blks_read`  | `int`  | *unused*                                                     |
| `tidx_blks_hit`   | `int`  | *unused*                                                     |

## Example

1.  Create a new table.

```sql
CREATE TABLE example_table (
    data text,
    cluster text,
    storage int
);
```

2.  Run the query combined with a `WHERE` clause to look up based on the table name (`relname`).

```sql
SELECT relid, schemaname, relname FROM pg_statio_user_tables;
```

3.  It will return the table size in bytes.

```sql
 relid | schemaname |  relname    
-------+------------+---------------
 16384 | public     | job          
 16385 | public     | example_table
(2 rows)
```


# Welcome

Discover everything you need to know about Oxla right here, right now!

<img className="block dark:hidden" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/light1.png" alt="Hero Light" />

<img className="hidden dark:block" src="https://mintlify.s3-us-west-1.amazonaws.com/oxla/assets/dark1.png" alt="Hero Dark" />

<CardGroup cols={3}>
  <Card
    title="Getting Started"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 124.32 135.46">
       <g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path d="M48,135.46a3,3,0,0,1-1.9-.69,2.92,2.92,0,0,1,.32-4.69c14.65-9.46,25.82-21.68,26-28.42a1.94,1.94,0,0,1,3.88.08c-.19,8.34-11.15,19.72-22.72,28.16,17.37-5.51,30.92-13.12,38.51-21.7,8.8-9.92,2.87-17.54-.09-20.35A1.94,1.94,0,0,1,94.64,85c6.07,5.78,9.34,15.57.33,25.75-8.86,10-25.15,18.7-45.86,24.49l-.33.09A3,3,0,0,1,48,135.46Zm.53-2.12h0Z"/><path d="M2.91,97.63A2.88,2.88,0,0,1,1.08,97,2.92,2.92,0,0,1,0,94.37l0-.32C2.42,72.67,8.38,55.19,16.82,44.83c6.12-7.5,12.51-8.29,16.8-7.63,7.4,1.13,13,7.14,14.51,10.85l-3.61,1.44C43.36,46.57,38.6,41.88,33,41c-4.78-.73-9.22,1.37-13.2,6.26C12.59,56.16,7.27,70.78,4.64,88.83c7.12-14.12,17.41-27,25.58-27.14,2.26,0,5.33.83,7.43,5.21l-3.49,1.68c-1.32-2.74-2.86-3-3.87-3-6.37.12-17.44,13.71-24.69,30.31a2.88,2.88,0,0,1-2,1.67A3.25,3.25,0,0,1,2.91,97.63Zm1-2.83v0Z"/><path class="cls-1" d="M11.26,135,11,135a1.93,1.93,0,0,1-1.59-1.39C3,110.86,13.18,104.48,22.81,101.47a1.94,1.94,0,1,1,1.15,3.7c-5.63,1.76-15.84,5-11.72,23.88,2.64-2.16,5.75-2.71,8.59-3.22,5.35-1,10-1.78,12.38-12.5a1.94,1.94,0,0,1,3.79.86c-3,13.23-9.92,14.47-15.49,15.46-3.65.65-6.54,1.17-8.61,4.48A1.94,1.94,0,0,1,11.26,135Z"/><path d="M42.79,112.14l-.82-.59c-3.18-2.29-7-5.38-10.49-8.46h0A90,90,0,0,1,24,95.67l-.63-.73.2-1A139.56,139.56,0,0,1,42.08,51.72C55,31.77,78.88,6.78,119.33,1a4.45,4.45,0,0,1,3.51,1.23,4.17,4.17,0,0,1,1.47,3.23c-2.11,41.26-23.91,68-41.82,83.13-19.37,16.38-38,22.94-38.75,23.21Zm-8.73-12c3.08,2.73,6.44,5.46,9.35,7.61A136.27,136.27,0,0,0,80.09,85.55c17.27-14.64,38.28-40.43,40.34-80.19a1.11,1.11,0,0,0-.63-.5C88.61,9.31,63.56,25.75,45.41,53.72a140.51,140.51,0,0,0-17.8,40.14C28.64,95,30.86,97.31,34.06,100.19Z"/><path class="cls-1" d="M93.59,43.93A9.41,9.41,0,1,1,103,34.52,9.42,9.42,0,0,1,93.59,43.93Zm0-14.94a5.53,5.53,0,1,0,5.53,5.53A5.54,5.54,0,0,0,93.59,29Z"/><path class="cls-1" d="M72.09,67.81A9.41,9.41,0,1,1,81.5,58.4,9.42,9.42,0,0,1,72.09,67.81Zm0-14.94a5.53,5.53,0,1,0,5.53,5.53A5.54,5.54,0,0,0,72.09,52.87Z"/><path class="cls-1" d="M3.83,33.82a1.94,1.94,0,0,1-1.27-3.41L21,14.56a1.94,1.94,0,1,1,2.53,2.94L5.09,33.35A1.92,1.92,0,0,1,3.83,33.82Z"/><path class="cls-1" d="M107.73,85.75a1.94,1.94,0,0,1-1.27-3.41L120.87,70a1.94,1.94,0,1,1,2.53,2.94L109,85.28A1.92,1.92,0,0,1,107.73,85.75Z"/><path class="cls-1" d="M92.46,135a1.94,1.94,0,0,1-1.27-3.41l29.35-25.2a1.94,1.94,0,1,1,2.53,2.94l-29.35,25.2A1.92,1.92,0,0,1,92.46,135Z"/><path class="cls-1" d="M27,29.87a1.94,1.94,0,0,1-1.27-3.41L56,.47a1.94,1.94,0,1,1,2.53,2.94l-30.27,26A1.92,1.92,0,0,1,27,29.87Z"/></g></g>
     </svg>
    }
    href="https://docs.oxla.com/2-run-oxla/run-oxla-in-2-minutes"
  >
    In just a few steps, you'll be up and running with Oxla.
  </Card>

  <Card
    title="Oxla Cloud"
    icon={
     <svg
       version='1.0'
       xmlns='http://www.w3.org/2000/svg'
       viewBox='0 0 512.000000 512.000000'
       preserveAspectRatio='xMidYMid meet'
     >
    <g
       transform='translate(0.000000,512.000000) scale(0.100000,-0.100000)'
       class='cls-1'
       stroke='none'
     >
    <path d="M3115 4806 c-133 -31 -252 -85 -349 -158 l-59 -45 -62 23 c-119 43
    -216 57 -364 51 -144 -5 -232 -23 -358 -73 -205 -81 -380 -236 -473 -419 l-32
    -62 -73 -7 c-153 -14 -264 -65 -371 -172 -98 -97 -164 -239 -164 -354 0 -24
    -5 -29 -33 -35 -50 -11 -148 -58 -214 -103 -132 -90 -243 -249 -283 -408 -24
    -94 -26 -251 -5 -342 48 -204 198 -389 390 -482 123 -60 180 -70 413 -70 l202
    0 0 -290 0 -290 -158 0 -157 0 -22 48 c-34 74 -78 118 -150 154 -56 28 -77 32
    -139 32 -63 0 -81 -4 -140 -34 -233 -119 -233 -441 0 -560 59 -30 77 -34 140
    -34 128 0 234 68 289 186 l21 47 214 3 c211 3 214 3 233 27 18 22 19 44 19
    367 l0 344 225 0 225 0 0 -397 0 -398 -146 -146 -147 -147 -45 20 c-68 30
    -172 29 -243 -4 -121 -55 -180 -142 -187 -274 -4 -72 -1 -89 21 -137 34 -74
    88 -131 155 -164 78 -38 192 -39 267 -3 63 31 124 91 156 155 32 65 34 188 5
    253 l-20 43 156 157 c86 86 161 167 167 179 8 15 11 155 11 442 l0 421 225 0
    225 0 0 -614 0 -615 -55 -25 c-190 -87 -246 -335 -110 -494 43 -50 141 -100
    211 -108 63 -8 151 16 210 57 199 137 170 444 -52 546 l-54 24 0 615 0 614
    225 0 225 0 0 -421 c0 -287 3 -427 11 -442 6 -12 80 -92 165 -177 l153 -155
    -19 -55 c-54 -154 7 -311 150 -389 59 -33 72 -36 145 -36 67 0 89 5 137 28
    105 51 168 146 176 263 9 136 -54 246 -173 305 -57 28 -76 32 -139 32 -50 -1
    -87 -7 -118 -21 l-45 -20 -147 147 -146 146 0 398 0 397 230 0 230 0 0 -343 0
    -344 23 -21 c22 -21 31 -22 233 -22 l209 0 19 -47 c26 -62 87 -128 151 -161
    43 -23 62 -27 140 -27 78 0 97 4 140 27 60 32 114 87 146 148 34 65 34 205 1
    268 -37 69 -87 117 -154 148 -163 74 -345 5 -421 -158 l-22 -48 -157 0 -158 0
    0 288 0 289 95 6 c440 29 823 364 911 797 22 109 15 330 -14 435 -74 272 -232
    471 -474 594 -53 27 -115 55 -137 62 -32 9 -43 18 -47 38 -23 112 -41 168 -79
    247 -68 140 -147 233 -288 338 -51 37 -208 110 -282 131 -83 23 -329 29 -410
    11z m390 -156 c129 -41 222 -96 315 -190 123 -122 185 -248 209 -423 5 -38 15
    -75 21 -82 6 -8 42 -24 78 -36 226 -74 398 -219 492 -413 70 -145 84 -212 84
    -381 0 -132 -2 -146 -33 -235 -96 -281 -316 -488 -601 -563 l-85 -22 -1555 0
    -1555 0 -65 23 c-198 71 -340 224 -385 413 -73 312 137 628 450 674 75 12 95
    38 95 123 0 117 35 207 114 291 89 94 181 131 326 131 114 0 116 1 154 103 33
    89 81 160 159 234 155 149 335 222 572 230 145 6 248 -12 360 -61 74 -33 87
    -33 132 7 112 98 237 165 358 191 98 22 267 15 360 -14z m-2775 -3013 c49 -26
    90 -90 90 -140 0 -45 -37 -113 -73 -136 -70 -43 -136 -39 -194 12 -65 57 -79
    124 -40 197 26 50 90 90 142 90 18 0 51 -10 75 -23z m3793 9 c42 -17 93 -76
    102 -116 16 -72 -22 -151 -88 -180 -56 -26 -95 -25 -147 3 -50 26 -90 90 -90
    142 0 52 40 116 90 142 49 26 87 29 133 9z m-3004 -719 c135 -89 59 -307 -102
    -294 -98 8 -167 101 -146 196 11 49 38 82 90 109 54 28 104 25 158 -11z m2255
    5 c80 -47 103 -157 49 -230 -38 -50 -70 -67 -132 -67 -48 0 -64 5 -95 29 -48
    36 -70 86 -64 147 12 119 138 182 242 121z m-1133 -185 c80 -54 102 -142 54
    -222 -57 -98 -198 -101 -270 -6 -30 39 -32 121 -5 169 44 78 150 107 221 59z"/>
    </g>
    </svg>
    }
    href="https://docs.oxla.com/oxla-cloud-saas/introduction-to-oxla-cloud-saas"
  >
    Get an instant access to the Oxla data processing engine.
  </Card>

  <Card
    title="SQL Statements"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 144.9 145.97">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <g class="cls-1">
             <path
               class="cls-2"
               d="M91.94,106.25a2,2,0,0,1-2-2V73.36A5.35,5.35,0,0,0,84.6,68H51.87a2,2,0,1,1,0-4H84.6a9.35,9.35,0,0,1,9.34,9.34v30.89A2,2,0,0,1,91.94,106.25Z"
             />
           </g>
           <g class="cls-1">
             <path
               class="cls-2"
               d="M69.9,96a7.94,7.94,0,1,1,7.94-7.94A7.95,7.95,0,0,1,69.9,96Zm0-11.88a3.94,3.94,0,1,0,3.94,3.94A3.95,3.95,0,0,0,69.9,84.14Z"
             />
           </g>
           <path d="M87.36,22.33a2,2,0,0,1-2-2V5.52A1.52,1.52,0,0,0,83.84,4H5.52A1.52,1.52,0,0,0,4,5.52V20.33a2,2,0,0,1-4,0V5.52A5.53,5.53,0,0,1,5.52,0H83.84a5.53,5.53,0,0,1,5.52,5.52V20.33A2,2,0,0,1,87.36,22.33Z" />
           <path d="M2,51.37a2,2,0,0,1-2-2V34.56A5.53,5.53,0,0,1,5.52,29H83.84a5.53,5.53,0,0,1,5.52,5.52V47.24a2,2,0,0,1-4,0V34.56A1.52,1.52,0,0,0,83.84,33H5.52A1.52,1.52,0,0,0,4,34.56V49.37A2,2,0,0,1,2,51.37Z" />
           <path d="M2,80.42a2,2,0,0,1-2-2V63.61a5.53,5.53,0,0,1,5.52-5.52H45a2,2,0,0,1,0,4H5.52A1.52,1.52,0,0,0,4,63.61V78.42A2,2,0,0,1,2,80.42Z" />
           <path d="M84.62,126.1A40.36,40.36,0,0,1,56,114.29h0a40.5,40.5,0,0,1,0-57.18,40.43,40.43,0,0,1,57.19,0,40.42,40.42,0,0,1-28.59,69ZM58.85,111.45A36.44,36.44,0,1,0,84.62,49.24h0a36.44,36.44,0,0,0-25.77,62.21Z" />
           <path d="M142.9,146a2,2,0,0,1-1.41-.59l-31.09-31.1a2,2,0,0,1,2.82-2.82l31.09,31.1A2,2,0,0,1,142.9,146Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/3-sql-reference/3-1-sql-statements/sql-statement-overview"
  >
    Learn how to create, modify and manage tables using statements.
  </Card>

  <Card
    title="SQL Clauses"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142.87 143.38">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path d="M84.35,123.92H6a6,6,0,0,1-6-6V6A6,6,0,0,1,6,0H93.92a6,6,0,0,1,6,6V57.92a2,2,0,0,1-4,0V6a2,2,0,0,0-2-2H6A2,2,0,0,0,4,6V117.92a2,2,0,0,0,2,2H84.35a2,2,0,0,1,0,4Z" />
           <path d="M97.79,143.38a2,2,0,0,1-.82-.18,2,2,0,0,1-1.18-1.82l0-33a3.32,3.32,0,0,0-1.35-2.69L73.75,90.12a7.39,7.39,0,0,1-2.94-5.88V73.34A5.38,5.38,0,0,1,76.19,68h61.3a5.38,5.38,0,0,1,5.38,5.38v10.9a7.39,7.39,0,0,1-2.94,5.88L119.2,105.66a3.36,3.36,0,0,0-1.34,2.68v17a2,2,0,0,1-.67,1.49L99.12,142.87A2,2,0,0,1,97.79,143.38ZM76.19,72a1.38,1.38,0,0,0-1.38,1.38v10.9a3.36,3.36,0,0,0,1.34,2.68l20.72,15.54a7.32,7.32,0,0,1,2.94,5.89l0,28.57,14.07-12.51V108.34a7.39,7.39,0,0,1,2.94-5.88l20.73-15.54a3.32,3.32,0,0,0,1.34-2.68V73.34A1.38,1.38,0,0,0,137.49,72Z" />
           <path
             class="cls-1"
             d="M83.85,28H16.06a2,2,0,1,1,0-4H83.85a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M67.47,99.92H16.06a2,2,0,1,1,0-4H67.47a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M83.85,52H16.06a2,2,0,1,1,0-4H83.85a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M58.81,76H16.06a2,2,0,1,1,0-4H58.81a2,2,0,0,1,0,4Z"
           />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/3-sql-reference/3-2-sql-clauses/sql-clauses-overview"
  >
    Discover how to write user-friendly queries and analyze data using different
    constraints and conditions.
  </Card>

  <Card
    title="SQL Data Types"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 148.23 144.14">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path d="M33.16,140.27A30.88,30.88,0,1,1,64,109.39,30.91,30.91,0,0,1,33.16,140.27Zm0-57.76A26.88,26.88,0,1,0,60,109.39,26.91,26.91,0,0,0,33.16,82.51Z" />
           <path d="M139.6,56.32H87.78a2,2,0,0,1-2-2V2.5a2,2,0,0,1,2-2H139.6a2,2,0,0,1,2,2V54.32A2,2,0,0,1,139.6,56.32Zm-49.82-4H137.6V4.5H89.78Z" />
           <path
             class="cls-1"
             d="M113.7,144.14a2,2,0,0,1-1.42-.58L79.75,111a2,2,0,0,1,0-2.83l32.53-32.53a2,2,0,0,1,2.83,0l32.54,32.53a2,2,0,0,1,0,2.83l-32.54,32.54A2,2,0,0,1,113.7,144.14ZM84,109.61l29.71,29.7,29.7-29.7L113.7,79.9Z"
           />
           <path d="M63,56.81H2a2,2,0,0,1-1.73-3L30.76,1a2,2,0,0,1,3.46,0L64.71,53.81a2,2,0,0,1-1.73,3Zm-57.52-4H59.52L32.49,6Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/3-sql-reference/3-3-sql-data-types/data-types-overview"
  >
    Familiarize yourself with the data types we use with practical examples.
  </Card>

  <Card
    title="SQL Functions"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 125.77 134.57">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path
             class="cls-1"
             d="M62.88,71.38A2,2,0,0,1,61.69,71a39.66,39.66,0,0,1,0-62.58,1.94,1.94,0,0,1,2.39,0,39.68,39.68,0,0,1,0,62.58A2,2,0,0,1,62.88,71.38Zm0-59a35.79,35.79,0,0,0,0,54.52,35.79,35.79,0,0,0,0-54.52Z"
           />
           <path d="M86.09,79.36a1.94,1.94,0,0,1,0-3.88,35.8,35.8,0,0,0,0-71.6,35.43,35.43,0,0,0-22,7.58l-1.19.93-1.19-.93a35.43,35.43,0,0,0-22-7.58,35.8,35.8,0,1,0,0,71.6,35.43,35.43,0,0,0,22-7.58L62.88,67l1.19.93a36.39,36.39,0,0,0,4.51,3,1.94,1.94,0,0,1-1.89,3.39,40,40,0,0,1-3.81-2.43,39.25,39.25,0,0,1-23.2,7.5A39.68,39.68,0,1,1,39.69,0a39.25,39.25,0,0,1,23.2,7.5A39.27,39.27,0,0,1,86.09,0a39.68,39.68,0,0,1,0,79.36Z" />
           <path d="M54,134.57H48.89a1.94,1.94,0,1,1,0-3.88H54a8.08,8.08,0,0,0,7.83-6.07L74.94,73.93a12,12,0,0,1,11.59-9h5.09a1.94,1.94,0,0,1,0,3.88H86.53A8.08,8.08,0,0,0,78.7,74.9L65.57,125.6A12,12,0,0,1,54,134.57Z" />
           <path d="M79,101.7H61.48a1.94,1.94,0,0,1,0-3.88H79a1.94,1.94,0,0,1,0,3.88Z" />
           <path d="M110.45,123.33a1.94,1.94,0,0,1-1.37-.57L95,108.64a1.94,1.94,0,0,1,2.74-2.74L111.82,120a1.94,1.94,0,0,1-1.37,3.31Z" />
           <path d="M96.33,123.33A1.94,1.94,0,0,1,95,120l14.12-14.12a1.94,1.94,0,0,1,2.74,2.74L97.7,122.76A1.92,1.92,0,0,1,96.33,123.33Z" />
           <path d="M90.11,132.16a1.9,1.9,0,0,1-1.45-.66,25.88,25.88,0,0,1,0-34.33,1.94,1.94,0,1,1,2.9,2.58,22,22,0,0,0,0,29.19,1.94,1.94,0,0,1-1.45,3.22Z" />
           <path d="M116.66,132.16a1.9,1.9,0,0,1-1.28-.49,1.92,1.92,0,0,1-.17-2.73,22,22,0,0,0,0-29.19,1.94,1.94,0,1,1,2.9-2.58,25.88,25.88,0,0,1,0,34.33A1.9,1.9,0,0,1,116.66,132.16Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/3-sql-reference/3-4-sql-functions/sql-functions-overview"
  >
    A thorough guide on how to create and call functions to perform different
    data operations.
  </Card>

  <Card
    title="SQL Mutations"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 123.64 134.24">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path
             class="cls-1"
             d="M10.08,44.58a2,2,0,0,1-1.29-3.64L47.62,9.78A2,2,0,1,1,50.18,13L11.35,44.13A2,2,0,0,1,10.08,44.58Z"
           />
           <path
             class="cls-1"
             d="M74.78,125.62A2,2,0,0,1,73.49,122l39.36-31.59a2,2,0,1,1,2.56,3.19L76.05,125.17A2,2,0,0,1,74.78,125.62Z"
           />
           <path
             class="cls-1"
             d="M48.7,92.27a2,2,0,0,1-1.28-3.64L72.07,68.85A2,2,0,1,1,74.63,72L50,91.82A2,2,0,0,1,48.7,92.27Z"
           />
           <path
             class="cls-1"
             d="M36.28,77.82A2,2,0,0,1,35,74.18L59.59,54.44a2,2,0,1,1,2.56,3.19L37.56,77.37A2,2,0,0,1,36.28,77.82Z"
           />
           <path d="M121.6,100.17a2,2,0,0,1-1.6-.77c-8.89-11.07-23.31-8.73-38.57-6.24-15.76,2.56-32,5.22-42.43-7.72s-4.27-28.27,1.65-43.09C46.38,28,51.79,14.41,42.9,3.33A2,2,0,1,1,46.09.76c10.39,13,4.27,28.28-1.64,43.1-5.74,14.37-11.15,27.94-2.26,39s23.31,8.73,38.58,6.24c15.75-2.56,32-5.22,42.42,7.73a2,2,0,0,1-1.59,3.32Z" />
           <path d="M79.16,134.24a2,2,0,0,1-1.6-.77c-10.38-12.94-4.27-28.26,1.64-43.08,2.59-6.49,5.27-13.2,6.39-19.45a2,2,0,1,1,4,.73c-1.2,6.65-4,13.56-6.62,20.24-5.73,14.36-11.14,27.93-2.25,39a2,2,0,0,1-1.59,3.32Z" />
           <path d="M23.66,47.24C14.75,47.24,6.57,45,.45,37.39a2,2,0,0,1,3.19-2.55C12.53,45.92,27,43.57,42.21,41.08c7.1-1.16,14.43-2.35,21.19-2.08a2.05,2.05,0,0,1,2,2.13,2,2,0,0,1-2.13,2c-6.34-.26-13.47.9-20.36,2C36.41,46.17,29.86,47.24,23.66,47.24Z" />
           <path d="M85.41,50.24a2,2,0,0,1-1.28-3.64L97.49,35.87a2,2,0,1,1,2.56,3.19L86.69,49.79A2,2,0,0,1,85.41,50.24Z" />
           <path d="M78.1,41.12a2,2,0,0,1-.54-.07,2,2,0,0,1-1.44-2.51L80.57,22a2,2,0,1,1,4,1.07L80.07,39.61A2,2,0,0,1,78.1,41.12Z" />
           <path d="M92.73,59.35a2,2,0,0,1-.09-4.09l17.11-.75a2,2,0,1,1,.18,4.09l-17.11.75Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/4-sql-mutations/sql-mutations"
  >
    Use a sequence of data manipulation to your database.
  </Card>

  <Card
    title="Error Handling"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 141.84 142.09">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path d="M135.7,142.09h-69a6.13,6.13,0,0,1-5.31-9.19L95.91,73.18A2,2,0,0,1,96,73a6.13,6.13,0,0,1,10.5.19L141,132.9a6.13,6.13,0,0,1-5.31,9.19ZM99.28,75.33,64.89,134.9a2.13,2.13,0,0,0,1.85,3.19h69a2.13,2.13,0,0,0,1.84-3.19L103.07,75.18a2.14,2.14,0,0,0-3.69,0A.78.78,0,0,1,99.28,75.33Z" />
           <path
             class="cls-1"
             d="M101.21,118a2,2,0,0,1-2-2V94.05a2,2,0,0,1,4,0V116A2,2,0,0,1,101.21,118Z"
           />
           <path
             class="cls-1"
             d="M101.21,128.17a2,2,0,0,1-2-2v-1a2,2,0,0,1,4,0v1A2,2,0,0,1,101.21,128.17Z"
           />
           <path d="M101.21,25.3a2,2,0,0,1-2-2V6.09A2.1,2.1,0,0,0,97.12,4h-91A2.1,2.1,0,0,0,4,6.09V23.3a2,2,0,0,1-4,0V6.09A6.09,6.09,0,0,1,6.09,0h91a6.09,6.09,0,0,1,6.09,6.09V23.3A2,2,0,0,1,101.21,25.3Z" />
           <path d="M101.21,59.06a2,2,0,0,1-2-2V39.85a2.1,2.1,0,0,0-2.09-2.09h-91A2.1,2.1,0,0,0,4,39.85V57.06a2,2,0,0,1-4,0V39.85a6.09,6.09,0,0,1,6.09-6.09h91a6.09,6.09,0,0,1,6.09,6.09V57.06A2,2,0,0,1,101.21,59.06Z" />
           <path d="M67.09,106.39h-61A6.09,6.09,0,0,1,0,100.3V73.6a6.09,6.09,0,0,1,6.09-6.09H86.71a2,2,0,0,1,0,4H6.09A2.1,2.1,0,0,0,4,73.6v26.7a2.1,2.1,0,0,0,2.09,2.09h61a2,2,0,0,1,0,4Z" />
           <path
             class="cls-1"
             d="M18.86,26.28A7.14,7.14,0,1,1,26,19.14,7.14,7.14,0,0,1,18.86,26.28Zm0-10.28A3.14,3.14,0,1,0,22,19.14,3.15,3.15,0,0,0,18.86,16Z"
           />
           <path
             class="cls-1"
             d="M18.86,60A7.14,7.14,0,1,1,26,52.9,7.14,7.14,0,0,1,18.86,60Zm0-10.28A3.14,3.14,0,1,0,22,52.9,3.15,3.15,0,0,0,18.86,49.76Z"
           />
           <path
             class="cls-1"
             d="M18.86,94.4A7.14,7.14,0,1,1,26,87.26,7.14,7.14,0,0,1,18.86,94.4Zm0-10.28A3.14,3.14,0,1,0,22,87.26,3.15,3.15,0,0,0,18.86,84.12Z"
           />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/5-error-handling/error-handling"
  >
    Something went wrong? Head over here to see all your troubleshooting
    options!
  </Card>

  <Card
    title="Oxla vs PostgreSQL"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142.3 140.57">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path d="M58.84,60.84H2a2,2,0,0,1-2-2V2A2,2,0,0,1,2,0H58.84a2,2,0,0,1,2,2V58.84A2,2,0,0,1,58.84,60.84ZM4,56.84H56.84V4H4Z" />
           <path d="M140.3,140.57H70.93a2,2,0,0,1-1.73-1,2,2,0,0,1,0-2L103.87,76a2,2,0,0,1,3.48,0L142,137.59a2,2,0,0,1-1.74,3Zm-66-4h62.53L105.61,81Z" />
           <path
             class="cls-1"
             d="M20.2,136.87a2,2,0,0,1-1.48-3.35L132,9.25a2,2,0,0,1,3,2.7L21.68,136.22A2,2,0,0,1,20.2,136.87Z"
           />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/6-oxla-vs-postgre/differences-between-oxla-vs-postgre"
  >
    Dig up on the differences between Oxla & PostgreSQL which need to be
    addressed.
  </Card>

  <Card
    title="Public Metrics"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 143.02 135.26">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path
             class="cls-1"
             d="M86.54,38.85H15.64a2,2,0,0,1,0-4h70.9a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M122.53,38.85H96.91a2,2,0,0,1,0-4h25.62a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M43.82,79H15.64a2,2,0,0,1,0-4H43.82a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M122.83,79h-15a2,2,0,0,1,0-4h15a2,2,0,0,1,0,4Z"
           />
           <path d="M110,101.66H39a3.94,3.94,0,0,1-3.72-5.26L53,46.14A3.95,3.95,0,0,1,60.36,46L74,79.43,88.61,25.77a3.91,3.91,0,0,1,3.81-2.91h0a3.88,3.88,0,0,1,3.78,3l17.51,70.71a.76.76,0,0,1,.06.2,3.95,3.95,0,0,1-3.83,4.89ZM56.71,47.6,39.05,97.73l70.86-.07L92.42,27,77.8,80.64a3.94,3.94,0,0,1-7.46.44Z" />
           <path d="M141,121.62H20.57a6.94,6.94,0,0,1-6.93-6.93V2a2,2,0,0,1,4,0V114.69a2.93,2.93,0,0,0,2.93,2.93H141a2,2,0,0,1,0,4Z" />
           <path d="M29.28,17.64a2,2,0,0,1-1.41-.59L15.64,4.83,3.41,17.05a2,2,0,0,1-2.82,0,2,2,0,0,1,0-2.82L14.23.59a2,2,0,0,1,2.82,0L30.69,14.23a2,2,0,0,1-1.41,3.41Z" />
           <path d="M127.38,135.26a2,2,0,0,1-1.41-3.41l12.22-12.23L126,107.39a2,2,0,1,1,2.82-2.82l13.64,13.64a2,2,0,0,1,0,2.82l-13.64,13.64A2,2,0,0,1,127.38,135.26Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/8-public-metrics/public-metrics"
  >
    Discover public metrics to measuring impact and informing progress.
  </Card>

  <Card
    title="Oxla Configuration File"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.5 133.51">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path
             class="cls-1"
             d="M94.47,33.52H65.94a2,2,0,0,1-2-2V2a2,2,0,0,1,4,0V29.52H94.47a2,2,0,0,1,0,4Z"
           />
           <path d="M26.67,123.92H6a6,6,0,0,1-6-6V6A6,6,0,0,1,6,0H66a8.67,8.67,0,0,1,6.2,2.57L95.69,26.11a8.67,8.67,0,0,1,2.57,6.2V44.85a2,2,0,1,1-4,0V32.31a4.78,4.78,0,0,0-1.39-3.38L69.33,5.39A4.78,4.78,0,0,0,66,4H6A2,2,0,0,0,4,6V117.92a2,2,0,0,0,2,2H26.67a2,2,0,0,1,0,4Z" />
           <path
             class="cls-1"
             d="M90.35,67.81H42.65a2,2,0,0,1,0-4h47.7a2,2,0,0,1,0,4Z"
           />
           <path d="M110.05,77.5a11.69,11.69,0,1,1,11.69-11.69A11.7,11.7,0,0,1,110.05,77.5Zm0-19.38a7.69,7.69,0,1,0,7.69,7.69A7.7,7.7,0,0,0,110.05,58.12Z" />
           <path
             class="cls-1"
             d="M120.5,123.82H72a2,2,0,0,1,0-4H120.5a2,2,0,0,1,0,4Z"
           />
           <path d="M52.34,133.51A11.69,11.69,0,1,1,64,121.82,11.7,11.7,0,0,1,52.34,133.51Zm0-19.38A7.69,7.69,0,1,0,60,121.82,7.7,7.7,0,0,0,52.34,114.13Z" />
           <path
             class="cls-1"
             d="M120.5,95.59H101.05a2,2,0,1,1,0-4H120.5a2,2,0,0,1,0,4Z"
           />
           <path
             class="cls-1"
             d="M61.66,95.59h-19a2,2,0,0,1,0-4h19a2,2,0,0,1,0,4Z"
           />
           <path d="M81.35,105.28A11.69,11.69,0,1,1,93,93.59,11.7,11.7,0,0,1,81.35,105.28Zm0-19.38A7.69,7.69,0,1,0,89,93.59,7.7,7.7,0,0,0,81.35,85.9Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/9-oxla-config-file/oxla-configuration-file"
  >
    Optimize Oxla with its configuration file for development and deployment.
  </Card>

  <Card
    title="Understanding Transactions"
    icon={
     <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 123.98 135.65">
       <g id="Layer_2" data-name="Layer 2">
         <g id="Layer_1-2" data-name="Layer 1">
           <path
             class="cls-1"
             d="M76.2,135.65a2,2,0,0,1-1.36-.53L47.08,109.35a2,2,0,0,1,0-2.94L74.84,80.65a2,2,0,0,1,3.36,1.47V95.23H122a2,2,0,0,1,0,4H76.2a2,2,0,0,1-2-2V86.7L51.38,107.88,74.2,129.06V118.54a2,2,0,0,1,2-2H122a2,2,0,0,1,0,4H78.2v13.11a2,2,0,0,1-1.2,1.83A1.89,1.89,0,0,1,76.2,135.65Z"
           />
           <path d="M101.21,25.3a2,2,0,0,1-2-2V6.09A2.1,2.1,0,0,0,97.12,4h-91A2.1,2.1,0,0,0,4,6.09V23.3a2,2,0,0,1-4,0V6.09A6.09,6.09,0,0,1,6.09,0h91a6.09,6.09,0,0,1,6.09,6.09V23.3A2,2,0,0,1,101.21,25.3Z" />
           <path d="M101.21,59.06a2,2,0,0,1-2-2V39.85a2.1,2.1,0,0,0-2.09-2.09h-91A2.1,2.1,0,0,0,4,39.85V57.06a2,2,0,0,1-4,0V39.85a6.09,6.09,0,0,1,6.09-6.09h91a6.09,6.09,0,0,1,6.09,6.09V57.06A2,2,0,0,1,101.21,59.06Z" />
           <path
             class="cls-1"
             d="M18.86,26.28A7.14,7.14,0,1,1,26,19.14,7.14,7.14,0,0,1,18.86,26.28Zm0-10.28A3.14,3.14,0,1,0,22,19.14,3.15,3.15,0,0,0,18.86,16Z"
           />
           <path
             class="cls-1"
             d="M18.86,60A7.14,7.14,0,1,1,26,52.9,7.14,7.14,0,0,1,18.86,60Zm0-10.28A3.14,3.14,0,1,0,22,52.9,3.15,3.15,0,0,0,18.86,49.76Z"
           />
           <path
             class="cls-1"
             d="M18.86,94.4A7.14,7.14,0,1,1,26,87.26,7.14,7.14,0,0,1,18.86,94.4Zm0-10.28A3.14,3.14,0,1,0,22,87.26,3.15,3.15,0,0,0,18.86,84.12Z"
           />
           <path d="M36.26,106.39H6.09A6.09,6.09,0,0,1,0,100.3V73.6a6.09,6.09,0,0,1,6.09-6.09h91a6.09,6.09,0,0,1,6.09,6.09V86.81a2,2,0,0,1-4,0V73.6a2.1,2.1,0,0,0-2.09-2.09h-91A2.1,2.1,0,0,0,4,73.6v26.7a2.1,2.1,0,0,0,2.09,2.09H36.26a2,2,0,1,1,0,4Z" />
         </g>
       </g>
     </svg>
    }
    href="https://docs.oxla.com/7-transactions/understanding-transactions"
  >
    Learn more about data management through transactions.
  </Card>
</CardGroup>