SELECT queries data from one or more tables. Before running a SELECT statement, make sure you have the Select permission on the target table. For more information, see MaxCompute permissions.
Supported clients:
Syntax
[WITH <cte>[, ...] ]
SELECT [ALL | DISTINCT] <SELECT_expr>[, <EXCEPT_expr>][, <REPLACE_expr>] ...
FROM <TABLE_reference>
[WHERE <WHERE_condition>]
[GROUP BY {<col_list>|ROLLUP(<col_list>)}]
[HAVING <HAVING_condition>]
[WINDOW <WINDOW_clause>]
[ORDER BY <ORDER_condition>]
[DISTRIBUTE BY <DISTRIBUTE_condition> [SORT BY <SORT_condition>]|[ CLUSTER BY <CLUSTER_condition>] ]
[LIMIT <number>]For the execution order of clauses in a SELECT statement, see Execution order of clauses.
Limitations
A
SELECTstatement displays a maximum of 10,000 rows and returns results no larger than 10 MB. This limit does not apply whenSELECTis used as a subquery—in that case, all rows are returned to the parent query.Full table scans on partitioned tables are prohibited by default. For projects created after 20:00:00 on January 10, 2018, you must specify a partition when querying a partitioned table. This reduces unnecessary I/O and computing costs, especially under pay-as-you-go billing. To run a full table scan for the current session, submit
SET odps.sql.allow.fullscan=true;together with theSELECTstatement:SET odps.sql.allow.fullscan=true; SELECT * FROM sale_detail;For clustered tables, bucket pruning is optimized only when 400 or fewer partitions are scanned per table. If bucket pruning does not take effect, more data is scanned, which increases costs under pay-as-you-go billing and degrades performance under subscription billing.
Related query types
| Query type | Description |
|---|---|
| Subqueries | Query the results of a previous query |
| INTERSECT, UNION, and EXCEPT | Intersect, union, or complement query result datasets |
| JOIN | Join tables and return rows matching join and query conditions |
| SEMI JOIN | Filter left-table rows using the right table; result contains only left-table data |
| MAPJOIN hint | Improve JOIN performance when joining a large table with one or more small tables |
| SKEWJOIN hint | Handle data skew in JOIN operations by processing hot-spot and non-hot-spot data separately |
| LATERAL VIEW | Use with a user-defined table-valued function (UDTF) to split a single row into multiple rows |
| GROUPING SETS | Aggregate and analyze data across multiple dimensions |
| SELECT TRANSFORM | Start a child process, send formatted input via stdin, and parse stdout as output |
| Split size hint | Control query concurrency by adjusting the split size |
| Time travel and incremental queries | Query historical snapshots (time travel) or incremental data (incremental query) from Delta tables |
Sample data
The examples in this topic use the sale_detail table. Run the following statements to create the table and insert sample data:
-- Create a partitioned table named sale_detail.
CREATE TABLE IF NOT EXISTS sale_detail
(
shop_name STRING,
customer_id STRING,
total_price DOUBLE
)
PARTITIONED BY (sale_date STRING, region STRING);
-- Add a partition.
ALTER TABLE sale_detail ADD PARTITION (sale_date='2013', region='china');
-- Insert data.
INSERT INTO sale_detail PARTITION (sale_date='2013', region='china') VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);Query the table to verify:
SELECT * FROM sale_detail;
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
| s3 | c3 | 100.3 | 2013 | china |
+------------+-------------+-------------+------------+------------+WITH clause (CTE)
The WITH clause defines one or more common table expressions (CTEs). Each CTE acts as a temporary named result set available for subsequent queries in the same statement.
Rules:
CTE names within the same
WITHclause must be unique.A CTE can reference other CTEs defined earlier in the same
WITHclause, but not itself and not in a circular dependency.
Self-reference (not supported)
-- Incorrect: A cannot reference itself.
WITH
A AS (SELECT 1 FROM A)
SELECT * FROM A;
-- FAILED: ODPS-0130161:[1,6] Parse exception - recursive cte A is invalid, it must have an initial_part and a recursive_part, which must be connected by UNION ALLCircular reference (not supported)
-- Incorrect: A references B, and B references A.
WITH
A AS (SELECT * FROM B),
B AS (SELECT * FROM A)
SELECT * FROM B;
-- FAILED: ODPS-0130071:[1,26] Semantic analysis exception - while resolving view B - [1,51]recursive function call is not supported, cycle is A->B->ASequential reference (supported)
WITH
A AS (SELECT 1 AS C),
B AS (SELECT * FROM A)
SELECT * FROM B;
-- Result:
+---+
| c |
+---+
| 1 |
+---+Column expression (SELECT_expr)
SELECT_expr specifies which columns to return. Use column names, *, regular expressions, or the DISTINCT and ALL keywords.
Select specific columns by name
SELECT shop_name FROM sale_detail;
-- Result:
+------------+
| shop_name |
+------------+
| s1 |
| s2 |
| s3 |
+------------+Select all columns with *
-- Enable full table scan for the current session.
SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail;
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
| s3 | c3 | 100.3 | 2013 | china |
+------------+-------------+-------------+------------+------------+Filter with WHERE
SELECT * FROM sale_detail WHERE shop_name='s1';
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
+------------+-------------+-------------+------------+------------+Select columns by regular expression
Wrap the regular expression in backticks.
Select all columns whose names start with sh:
SELECT `sh.*` FROM sale_detail;
-- Result:
+------------+
| shop_name |
+------------+
| s1 |
| s2 |
| s3 |
+------------+Exclude shop_name and return all other columns:
SELECT `(shop_name)?+.+` FROM sale_detail;
-- Result:
+-------------+-------------+------------+------------+
| customer_id | total_price | sale_date | region |
+-------------+-------------+------------+------------+
| c1 | 100.1 | 2013 | china |
| c2 | 100.2 | 2013 | china |
| c3 | 100.3 | 2013 | china |
+-------------+-------------+------------+------------+Exclude multiple columns (shop_name and customer_id):
SELECT `(shop_name|customer_id)?+.+` FROM sale_detail;
-- Result:
+-------------+------------+------------+
| total_price | sale_date | region |
+-------------+------------+------------+
| 100.1 | 2013 | china |
| 100.2 | 2013 | china |
| 100.3 | 2013 | china |
+-------------+------------+------------+Exclude all columns whose names start with t:
SELECT `(t.*)?+.+` FROM sale_detail;
-- Result:
+------------+-------------+------------+------------+
| shop_name | customer_id | sale_date | region |
+------------+-------------+------------+------------+
| s1 | c1 | 2013 | china |
| s2 | c2 | 2013 | china |
| s3 | c3 | 2013 | china |
+------------+-------------+------------+------------+When excluding multiple columns where one name is a prefix of another, place the longer name first in the expression. For example, if a table has partitionsdsanddshh, use `SELECT(dshh|ds)?+.+FROM t;rather thanSELECT(ds|dshh)?+.+FROM t;`.
Remove duplicates with DISTINCT
DISTINCT returns unique values; ALL (the default) returns all rows including duplicates.
SELECT DISTINCT region FROM sale_detail;
-- Result:
+------------+
| region |
+------------+
| china |
+------------+When applied to multiple columns, DISTINCT deduplicates based on the combined value of all listed columns:
SELECT DISTINCT region, sale_date FROM sale_detail;
-- Result:
+------------+------------+
| region | sale_date |
+------------+------------+
| china | 2013 |
+------------+------------+DISTINCT also works with window functions, removing duplicate rows from the window function result:
SET odps.sql.allow.fullscan=true;
SELECT DISTINCT sale_date, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY total_price) AS rn FROM sale_detail;
-- Result:
+-----------+------------+
| sale_date | rn |
+-----------+------------+
| 2013 | 1 |
+-----------+------------+DISTINCTandGROUP BYcannot be used in the same query. The following statement returns an error:
SELECT DISTINCT shop_name FROM sale_detail GROUP BY shop_name;
-- Error: GROUP BY cannot be used with SELECT DISTINCTExclude columns (EXCEPT_expr)
SELECT * EXCEPT(col1, col2, ...) returns all columns except the specified ones.
-- Return all columns except region.
SELECT * EXCEPT(region) FROM sale_detail;
-- Result:
+-----------+-------------+-------------+-----------+
| shop_name | customer_id | total_price | sale_date |
+-----------+-------------+-------------+-----------+
| s1 | c1 | 100.1 | 2013 |
| s2 | c2 | 100.2 | 2013 |
| s3 | c3 | 100.3 | 2013 |
+-----------+-------------+-------------+-----------+Replace columns (REPLACE_expr)
SELECT * REPLACE(expr AS col, ...) returns all columns, replacing the value of specified columns with the given expressions.
-- Return all columns, replacing total_price and region values.
SELECT * REPLACE(total_price+100 AS total_price, 'shanghai' AS region) FROM sale_detail;
-- Result:
+-----------+-------------+-------------+-----------+--------+
| shop_name | customer_id | total_price | sale_date | region |
+-----------+-------------+-------------+-----------+--------+
| s1 | c1 | 200.1 | 2013 | shanghai |
| s2 | c2 | 200.2 | 2013 | shanghai |
| s3 | c3 | 200.3 | 2013 | shanghai |
+-----------+-------------+-------------+-----------+--------+Target table (TABLE_reference)
TABLE_reference specifies the table to query.
Query a named table
SELECT customer_id FROM sale_detail;
-- Result:
+-------------+
| customer_id |
+-------------+
| c1 |
| c2 |
| c3 |
+-------------+Use a nested subquery as the source
SELECT * FROM (SELECT region, sale_date FROM sale_detail) t WHERE region = 'china';
-- Result:
+------------+------------+
| region | sale_date |
+------------+------------+
| china | 2013 |
| china | 2013 |
| china | 2013 |
+------------+------------+WHERE clause
The WHERE clause filters rows. For partitioned tables, conditions on partition columns enable partition pruning—only matching partitions are scanned.
Supported relational operators: >, <, =, >=, <=, <>, LIKE, RLIKE, IN, NOT IN, BETWEEN...AND. For details, see Relational operators.
Filter with a partition range
SELECT *
FROM sale_detail
WHERE sale_date >= '2008' AND sale_date <= '2014';
-- Equivalent to:
SELECT *
FROM sale_detail
WHERE sale_date BETWEEN '2008' AND '2014';
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
| s3 | c3 | 100.3 | 2013 | china |
+------------+-------------+-------------+------------+------------+Run the EXPLAIN statement to verify that partition pruning takes effect. A user-defined function (UDF) or partition conditions in a JOIN ON clause may prevent pruning. For more information, see Check whether partition pruning is effective.
Use a UDF for partition pruning
A UDF in the WHERE clause runs as a small pre-job, and the result replaces the UDF in the original statement.
To enable UDF-based partition pruning, annotate the UDF class:
@com.aliyun.odps.udf.annotation.UdfProperty(isDeterministic=true)com.aliyun.odps.udf.annotation.UdfPropertyis defined inodps-sdk-udf.jar. Upgradeodps-sdk-udfto version 0.30.x or later.
Alternatively, add SET odps.sql.udf.ppr.deterministic = true; before the SQL statement to treat all UDFs in the statement as deterministic. This method backfills partitions with job results, up to a maximum of 1,000 partitions. If more than 1,000 partitions are backfilled, an error is returned. To suppress the error and disable UDF-based partition pruning, run SET odps.sql.udf.ppr.to.subquery = false;.
The UDF must be in the WHERE clause of the source table for pruning to take effect:
-- Correct: UDF in the WHERE clause of the source table.
SELECT key, value FROM srcp WHERE udf(ds) = 'xx';
-- Incorrect: UDF in a JOIN ON clause does not trigger partition pruning.
SELECT A.c1, A.c2 FROM srcp1 A JOIN srcp2 B ON A.c1 = B.c1 AND udf(A.ds) = 'xx';Column aliases are not available in WHERE
If a column in SELECT_expr uses a function and is renamed with an alias, the alias cannot be referenced in the WHERE clause. The following statement returns an error:
-- Incorrect: skynet_id is an alias defined in SELECT, not available in WHERE.
SELECT task_name,
inst_id,
settings,
GET_JSON_OBJECT(settings, '$.SKYNET_ID') AS skynet_id,
GET_JSON_OBJECT(settings, '$.SKYNET_NODENAME') AS user_agent
FROM Information_Schema.TASKS_HISTORY
WHERE ds = '20211215' AND skynet_id IS NOT NULL
LIMIT 10;GROUP BY clause
GROUP BY groups rows by specified columns and is typically used with aggregate functions.
Rules:
GROUP BYis executed beforeSELECT. Columns inGROUP BYcan be specified by the column names of the input table, or by an expression formed from the columns of that table. Aliases defined in theSELECTlist can also be used inGROUP BY.All columns in the
SELECTlist that are not wrapped in an aggregate function must appear in theGROUP BYclause.Regular expressions in
GROUP BYmust use the full expression for the columns.GROUP BYcannot be used together withDISTRIBUTE BYorSORT BY.
Group by a column
SELECT region FROM sale_detail GROUP BY region;
-- Result:
+------------+
| region |
+------------+
| china |
+------------+Aggregate with GROUP BY
SELECT region, SUM(total_price) FROM sale_detail GROUP BY region;
-- Result:
+------------+------------+
| region | _c1 |
+------------+------------+
| china | 300.6 |
+------------+------------+Use a SELECT alias in GROUP BY
SELECT region AS r FROM sale_detail GROUP BY r;
-- Equivalent to:
SELECT region AS r FROM sale_detail GROUP BY region;
-- Result:
+------------+
| r |
+------------+
| china |
+------------+Group by a column expression
SELECT 2 + total_price AS r FROM sale_detail GROUP BY 2 + total_price;
-- Result:
+------------+
| r |
+------------+
| 102.1 |
| 102.2 |
| 102.3 |
+------------+Missing GROUP BY column returns an error
-- Incorrect: total_price is not in GROUP BY and not in an aggregate function.
SELECT region, total_price FROM sale_detail GROUP BY region;
-- Error: FAILED: ODPS-0130071:[1,16] Semantic analysis exception - column reference sale_detail.total_price should appear in GROUP BY key
-- Correct:
SELECT region, total_price FROM sale_detail GROUP BY region, total_price;
-- Result:
+------------+-------------+
| region | total_price |
+------------+-------------+
| china | 100.1 |
| china | 100.2 |
| china | 100.3 |
+------------+-------------+GROUP BY ALL (BigQuery compatible mode)
When odps.sql.bigquery.compatible=true, GROUP BY ALL automatically groups by all non-aggregated columns in the SELECT list:
-- Explicitly list grouping fields.
SELECT
shop_name,
customer_id,
sale_date,
region,
SUM(total_price) AS total_sales
FROM sale_detail
GROUP BY shop_name, customer_id, sale_date, region;
-- Equivalent using GROUP BY ALL.
SET odps.sql.bigquery.compatible=true;
SELECT
shop_name,
customer_id,
sale_date,
region,
SUM(total_price) AS total_sales
FROM sale_detail
GROUP BY ALL;
-- Result:
+-----------+-------------+-----------+--------+-------------+
| shop_name | customer_id | sale_date | region | total_sales |
+-----------+-------------+-----------+--------+-------------+
| s1 | c1 | 2013 | china | 100.1 |
| s2 | c2 | 2013 | china | 100.2 |
| s3 | c3 | 2013 | china | 100.3 |
+-----------+-------------+-----------+--------+-------------+Use positional aliases in GROUP BY
Run SET odps.sql.groupby.position.alias=true; to treat integer constants in GROUP BY as column positions in the SELECT list:
SET odps.sql.groupby.position.alias=true;
-- 1 refers to the first column in the SELECT list (region).
SELECT region, SUM(total_price) FROM sale_detail GROUP BY 1;
-- Result:
+------------+------------+
| region | _c1 |
+------------+------------+
| china | 300.6 |
+------------+------------+HAVING clause
HAVING filters grouped data, typically using aggregate functions. It is evaluated after GROUP BY.
-- Insert additional data to demonstrate HAVING.
INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai') VALUES ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
-- Return only groups where the total price is less than 305.
SELECT region, SUM(total_price) FROM sale_detail
GROUP BY region
HAVING SUM(total_price) < 305;
-- Result:
+------------+------------+
| region | _c1 |
+------------+------------+
| china | 300.6 |
| shanghai | 200.9 |
+------------+------------+ORDER BY clause
ORDER BY sorts all rows by one or more columns. The sort is global—all data is merged into a single node.
By default, ORDER BY requires a LIMIT clause. Without LIMIT, an error is returned. This prevents accidentally processing large datasets on a single node.
Rules:
Default sort order is ascending (
ASC). UseDESCfor descending order.NULLvalues are treated as the smallest value (consistent with MySQL behavior).ORDER BYcolumns must reference output columns from theSELECTstatement—either by column name or alias.ORDER BYcannot be used together withDISTRIBUTE BYorSORT BY.
Sort ascending (default)
SELECT * FROM sale_detail ORDER BY total_price LIMIT 2;
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
+------------+-------------+-------------+------------+------------+Sort descending
SELECT * FROM sale_detail ORDER BY total_price DESC LIMIT 2;
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s3 | c3 | 100.3 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
+------------+-------------+-------------+------------+------------+Use a column alias in ORDER BY
SELECT total_price AS t FROM sale_detail ORDER BY t LIMIT 3;
-- Result:
+------------+
| t |
+------------+
| 100.1 |
| 100.2 |
| 100.3 |
+------------+Use positional aliases in ORDER BY
Run SET odps.sql.orderby.position.alias=true; to treat integer constants in ORDER BY as column positions:
SET odps.sql.orderby.position.alias=true;
-- 3 refers to the third column in the SELECT list (total_price).
SELECT * FROM sale_detail ORDER BY 3 LIMIT 3;
-- Result:
+------------+-------------+-------------+------------+------------+
| shop_name | customer_id | total_price | sale_date | region |
+------------+-------------+-------------+------------+------------+
| s1 | c1 | 100.1 | 2013 | china |
| s2 | c2 | 100.2 | 2013 | china |
| s3 | c3 | 100.3 | 2013 | china |
+------------+-------------+-------------+------------+------------+Skip rows with OFFSET
ORDER BY...LIMIT m OFFSET n returns m rows starting after the first n rows. LIMIT n, m is an equivalent shorthand.
-- Sort by total_price ascending, skip the first 2 rows, return up to 3.
SELECT customer_id, total_price FROM sale_detail ORDER BY total_price LIMIT 3 OFFSET 2;
-- Equivalent:
SELECT customer_id, total_price FROM sale_detail ORDER BY total_price LIMIT 2, 3;
-- Result (only 1 row remains after skipping 2):
+-------------+-------------+
| customer_id | total_price |
+-------------+-------------+
| c3 | 100.3 |
+-------------+-------------+Remove the LIMIT requirement for ORDER BY
Because ORDER BY runs on a single node, the LIMIT requirement prevents accidentally sorting very large datasets. To disable this requirement:
Project level: Run
SETPROJECT odps.sql.validate.orderby.limit=false;Session level: Submit
SET odps.sql.validate.orderby.limit=false;together with the SQL statement.
Sorting large datasets on a single node consumes more resources and takes longer.
Accelerate global sorting with Range Clustering
In typical ORDER BY scenarios, all data must be processed on a single node. Range Clustering samples the data first, divides it into ranges, then sorts each range concurrently—producing a globally ordered result in parallel. For details, see Global sorting acceleration.
DISTRIBUTE BY clause
DISTRIBUTE BY performs hash sharding on rows based on the specified columns, routing rows with the same key to the same reducer. Use it to ensure that related data is processed together, or to prevent data overlap across reducers.
Columns in DISTRIBUTE BY must reference output columns from the SELECT statement by their aliases. If no alias is specified, the column name is used.
-- Hash-shard rows by the region column.
SELECT region FROM sale_detail DISTRIBUTE BY region;
-- The following two statements are equivalent to the one above:
SELECT region AS r FROM sale_detail DISTRIBUTE BY region;
SELECT region AS r FROM sale_detail DISTRIBUTE BY r;
-- Result:
+------------+
| r |
+------------+
| china |
| china |
| china |
+------------+DISTRIBUTE BYcannot be used together withORDER BYorGROUP BY.
SORT BY clause
SORT BY sorts data within each reducer partition. It does not guarantee global order.
Rules:
Default sort order is ascending. Use
DESCfor descending.When used with
DISTRIBUTE BY,SORT BYsorts within each partition created byDISTRIBUTE BY.When used without
DISTRIBUTE BY,SORT BYsorts within each reducer independently.
DISTRIBUTE BY + SORT BY (distributed sort)
-- Insert additional data to show multiple regions.
INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai') VALUES ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);
-- Set 2 reducers.
SET odps.stage.reducer.num=2;
-- Hash-shard by region, then sort by total_price ascending within each shard.
SELECT region, total_price FROM sale_detail DISTRIBUTE BY region SORT BY total_price;
-- Result:
+------------+-------------+
| region | total_price |
+------------+-------------+
| shanghai | NULL |
| shanghai | 100.4 |
| shanghai | 100.5 |
| china | 100.1 |
| china | 100.2 |
| china | 100.3 |
+------------+-------------+Sort descending within each shard:
SET odps.stage.reducer.num=2;
SELECT region, total_price FROM sale_detail DISTRIBUTE BY region SORT BY total_price DESC;
-- Result:
+------------+-------------+
| region | total_price |
+------------+-------------+
| shanghai | 100.5 |
| shanghai | 100.4 |
| shanghai | NULL |
| china | 100.3 |
| china | 100.2 |
| china | 100.1 |
+------------+-------------+SORT BY without DISTRIBUTE BY
SORT BY alone sorts within each reducer independently. This does not produce a globally sorted result, but it improves the storage compression ratio and reduces disk reads during filtering, which can speed up subsequent global sorting operations.
SET odps.stage.reducer.num=2;
SELECT region, total_price FROM sale_detail SORT BY total_price DESC;
-- Result (order across reducers is not guaranteed):
+------------+-------------+
| region | total_price |
+------------+-------------+
| shanghai | 100.5 |
| shanghai | 100.4 |
| china | 100.3 |
| china | 100.2 |
| china | 100.1 |
| shanghai | NULL |
+------------+-------------+Column aliases inORDER BY,DISTRIBUTE BY, andSORT BYcan be specified in Chinese.
LIMIT clause
LIMIT <number> restricts the number of output rows. The value must be a 32-bit integer with a maximum of 2,147,483,647.
LIMIT filters data after a distributed scan. It does not reduce the amount of data scanned or lower computing costs.Remove the screen display limit
If a SELECT statement has no LIMIT clause, or if LIMIT exceeds the project's display limit (n), the results window shows at most n rows.
Data protection disabled: In
odpscmd_config.ini, setuse_instance_tunnel=true. Withoutinstance_tunnel_max_record, the display is unlimited. With it, the display is capped by the value—up to 10,000 rows. For details, see Usage notes.Data protection enabled: The display is capped by
READ_TABLE_MAX_ROW, up to 10,000 rows.
Run SHOW SecurityConfiguration; to check the ProjectProtection setting. If ProjectProtection=true, disable data protection with SET ProjectProtection=false; only if your project's requirements allow it. For more information, see Data protection mechanism.
WINDOW clause
For window function syntax, see Window function syntax.