SQL 查询

所有 DML(数据操作语言)语句都可包含查询。此部分介绍 Vertica 中的部分查询类型,其他详细信息将在后续几节介绍。

简单查询

简单查询包含对一个表执行的查询。以下查询会查找产品表中的产品键和 SKU 编号,处理它只需要很少的工作量。

=> SELECT product_key, sku_number FROM public.product_dimension;
product_key  | sku_number
-------------+-----------
43           | SKU-#129
87           | SKU-#250
42           | SKU-#125
49           | SKU-#154
37           | SKU-#107
36           | SKU-#106
86           | SKU-#248
41           | SKU-#121
88           | SKU-#257
40           | SKU-#120
(10 rows)

表可以包含数组。您可以选择整个数组列、其索引或应用于数组的函数的结果。有关详细信息,请参阅数组和集(集合)

联接

联接使用关系运算符合并两个或两个以上表中的信息。查询的 ON 子句会指定表的合并方式,例如通过将外键与主键相匹配。在以下示例中,查询通过联接商店架构的销售事实表和销售表中的商店键 ID,请求交易量大于 70 的商店的名称。

=> SELECT store_name, COUNT(*) FROM store.store_sales_fact
   JOIN store.store_dimension ON store.store_sales_fact.store_key = store.store_dimension.store_key
   GROUP BY store_name HAVING COUNT(*) > 70 ORDER BY store_name;

 store_name | count
------------+-------
 Store49    |    72
 Store83    |    78
(2 rows)

有关更多详细信息,请参阅联接。另请参阅子查询示例中的“多列子查询”部分。

交叉联接

交叉联接又称为笛卡儿积,它会将一个表中所有记录与另一个表中所有记录联接在一起。当表之间没有联接键来限制记录时,则会产生交叉联接。例如,以下查询返回了供应商表和商店表中供应商和商店名称的所有实例。

=> SELECT vendor_name, store_name FROM public.vendor_dimension
    CROSS JOIN store.store_dimension;
vendor_name         | store_name
--------------------+------------
Deal Warehouse      | Store41
Deal Warehouse      | Store12
Deal Warehouse      | Store46
Deal Warehouse      | Store50
Deal Warehouse      | Store15
Deal Warehouse      | Store48
Deal Warehouse      | Store39
Sundry Wholesale    | Store41
Sundry Wholesale    | Store12
Sundry Wholesale    | Store46
Sundry Wholesale    | Store50
Sundry Wholesale    | Store15
Sundry Wholesale    | Store48
Sundry Wholesale    | Store39
Market Discounters  | Store41
Market Discounters  | Store12
Market Discounters  | Store46
Market Discounters  | Store50
Market Discounters  | Store15
Market Discounters  | Store48
Market Discounters  | Store39
Market Suppliers    | Store41
Market Suppliers    | Store12
Market Suppliers    | Store46
Market Suppliers    | Store50
Market Suppliers    | Store15
Market Suppliers    | Store48
Market Suppliers    | Store39
...                 | ...
(4000 rows)

此示例的输出已截断,因为这个特殊的交叉联接返回了几千行。另请参阅交叉联接

子查询

子查询是一种嵌套在其他查询中的查询。在以下示例中,我们希望列出脂肪含量最高的所有产品。内查询(子查询)向外查询块(包含查询)返回了所有食品产品中脂肪含量最高的产品。然后,外查询使用这些信息返回脂肪含量最高的产品的名称。

=> SELECT product_description, fat_content FROM public.product_dimension
   WHERE fat_content IN
     (SELECT MAX(fat_content) FROM public.product_dimension
      WHERE category_description = 'Food' AND department_description = 'Bakery')
   LIMIT 10;
         product_description         | fat_content
-------------------------------------+-------------
 Brand #59110 hotdog buns            |          90
 Brand #58107 english muffins        |          90
 Brand #57135 english muffins        |          90
 Brand #54870 cinnamon buns          |          90
 Brand #53690 english muffins        |          90
 Brand #53096 bagels                 |          90
 Brand #50678 chocolate chip cookies |          90
 Brand #49269 wheat bread            |          90
 Brand #47156 coffee cake            |          90
 Brand #43844 corn muffins           |          90
(10 rows)

有关详细信息,请参阅子查询

对查询排序

使用 ORDER BY 子句可以对查询返回的行进行排序。

有关查询结果的特殊说明

在不同计算机上运行某些查询得到的结果可能不同,其原因如下:

  • 由于精确度原因,在 FLOAT 类型上分区会返回具有不确定性的结果,尤其当数量接近于另一种类型时,例如输出范围非常小的 RADIANS() 函数的结果。

    如果您必须通过不属于 INTEGER 类型的数据进行分区,要想获得具有确定性的结果,请使用 NUMERIC

  • 大多数分析(和分析聚合,例如作为例外的 MIN()/MAX()/SUM()/COUNT()/AVG())依赖于输入数据的唯一顺序来获取具有确定性的结果。如果分析 window-order 子句无法解析数据中的关系,每次运行查询时结果都不相同。

    例如,在以下查询中,分析 ORDER BY 没有在查询中包含第一列 promotion_key。因此,对于 AVG(RADIANS(cost_dollar_amount)), product_version 的关系,同一个 promotion_key 在分析分区中的位置可能不同,从而产生不同的 NTILE() 编号。因此,DISTINCT 也可能具有不同的结果:

    => SELECT COUNT(*) FROM
          (SELECT DISTINCT SIN(FLOOR(MAX(store.store_sales_fact.promotion_key))),
       NTILE(79) OVER(PARTITION BY AVG (RADIANS
          (store.store_sales_fact.cost_dollar_amount ))
       ORDER BY store.store_sales_fact.product_version)
       FROM store.store_sales_fact
       GROUP BY store.store_sales_fact.product_version,
             store.store_sales_fact.sales_dollar_amount ) AS store;
     count
    -------
      1425
    (1 row)
    

    如果将 MAX(promotion_key) 添加到分析 ORDER BY,则结果在任何计算机上都是相同的:

    => SELECT COUNT(*) FROM (SELECT DISTINCT MAX(store.store_sales_fact.promotion_key),
        NTILE(79) OVER(PARTITION BY MAX(store.store_sales_fact.cost_dollar_amount)
       ORDER BY store.store_sales_fact.product_version,
       MAX(store.store_sales_fact.promotion_key))
       FROM store.store_sales_fact
       GROUP BY store.store_sales_fact.product_version,
         store.store_sales_fact.sales_dollar_amount) AS store;