查询数据。

语法

select_statement ::=  SELECT [ JSON | HOTDATA ] ( select_clause | '*' )
                      FROM table_name
                      [ WHERE where_clause ]
                      [ GROUP BY group_by_clause ]
                      [ ORDER BY ordering_clause ]
                      [ PER PARTITION LIMIT (integer | bind_marker) ]
                      [ LIMIT (integer | bind_marker) ]
                      [ ALLOW FILTERING ]
select_clause    ::=  selector [ AS identifier ] ( ',' selector [ AS identifier ] )
selector         ::=  column_name
                      | term
                      | CAST '(' selector AS cql_type ')'
                      | function_name '(' [ selector ( ',' selector )* ] ')'
                      | COUNT '(' '*' ')'
where_clause     ::=  relation ( AND relation )*
relation         ::=  column_name operator term
                      '(' column_name ( ',' column_name )* ')' operator tuple_literal
                      TOKEN '(' column_name ( ',' column_name )* ')' operator term
operator         ::=  '=' | '<' | '>' | '<=' | '>=' | '!=' | IN | CONTAINS | CONTAINS KEY
group_by_clause  ::=  column_name ( ',' column_name )*
ordering_clause  ::=  column_name [ ASC | DESC ] ( ',' column_name [ ASC | DESC ] )*
说明
  • SELECT语句读取表中一个或多个行的一个或多个列。它返回与请求匹配的行的结果集,其中每一行都包含与查询相对应的选择值。另外,可以将包括聚合函数在内的函数应用于结果。
  • SELECT语句至少包含一个选择子句和该选择所在的表的名称。请注意,Lindorm CQL暂不支持join或子查询,因此select语句仅适用于单个表。在大多数情况下,select还有where子句,并且可以选择其他子句来对结果进行排序或限制。如果提供了ALLOW FILTERING标志,则可以允许需要过滤的查询。

示例

CREATE TABLE persioninfo  (c1 int primary key, c2 text, c3 text);
SELECT c1, c2 FROM persioninfo WHERE c1 IN (199, 200, 207);
SELECT JSON c1, c2 FROM persioninfo WHERE c1 = 199;
SELECT c1 AS name, c2 AS address FROM persioninfo;


CREATE TABLE persioninfo  (c1 int , c2 text, c3 text, PRIMARY KEY(c1,c2));
SELECT *
FROM persioninfo
WHERE c1 = 12
  AND c2 > '2011-02-03'
  AND c2 <= '2012-01-01'

SELECT COUNT (*) AS user_count FROM persioninfo;

SELECT的选择子句

