选择未聚合的变量,功能上依赖于 GROUPing 变量

2024-04-04

背景

我正在一个非常受限的 T-SQL 环境中工作,其中只能定义一个对象的“主体”VIEW: 大概是... in

CREATE VIEW My_View AS ...

在引擎盖下。这是我的@@VERSION https://learn.microsoft.com/en-us/sql/t-sql/functions/version-transact-sql-configuration-functions?view=sql-server-linux-ver15:

Microsoft SQL Server 2019 (RTM-CU19) (KB5023049) - 15.0.4298.1 (X64)
2023 年 1 月 27 日 16:44:09
版权所有 (C) 2019 微软公司
Linux 上的网络版(64 位)(Amazon Linux 2)

我应该注意到这些表是从同步的平面文件,因此,没有formal保留了原始来源的示意性结构。也就是说,所有“功能依赖”都仅仅是inferred(尽管可靠)来自列名称和业务概念。

Problem

假设我有下表My_Measures...

Person_ID Name Measure
1 Greg 0
1 Greg 10
2 Devon 20
2 Devon 30

...在哪里Name功能上依赖于Person_ID.

通常

现在假设我希望总计的 the Measure进入每个人的各种汇总统计数据。这在 SQL 中很简单......

SELECT
    Person_ID,
    MIN(Measure) AS Min_Measure,
    MAX(Measure) AS Max_Measure,
    AVG(Measure) AS Avg_Measure
FROM 
    My_Measures
GROUP BY 
    Person_ID

...并产生以下结果:

Person_ID Min_Measure Max_Measure Avg_Measure
1 0 10 5
2 20 30 25

扭曲

但假设我想包括Name并排每个Person_ID,像这样:

Person_ID Name Min_Measure Max_Measure Avg_Measure
1 Greg 0 10 5
2 Devon 20 30 25

显然,以下尝试...

SELECT
    Person_ID,
--  ⌄⌄⌄⌄⌄
    Name,
--  ^^^^^
    MIN(Measure) AS Min_Measure,
    MAX(Measure) AS Max_Measure,
    AVG(Measure) AS Avg_Measure
FROM 
    My_Measures
GROUP BY 
    Person_ID

...将因以下错误而失败:

列“My_Measures.Name”在选择列表中无效,因为它未包含在聚合函数或 GROUP BY 子句中。

Attempts

我找到了几个un产生预期输出的令人满意的方法。

(1) GROUP BY因变量

一种方法是GROUP BY the Name column after Person_ID;更一般地说,将因变量附加到end of the GROUP BY clause:

SELECT
    Person_ID,
--  ⌄⌄⌄⌄⌄
    Name,
--  ^^^^^
    MIN(Measure) AS Min_Measure,
    MAX(Measure) AS Max_Measure,
    AVG(Measure) AS Avg_Measure
FROM
    My_Measures
GROUP BY
--           ⌄⌄⌄⌄⌄⌄
    Person_ID, Name
--           ^^^^^^

这使得分组保持不变,因为“真实”分组变量(此处Person_ID)已经定义了它,因变量只是“跟随”。然而,这会浪费处理(任意多个)因变量的性能,这可能会更复杂(CHAR字符串为Name) 用于索引目的。

(2)“聚合”因变量

另一种方法是“聚合”Name列,具有某些功能(例如MIN())这给了我们一个代表值(例如'Greg')来自许多相同的重复项(例如('Greg', 'Greg')).

SELECT
    Person_ID,
--  ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
    MIN(Name)    AS Name,
--  ^^^^^^^^^^^^^^^^^^^^^
    MIN(Measure) AS Min_Measure,
    MAX(Measure) AS Max_Measure,
    AVG(Measure) AS Avg_Measure
FROM 
    My_Measures
GROUP BY 
    Person_ID

这同样达到了预期的结果,但同样浪费了计算许多相同值的聚合的性能。此外,它仅适用于以下值可比从而有一个MIN();但它显然会失败non-可比较的数据类型。

