通过


ANY_VALUE(Transact-SQL)

适用于:Microsoft Fabric 中的仓库

ANY_VALUE 函数从一组行返回任何值(非(NULL 如果可能)。 可以将它用作聚合函数和窗口(分析)函数:

  • 聚合使用情况:从整个组返回任意值。
  • 窗口用法:对定义的窗口框架进行操作,并从整个窗口返回任意值。

Transact-SQL 语法约定

Syntax

聚合函数语法:

ANY_VALUE ( [ ALL | DISTINCT ] expression )

分析函数语法:

ANY_VALUE ( [ ALL | DISTINCT ] expression) OVER ( [ <partition_by_clause> ] [ <order_by_clause> ] )

Arguments

ALL

向所有值应用此聚合函数。 ALL 是默认选项,只有有意义的选项,并且仅适用于 ISO 兼容性。

独特

DISTINCT 对 ISO 兼容性没有意义 ANY_VALUE,并且仅适用于 ISO 兼容性。

expression

要返回的值。 任何值都可以作为结果返回,但如果 NULL 可能,则会跳过这些值。

OVER 子句

partition_by_clause将子句生成的FROM结果集划分为分区,并将函数应用于每个分区。

如果未指定此子句,该函数会将查询结果集的所有行视为单个组。

order_by_clause 在应用函数之前确定数据的顺序。 如果指定 partition_by_clause,它将确定分区中的数据顺序。 不需要 order_by_clause

有关详细信息,请参阅 SELECT - OVER 子句(Transact-SQL)。

返回类型

返回与 表达式相同的类型的值。

注解

ANY_VALUE 具有不确定性。 有关详细信息,请参阅 “确定性”和“不确定”函数。 与或LAST_VALUE不同FIRST_VALUEANY_VALUE不提供确定性排序。 它适用于确切值对查询逻辑不重要的情况。

函数在可能的情况下尝试返回非NULL值,并且仅当所有值均为NULL时返回NULL值。

用例

一个常见的用例 ANY_VALUE 是,你需要在按键列分组的结果集中包括非键列。 例如,如果将行分组依据StoreID,则可以使用 ANY_VALUE 返回列的值,例如存储名称、地址或其他描述性属性,而无需将它们添加到GROUP BY子句,或者LAST_VALUE使用更昂贵的函数(例如MAXMINFIRST_VALUE将它们包含在投影中)。 此方法简化了查询设计,提高了可读性,并增强了性能,因为 SQL 查询不需要对描述性列执行不必要的分组。 因此,聚合保持简洁、更易于维护、更高效。

示例

答: 检索任何非 NULL 值

此简单查询演示如何 ANY_VALUE 从一组值返回任意非 NULL 值:

SELECT ANY_VALUE(v)
FROM (VALUES (NULL), (NULL), (NULL), (NULL), (2), (NULL), (NULL), (7), (NULL), (NULL)) AS t(v);

该函数忽略 NULL 值并返回非NULL 值之一(有时为 2,有时为 7),以不确定的方式。

B. 项目描述性列

此查询通过联接FactSalesDimStore、分组StoreKey和检索密钥存储详细信息ANY_VALUE来汇总每个商店的总销售额。

USE ContosoDW;  
GO  
SELECT
    fs.StoreKey,
    ANY_VALUE(ds.StoreName)        AS StoreName,
    ANY_VALUE(ds.StoreDescription) AS StoreDescription,
    ANY_VALUE(ds.Status)           AS StoreStatus,
    ANY_VALUE(ds.Phone)            AS StorePhone,
    ANY_VALUE(ds.Fax)              AS StoreFax,
    ANY_VALUE(ds.ZipCode)          AS ZipCode,
    ANY_VALUE(ds.AddressLine1)     AS AddressLine1,
    ANY_VALUE(ds.AddressLine2)     AS AddressLine2,
    SUM(fs.UnitPrice * fs.SalesQuantity) AS SalesAmount
FROM dbo.FactSales AS fs
LEFT JOIN dbo.DimStore AS ds
    ON ds.StoreKey = fs.StoreKey
GROUP BY
    fs.StoreKey;  

通过应用ANY_VALUE函数,可以包括非分组列(例如StoreName,、StoreDescriptionStoreStatusStorePhoneZipCodeStoreFax、和AddressLine1AddressLine2),而无需在GROUP BY子句中列出它们。

C. 将值从行逆透视到列

FactSales 表包含每行项一行,用于 OrderKey 标识顺序。 对于每个顺序,属性(例如 OrderDateDeliveryDateCustomerKey会在 StoreKey 属于同一 OrderKey行的所有行中重复。 相比之下, ProductKey 各行项因行项而异,每个产品各有一个 LineNumber

以下查询将透视 FactSales 行,以便每个 OrderKey 行都是一行。 它保留共享订单级别属性,并为与每个行号关联的产品创建一个单独的列(ProductKey0ProductKey1...)。 该 ANY_VALUE 函数用于从每个组中选取一个代表性值,而条件表达式提取每个特定行项的产品。

SELECT
    OrderKey,
    -- Projecting groups that are same within the group.
    ANY_VALUE(OrderDate)      AS OrderDate,
    ANY_VALUE(DeliveryDate)   AS DeliveryDate,
    ANY_VALUE(CustomerKey)    AS CustomerKey,
    ANY_VALUE(StoreKey)       AS StoreKey,
    -- Unpivoted values returned as multiple columns per row
    ANY_VALUE(IIF(LineNumber = 0, ProductKey, NULL)) AS ProductKey0,
    ANY_VALUE(IIF(LineNumber = 1, ProductKey, NULL)) AS ProductKey1,
    ANY_VALUE(IIF(LineNumber = 2, ProductKey, NULL)) AS ProductKey2,
    ANY_VALUE(IIF(LineNumber = 3, ProductKey, NULL)) AS ProductKey3,
    ANY_VALUE(IIF(LineNumber = 4, ProductKey, NULL)) AS ProductKey4,
    ANY_VALUE(IIF(LineNumber = 5, ProductKey, NULL)) AS ProductKey5,
    ANY_VALUE(IIF(LineNumber = 6, ProductKey, NULL)) AS ProductKey6
FROM dbo.FactSales
GROUP BY
    OrderKey;

通过使用函数ANY_VALUE,可以避免在子句中放置OrderDateDeliveryDateCustomerKey放置和StoreKey放置GROUP BY。 该ANY_VALUE函数简化了查询并可以提高性能,因为子句中GROUP BY只使用单个列(OrderKey)。 该 ANY_VALUE + CASE WHEN 模式提取 ProductKey 适合每个行项,并将它们作为单独的列返回。 在实践中,此模式生成产品密钥的编程透视(传统运算符的 UNPIVOT 替代方法)。

D. 每两列分区的随机值

你正在为每个商店生成一个销售级详细信息报告,其中包含每日关键绩效指标(KPI)。 在报表中,需要返回每个 (StoreKey, ) 分区的相同SalesOrderNumberDateKey其中不存在业务规则来选取特定SalesOrderNumber规则。 无需在报表中按行选取最早、最新或最大订单。 例如,用户界面显示每行旁边的“商店日参考订单”,以便分析师可以快速跳转到(商店、日)对的订单。

目的是为每个(商店、天)返回一个一致 SalesOrderNumber

USE ContosoDW;
GO
SELECT
    fs.DateKey,
    fs.StoreKey,

    -- Window KPI: total sales per Store-Day (keeps row-level output)
    SUM(fs.UnitPrice * fs.SalesQuantity)
      OVER (PARTITION BY fs.StoreKey, dd.DateKey) AS DailySales,

    -- Partition label with no preferred ordering: any one order from that Store-Day
    ANY_VALUE(fs.SalesOrderNumber)
      OVER (PARTITION BY fs.StoreKey, dd.DateKey) AS SampleOrderNumber

FROM dbo.FactSales AS fs;

如果将表达式替换为ANY_VALUE(fs.SalesOrderNumber)fs.SalesOrderNumber列引用,则标签会逐行变化;将丢失“每个(商店,日)的一个一致性标签”行为。