在 OVER(PARTITION BY) 中使用 CTE

Posted

技术标签:

【中文标题】在 OVER(PARTITION BY) 中使用 CTE【英文标题】:Using a CTE in OVER(PARTITION BY) 【发布时间】:2017-03-22 14:06:32 【问题描述】:

我正在尝试从表中的 3 列计算体积并仅返回唯一的体积。我们有许多行具有相同的WidthHeightLength,因此我的体积计算自然会有Volume 的重复返回值。我的印象是,为了做到这一点,我必须使用OVERPARTITIONCTE,因为在OVER 中不允许引用别名

WITH
cteVolume (Id, Volume)
AS 
(
    SELECT Id, Width * Height * [Length] AS Volume FROM  PackageMaterialDimensions
)
SELECT * 
INTO #volumeTempTable
FROM (
SELECT pp.ID, (pp.Width * pp.Height * pp.[Length]) AS Volume,
ROW_NUMBER() OVER(PARTITION BY cte.Volume ORDER BY pp.ID DESC) rn
FROM PlanPricing pp
INNER JOIN cteVolume cte ON pp.ID = cte.Id
) a
WHERE rn = 1

SELECT * FROM #volumeTempTable
ORDER BY Volume DESC

DROP TABLE #volumeTempTable  

注意,临时表的原因是因为我计划对这些数据做一些额外的工作。我目前也在调试,所以我正在使用这些表来输出到数据窗口

这是这个查询的问题 - 它仍然返回重复 - 每行只返回一卷 - 当表中有 71000 行时,它只返回大约 75 行

我如何修改此查询以基本上执行以下操作 - 计算表中每一行的体积 - 选择具有独特体积计算的行。 (我不想在我的结果集中看到两次相同的卷)

编辑 - 按要求提供数据

当前数据集忽略多余的列

我想要的是 身份证 |音量 193 | 280 286 | 350 274 | 550 241 | 720

基本上,我想计算每一行的体积,然后我想以某种方式按体积分组,以减少重复并从每组中选择第一行

【问题讨论】:

请澄清“SELECT rows DISTINCT by volume”是什么意思。样本数据和期望的结果会有所帮助。 @Adrian SELECT MIN(id), Width * Height * [Length] AS Volume FROM PackageMaterialDimensions GROUP BY Width * Height * [Length] 不够吗? 【参考方案1】:

这是你想要的吗?

WITH cteVolume (Id, Volume) AS (
      SELECT Id, Width * Height * [Length] AS Volume
      FROM PackageMaterialDimensions
    )
SELECT DISTINCT volume
FROM CTE ;

如果您希望每个卷有一个 id:

WITH cteVolume (Id, Volume) AS (
      SELECT Id, Width * Height * [Length] AS Volume
      FROM PackageMaterialDimensions
    )
SELECT volume, MIN(Id) as Id
FROM CTE
GROUP BY volume;

【讨论】:

不,因为我在结果集中有重复的卷。我刚刚用您要求的信息更新了问题。让我知道该信息是否澄清了事情。 我可以在您建议的查询中执行DISTINCT,但现在的问题是我需要更多的数据而不仅仅是卷。我至少需要 ID【参考方案2】:

也许您的问题来自于从PackageMaterialDimensions 表中分区cte.volume,但您还从PlanPricing 表中选择pp.volume

如果没有关于您的数据集和表格的更多信息,无法确认。

【讨论】:

【参考方案3】:

据我所知,您不能在 CTE 的递归部分中使用 windows 函数。您必须在 CTE 部分内手动对它们求和。 所以,而不是

ROW_NUMBER() OVER(PARTITION BY cte.Volume ORDER BY pp.ID DESC) rn

随便写

1 as rn

在第一部分,和

rn+1 as rn

在第二部分。

【讨论】:

以上是关于在 OVER(PARTITION BY) 中使用 CTE的主要内容,如果未能解决你的问题,请参考以下文章

在mysql中使用sum() over(Partition by)组合多行数据

使用 OVER (PARTITION BY ) 而不是 Group By

oracle查询中over(partition by ...order by ...)用法

Hive 问题 - Rank() OVER (PARTITION BY Dept ORDER BY sum(salary))

使用 Row_number() OVER(partition BY..) 以及声明局部变量

Junit 测试用例 - HSQLDB count(...) over (partition ... order by ...)