(3) ReJOIN聚合后

也许最令人失望的方法是简单地计算聚合,然后重新关联Person_ID以其Name via a JOIN:

-- Aggregate by ID.
WITH agg AS(
    SELECT
        Person_ID,
        MIN(Measure) AS Min_Measure,
        MAX(Measure) AS Max_Measure,
        AVG(Measure) AS Avg_Measure
    FROM 
        My_Measures
    GROUP BY 
        Person_ID
    
-- Deduplicate names for the JOIN. Given functional dependency, DISTINCT suffices.
), msr AS (
    SELECT DISTINCT
        Person_ID,
        Name
    FROM My_Measures
    
-- Reassociate the names with their IDs.
) SELECT
    agg.Person_ID   AS Person_ID,
--  ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
    msr.Name        AS Name,
--  ^^^^^^^^^^^^^^^^^^^^^^^^
    agg.Min_Measure AS Min_Measure,
    agg.Max_Measure AS Max_Measure,
    agg.Avg_Measure AS Avg_Measure
FROM
--      ⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄⌄
    agg INNER JOIN msr
--      ^^^^^^^^^^^^^^
    ON agg.Person_ID = msr.Person_ID

显然,这将大量资源浪费在不必要的事情上JOIN和多个 CTE,全部都是为了recover数据(如Name)我们原来had!

(4) 采取FIRST_VALUE() Over a PARTITION

我在 T-SQL 中搜索了一些等效的内容first() https://dplyr.tidyverse.org/reference/nth.htmlR 中的函数。在 SQL 中,这样的FIRST()会简单地选择非常first value ('Greg')来自许多相同的重复项(('Greg', 'Greg'))在一个GROUP,不需要任何昂贵的计算。此外,这会起作用不管的可比性。

我偶然发现了FIRST_VALUE() https://learn.microsoft.com/en-us/sql/t-sql/functions/first-value-transact-sql?view=sql-server-linux-ver15功能,但这似乎需要一个PARTITION对于每种用法,以及 - 由于我在优化方面相对缺乏经验PARTITIONs — 我担心对性能的影响,如果many因变量必须是SELECTed.

它看起来也很丑。  ̄\(ツ)

Question

最好的方法是什么SELECT任意一组因变量(例如Name)以及分组变量(例如Person_ID)?请优先考虑表现,但还要考虑elegance and 正规最后可扩展性:这应该理想地适用于all数据类型,甚至non-可比。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