选择子句确定需要查询哪些列并在结果集中返回,以及在返回之前对该结果应用的任何转换。它由逗号分隔的选择器列表组成,或者由通配符(*)组成,以选择表中定义的所有列。包括以下内容:
  • Selectors
    包括以下类型:
    • column_name:所选表的列名,以检索该列的值。
    • term:一个term,通常嵌套在其他选择器(如函数)中,如果直接选择一个术语,则结果集的对应列将仅具有返回的每一行的该术语的值。
    • CAST '(' selector AS cql_type ')':强制转换,允许将嵌套选择器转换为(兼容)类型。
    • function_name '(' [ selector ( ',' selector )* ] ')':函数调用,其中参数是选择器本身。
    • COUNT '(' '*' ')':对COUNT函数的特殊调用COUNT(*),对所有非空结果进行计数。
  • WRITETIME function

    Selection仅支持特殊函数(其他任何地方都不允许)WRITETIME,这个函数仅接受一个参数,并且该参数必须为列名。这个函数允许检索存储在每个列内部的元信息,即WRITETIME列的值的时间戳。

  • where clause
    where子句指定必须查询的行。它由作为主键的一部分,或在其上定义了二级索引的列的关系组成。并非所有关系都允许在查询中。例如,不支持partition key的非相等关系(其中IN被视为相等关系)。对于给定的partition keyclustering column引起行的排序,并且它们的关系被限制为允许选择连续的(对于排序)行集的关系。例如,创建如下表posts
    CREATE TABLE posts (
        userid text,
        blog_title text,
        posted_at timestamp,
        entry_title text,
        content text,
        category int,
        PRIMARY KEY (userid, blog_title, posted_at)
    )    
    可以进行如下的查询:
     SELECT entry_title, content FROM posts
     WHERE userid = 'john doe'
       AND blog_title='John''s Blog'
       AND posted_at >= '2012-01-01' AND posted_at < '2012-01-31'
    但是不能进行如下的查询,因为它不会选择一组连续的行(并且我们假设未设置二级索引)。
    SELECT entry_title, content FROM posts
     WHERE userid = 'john doe'
       AND posted_at >= '2012-01-01' AND posted_at < '2012-01-31'
    此外,仅在partition key的最后一列和primary key的最后一列上允许IN关系,也可以使用元组符号将Clustering column组合在一起。如下:
    SELECT * FROM posts
     WHERE userid = 'john doe'
       AND (blog_title, posted_at) > ('John''s Blog', '2012-01-01')
    将按照聚类顺序要求所有排在“John''s Blog”为blog_tile和“ 2012-01-01”为post_at之后的行。特别是,只要post_at <='2012-01-01'的行的blog_title>'John's Blog',则将返回该行,但以下情况除外:
    SELECT * FROM posts
     WHERE userid = 'john doe'
       AND blog_title > 'John''s Blog'
       AND posted_at > '2012-01-01'
    元组符号也可用于clustering column的IN子句:
    SELECT * FROM posts
     WHERE userid = 'john doe'
       AND (blog_title, posted_at) IN (('John''s Blog', '2012-01-01'), ('Extreme Chess', '2014-06-01'))
  • Grouping results
    GROUP BY选项允许将所有共享一组列的相同值的选定行浓缩为单个行。使用GROUP BY选项,只能在partition key级别或clustering column级别对行进行分组。因此,GROUP BY选项仅按主键顺序接受主键列名称作为参数。如果主键列受到相等性限制的约束,则它不需要出现在GROUP BY子句中。
    说明 因为cql的group by是把数据拉到一个server节点进行处理,数据量大的情况下,整个事件比较长。
  • Ordering results
    ORDER BY子句允许选择返回结果的顺序。它以列名列表和列顺序作为参数(升序为ASC,降序为DESC,没有指定顺序与ASC等效)。当前,可能的顺序受表上定义的clustering order限制:
    • 如果表是在没有任何特定CLUSTERING ORDER的情况下定义的,则允许的排序是由clustering columns和与之相反的顺序引起的。
    • 否则,允许的顺序是CLUSTERING ORDER选项的顺序和相反的顺序。
  • Limiting results

    SELECT语句的LIMIT选项限制查询返回的行数。

  • Allowing filtering

    默认情况下,Lindorm CQL仅允许不涉及“filtering”服务器端的选择查询,即我们知道所有(实时)记录读取将在结果集中返回(或部分返回)的查询。原因是这些“non filtering”查询在某种意义上具有可预测的性能,因为它们将在与查询返回的数据量成比例的时间内执行(可以通过LIMIT进行控制)。

    ALLOW FILTERING选项允许显式允许(某些)需要过滤的查询。请注意,使用ALLOW FILTERING的查询可能因此具有不可预测的性能(对于上面的定义),即使选择少数记录的查询也可能表现出取决于集群中存储的数据总量的性能。

    例如,创建的如下表格,其中包含用户个人资料及其出生年份(带有次级索引)和居住国家/地区:
    CREATE TABLE users (
        username text PRIMARY KEY,
        firstname text,
        lastname text,
        birth_year int,
        country text
    )
    
    CREATE INDEX ON users(birth_year);
    可以进行以下有效查询:
    SELECT * FROM users;
    SELECT * FROM users WHERE birth_year = 1981;
    因为在这两种情况下,Lindorm CQL都会保证这些查询的性能与返回的数据量成正比。特别是,如果没有用户出生于1981年,那么第二次查询的性能将不取决于存储在数据库中的用户配置文件的数量(至少不是直接地:由于二级索引实现的考虑,该查询可能仍取决于该数量集群中节点的数量,这间接取决于存储的数据量。但是,节点数始终比存储的用户配置文件数低几个数量级。当然,在实践中,两个查询都可能返回非常大的结果集,但是始终可以通过添加LIMIT来控制返回的数据量。以下的查询将被拒绝:
    SELECT * FROM users WHERE birth_year = 1981 AND country = 'FR';
    因为Lindorm CQL无法保证即使这些查询的结果很小,也不必扫描大量数据。通常,它将扫描所有1981年出生的用户的索引条目,即使实际上只有少数来自法国。但是,如果您“知道自己在做什么”,则可以使用ALLOW FILTERING强制执行此查询,因此以下查询有效:
    SELECT * FROM users WHERE birth_year = 1981 AND country = 'FR' ALLOW FILTERING;
  • HOTDATA
    在用户建表指定冷热分离的场景下,如果用户想要查询热数据,可以在SELECT语句关键字下指定HOTDATA:
    SELECT HOTDATA * FROM persioninfo;

    默认不指定的话,请求会在冷热数据都进行查询,然后合并出所需的数据。

  • SEARCH INDEX SELECT操作
    对构建SEARCH INDEX的列支持模糊匹配查询,以及多维组合查询以及排序功能。
    • 常见模糊匹配
      构建SEARCH INDEX的列,在进行select操作的时候,支持对构建索引的列进行模糊匹配查询,模糊匹配使用%表示0到任意个字符匹配,常见的模糊匹配支持前缀匹配、后缀匹配、前后缀匹配、完全匹配。示例如下:
      SELECT * FROM persioninfo where c2 like 'v2';//完全匹配,c2列数字为v2。
      select * from kss.tb where c2 like '%v2' //前缀匹配,表示v2关键字符前支持0到任意个字符匹配。
      select * from kss.tb where c2 like 'v2%' //后缀匹配,表示v2关键字符后支持0到任意个字符匹配。
      select * from kss.tb where c2 like '%v2%'//contains匹配,表示v2关键字符前后支持任意个字符匹配。
    • 指定seach_query查询
      使用search_query关键字查询,支持在select 语句中支持任意类solr原生query的语句,满足更丰富的查询检索需求。示例如下:
      SELECT selectors
        FROM table
        WHERE (indexed_column_expression | search_query = 'search_expression') 
        [ LIMIT n ]
        [ ORDER BY column_name ] ;
      Select语句中search_query关键字后面会跟随search_expression,具体的search_query的跟随字符限制请参考跟随符限制。常见的search_query跟随的选项支持情况如下:
      {
        "q": query_expression (string), 
        "fq": filter_query_expression(s) (string_or_array_of_strings, ...),  
        "facet": facet_query_expression (object) 
        "sort": sort_expression (string), 
        "start": start_index(number),
        timeAllowed: search_time_limit_ms,  
        "TZ": zoneID),   //  Any valid zone ID in java TimeZone class                            
        "paging": "driver" (string),
        "distrib.singlePass": true|false (boolean),
        "shards.failover": true|false (boolean),    // Default: true
        "shards.tolerant": true|false (boolean),    // Default: false
        "commit": true|false (boolean),
        "route.partition": partition_routing_expression (array_of_strings), 
        "route.range": range_routing_expression (array_of_strings), 
        "query.name": query_name (string),
      }
      示例如下:
      CREATE TABLE persioninfo (name text PRIMARY KEY, city text,id int, friend nested) WITH extensions = {'CONSISTENCY_TYPE':'strong', 'MUTABILITY':'IMMUTABLE'};
      CREATE SEARCH INDEX sidx on persioninf WITH COLUMNS (id,city);
      INSERT INTO persioninfo (name,city, id, friend) VALUES ('MY','hangzhou', 18, '[{"lili":18}, {"gg":20}]');
      SELECT name,id FROM persioninfo  WHERE search_query = '+city:hangzhou +age:[1 TO 18]';
      说明 因为search_query支持的语义比较丰富,所以暂时不支持searc_query语句与其他condition的组合使用,比如select * from table where search_query = 'c1:name' And column = 'a',这种用法是不支持的。