选择未聚合的变量,功能上依赖于 GROUPing 变量 的相关文章

  • FindAsync 很慢,但是延迟加载很快

    在我的代码中 我曾经使用加载相关实体await FindAsync 希望我能更好地遵守 C 异步指南 var activeTemplate await exec DbContext FormTemplates FindAsync exec
  • SQL Server:将 varchar 转换为十进制(也考虑指数表示法)

    我需要转换表的数据并进行一些操作 其中一种列数据类型是Varchar 但它存储decimal数字 我正在努力转换varchar into decimal 我努力了CAST TempPercent1 AS DECIMAL 28 16 问题是数
  • 小数除以小数并得到零

    为什么当我这样做时 select CAST 1 AS DECIMAL 38 28 CAST 1625625 AS DECIMAL 38 28 我得到 0 吗 但是当我得到 0 时 select CAST 1 AS DECIMAL 20 10
  • SQL查询多行变成单行

    有什么方法可以将通常返回具有相同值的多行的 SQL 查询更改为单行吗 例如 如果我现有的查询返回以下内容 ColA ColB 1 AA 1 BB 1 CC 2 AA 3 AA 我可以将查询更改为仅返回 3 行 并将 1 的第二个和第三个结果
  • 分组为连续整数范围

    我检查了其他帖子 包括使用 Linq 按可变整数范围进行分组 https stackoverflow com questions 1375997 group by variable integer range using linq 但我没有
  • SQL Server - 删除语句增加日志大小

    我有一个LOGGIN数据库很大 400 GB 它有数百万行 我刚刚跑了一个delete该语句花费了 2 5 小时并删除了可能数百万行 delete FROM DB dbo table where Level not in info erro
  • 动态/条件 SQL 连接?

    我在 MSSQL 表 TableB 中有数据 其中 dbo tableB myColumn 在特定日期后更改格式 我正在做一个简单的连接到该表 Select dbo tableB theColumnINeed from dbo tableA
  • PIVOT 运算符中指定的列名“FirstName”与 PIVOT 参数中的现有列名冲突

    当我尝试替换时收到以下错误消息null to zero PIVOT 运算符中指定的列名 jan 与 PIVOT 参数中的现有列名称 查询如下 select from select isnull jan 0 isnull feb 0 sum
  • 显示多个表的账户余额

    我有以下两个表 其中存储有关贷记和借记记录的信息 couponCr 表包含 voucherType voucherPrefix voucherNo crparty cramount SALES S 1 1 43000 SALES S 2 1
  • 动态SQL生成列名?

    我有一个查询 我正在尝试将行值转换为列名称 目前我正在使用SUM Case As ColumnName 声明 像这样 SELECT SKU1 SUM Case When Sku2 157 Then Quantity Else 0 End A
  • 如何使用 SQL Server 查询对“版本号”列进行排序

    我想知道我们当中的 SQL 天才是否可以向我伸出援助之手 我有一个专栏VersionNo在表中Versions包含 版本号 值 例如 VersionNo 1 2 3 1 1 10 3 1 1 4 7 2 etc 我正在寻找对此进行排序 但不
  • 无法使用 django-mssql 提供程序

    有谁知道如何使用 django mssql 提供程序 我已经安装了要求 但无法让它工作 如果 settings py 中没有 sqlserver ado 它可以正常导入 testenv C Users Robin test gt pytho
  • Powershell SQL Server数据库连接和连接超时问题

    我有一个连接到 SQL Server 2012 数据库的 powershell 脚本 该脚本运行 SQL 查询并将结果集放入数据表中 以将格式化的电子邮件发送给相关方 下面是问题所在的代码片段 CBA New Object System D
  • 如何找到查询结果的大小

    我在 Rails 中有以下查询 records Record select y id source where source gt source y id gt y id group y id source having count 1 如
  • 列的 SQL MAX(包括其主键)

    Short 从下面的 sql select 中 我获取了 cart id 和该购物车中最高价值商品的值 SELECT CartItems cart id MAX ItemValues value FROM CartItems INNER J
  • 如果不存在则插入数据(来自 2 个表),否则更新

    再会 我有3张桌子 tbl仓库产品 ProductID ProductName ProductCode Quantity tbl分公司产品 ProductID ProductCode ProductCode Quantity Locatio
  • 将存储过程的结果加上额外的列插入表中

    如何在其中插入更多列dbFileListOnly表以及 EXEC 查询 INSERT INTO admindb dbfilelistonly path col1 col2 path EXEC RESTORE FILELISTONLY FRO
  • 在 SQL Server 数据库之间传递用户定义的表类型

    我在 SQL Server 的一个数据库中有一个用户定义的表类型 我们称之为DB1 我的类型的定义非常简单 仅包含 2 列 创建我的类型的脚本如下 CREATE TYPE dbo CustomList AS TABLE ID int Dis
  • SQL Server 到 er 模型

    是否有程序可以将 SQL Server 数据库图表转换为 er 模型 或者从 SQL Server 服务器创建数据库的 er 模型 在 SQL Server 中 Management Studio 中的每个数据库都有 数据库图 功能 您可以
  • 获取 pandas 中最后一次出现特定值之后的所有行

    我的数据框看起来像 ID colA 1 B 1 D 2 B 2 D 2 C 我已返回每组中事件 B 最后一次出现后的所有行 输出将是 ID colA 1 D 2 D 2 C 我试过 a df colA str contains B grou

随机推荐