标签: window-functions

从带有外部参数化“where”子句的视图中调用时,窗口函数会导致糟糕的执行计划

很久以前我遇到过这个问题,我找到了一个适合我的解决方法并忘记了它。

但是现在在 SO 上有这个问题,所以我愿意提出这个问题。

有一个视图以非常简单的方式(订单 + 订单行)连接几个表。

在没有where子句的情况下查询时,视图返回几百万行。
然而,从来没有人这样称呼它。通常的查询是

select * from that_nasty_view where order_number = 123456;
Run Code Online (Sandbox Code Playgroud)

这将返回 5m 中的大约 10 条记录。

一件重要的事情:视图包含一个窗口函数,rank(),它由始终查询视图所使用的字段精确分区:

rank() over (partition by order_number order by detail_line_number)
Run Code Online (Sandbox Code Playgroud)

现在,如果使用查询字符串中的文字参数查询此视图,完全如上所示,它会立即返回行。执行计划很好:

  • 使用索引对两个表进行索引查找order_number(返回 10 行)。
  • 在返回的微小结果上计算窗口。
  • 选择。

然而,当以参数化的方式调用视图时,事情变得很糟糕:

  • Index scan在所有表上忽略索引。返回 5m 行。
  • 巨大的加入。
  • 计算所有partitions 的窗口(大约 500k 个窗口)。
  • Filter 从 5m 中取出 10 行。
  • 选择

在涉及参数的所有情况下都会发生这种情况。它可以是 SSMS:

declare @order_number int = 123456;
select * from that_nasty_view where order_number = @order_number; …
Run Code Online (Sandbox Code Playgroud)

sql-server-2008 view window-functions

10
推荐指数
2
解决办法
1926
查看次数

为什么我的 SQL Server 查询在 UPDATE 和 SELECT 上的表现不同?

我编写了一个 SQL Server 查询,它在对字段进行分区后更新记录以具有序列号。当我将它作为 SELECT 语句运行时,一切看起来都很棒:

DECLARE @RunDetailID INT = 448
DECLARE @JobDetailID INT

SELECT @JobDetailID = [JobDetailID] FROM [RunDetails] WHERE [RunDetailID] = @RunDetailID

SELECT
    [OrderedRecords].[NewSeq9],
    RIGHT([OrderedRecords].[NewSeq9], 4)
FROM
    (
        SELECT
            [Records].*,
            [Records].[SortField] + RIGHT('0000' + CAST(ROW_NUMBER() OVER(PARTITION BY [Records].[SortField] ORDER BY [Records].[RunDetailID], [Records].[SortField], [Records].[PieceID]) AS VARCHAR), 4) NewSeq9
        FROM
        (
            SELECT
                [MRDFStorageID], 
                [RunDetailID], 
                [SortField], 
                [PieceID], 
                [Seq9], 
                [BallotType]
            FROM
                [MRDFStorage]
                    JOIN [BallotStyles] ON [MRDFStorage].[SortField] = [BallotStyles].[Style] and [BallotStyles].[JobDetailID] = @JobDetailID
            WHERE
                [RunDetailID] IN (SELECT [RunDetailID] FROM [RunDetails] WHERE [JobDetailID] = …
Run Code Online (Sandbox Code Playgroud)

sql-server subquery window-functions update

10
推荐指数
1
解决办法
363
查看次数

基于时间戳的窗口偏移

我正在编写一个查询,用于对社交提要的结果进行分页。这个概念是移动应用程序将请求 N 个项目,并提供我在@CutoffTime下面调用的开始日期时间。截止时间的目的是确定分页窗口应该何时开始。我们使用时间戳而不是行偏移量的原因是,即使添加了较新的社交内容,时间戳也会让我们在获取较旧帖子时从一致的位置翻页。

由于社交提要项目可以来自您自己或您的朋友,因此我使用 aUNION来组合这两个组的结果。最初我尝试了TheQuery_CTE没有的逻辑UNION,结果很慢。

这就是我所做的(包括相关的表架构):

    CREATE TABLE [Content].[Photo]
(
    [PhotoId] INT NOT NULL PRIMARY KEY IDENTITY (1, 1), 
    [Key] UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID(),
    [FullResolutionUrl] NVARCHAR(255) NOT NULL, 
    [Description] NVARCHAR(255) NULL, 
    [Created] DATETIME2(2) NOT NULL DEFAULT SYSUTCDATETIME(),
);

CREATE TABLE [Content].[UserPhotoAssociation]
(
    [PhotoId] INT NOT NULL, 
    [UserId] INT NOT NULL, 
    [ShowInSocialFeed] BIT NOT NULL DEFAULT 0,

    CONSTRAINT [PK_UserPhotos] PRIMARY KEY ([PhotoId], [UserId]), 
    CONSTRAINT [FK_UserPhotos_User] FOREIGN KEY ([UserId]) 
        REFERENCES [User].[User]([UserId]), 
    CONSTRAINT [FK_UserPhotos_Photo] …
Run Code Online (Sandbox Code Playgroud)

sql-server azure-sql-database window-functions paging

10
推荐指数
1
解决办法
255
查看次数

计数(*)超过()

我有一个COUNT(*) OVER ()作为查询的一部分来获取大量数据,其中包含大约 15 个表的连接(有些大,有些小)。这里计数的最佳解决方案是什么?

  1. 单独查询以查找计数。
  2. COUNT(*) OVER () 作为获取数据的查询的一部分(因为它将计算每一行的计数?!)
  3. 或查询以获取计数并结合查询以获取数据。(当然,我必须为数据查询要获取的所有其他列设置 null。)

sql-server-2008 sql-server window-functions

10
推荐指数
2
解决办法
1万
查看次数

具有最大和最小日期以及每行关联 ID 的 PostgreSQL 查询

我有下表:

CREATE TABLE trans (
    id SERIAL PRIMARY KEY,
    trans_date date,
    trans_time time        
);
Run Code Online (Sandbox Code Playgroud)

我想有以下观点

CREATE OR REPLACE VIEW daily_trans AS
SELECT trans_date,
    max(trans_time) as first, 
    min(trans_time) as last,
    calculate_status(min(trans_time), max(trans_time)) as status 
GROUP BY trans_date 
Run Code Online (Sandbox Code Playgroud)

带有指定最大和最小 trans_time id 的列。

我怎么做?

postgresql aggregate window-functions

9
推荐指数
2
解决办法
1万
查看次数

用row_number() 和dense_rank() 解决“差距和孤岛”?

如何用解决的孤岛部分。我现在已经看过几次了,我想知道是否有人可以解释一下,dense_rank()row_number()

让我们使用这样的东西作为示例数据(示例使用 PostgreSQL),

CREATE TABLE foo
AS
  SELECT x AS id, trunc(random()*3+1) AS x
  FROM generate_series(1,50)
    AS t(x);
Run Code Online (Sandbox Code Playgroud)

这应该产生这样的东西。

 id | x 
----+---
  1 | 3
  2 | 1
  3 | 3
  4 | 3
  5 | 3
  6 | 2
  7 | 3
  8 | 2
  9 | 1
 10 | 3
...
Run Code Online (Sandbox Code Playgroud)

我们想要的是这样的...... z我们可以使用的价值在哪里GROUP BY

 id | x | grp
----+------
  1 | 3 | z
  2 | …
Run Code Online (Sandbox Code Playgroud)

postgresql window-functions gaps-and-islands rank

9
推荐指数
1
解决办法
8228
查看次数

`OVER` 子句中的 `ORDER BY` 和 `PARTITION BY` 参数有什么区别?

下面的这些查询都给了我完全相同的结果,我认为这是因为我的数据集而不是参数如何工作。

使用OVER子句时,ORDER BY和之间有什么区别PARTITION BY

稍微不同的是,为什么不使用该术语GROUP BY而不是更复杂的声音PARTITION BY,因为在这种情况下使用分区似乎与分组实现了相同的目的。我知道您可以更改这些内部分区,然后这些更改会反映在表中。是这个原因吗?

查询 1:

SELECT
    CP.iYear,
    AVG(AVG(CP.mUpgradeCost)) OVER(ORDER BY iYear) AS [avg]
FROM ProForma.dbo.CapitalProject CP
GROUP BY CP.iYear
Run Code Online (Sandbox Code Playgroud)

查询 2:

SELECT
    CP.iYear,
    AVG(AVG(CP.mUpgradeCost)) OVER(PARTITION BY iYear) AS [avg]
FROM ProForma.dbo.CapitalProject CP
GROUP BY CP.iYear
Run Code Online (Sandbox Code Playgroud)

window-functions

9
推荐指数
1
解决办法
2万
查看次数

使用加窗函数优化子查询

由于我的性能调优技巧似乎永远不够用,我总是想知道我是否可以针对某些查询执行更多优化。此问题涉及的情况是嵌套在子查询中的 Windowed MAX 函数。

我正在挖掘的数据是对不同组较大集的一系列事务。我有 4 个重要的字段,交易的唯一 ID,一批交易的组 ID,以及与各自唯一交易或交易组相关的日期。大多数情况下,集团日期与批次的最大唯一交易日期相匹配,但有时会通过我们的系统进行手动调整,并在捕获集团交易日期后进行唯一日期操作。此手动编辑不会按设计调整组日期。

我在此查询中确定的是唯一日期落在组日期之后的那些记录。以下示例查询构建了与我的场景大致相当的内容,SELECT 语句返回我正在查找的记录,但是,我是否以最有效的方式接近此解决方案?这需要一段时间才能在我的事实表加载期间运行,因为我的记录计数在前 9 位数字中,但主要是我对子查询的蔑视让我想知道这里是否有更好的方法。我并不关心任何索引,因为我相信它们已经到位;我正在寻找的是一种替代查询方法,它可以实现相同的目标,但效率更高。欢迎任何反馈。

CREATE TABLE #Example
(
    UniqueID INT IDENTITY(1,1)
  , GroupID INT
  , GroupDate DATETIME
  , UniqueDate DATETIME
)

CREATE CLUSTERED INDEX [CX_1] ON [#Example]
(
    [UniqueID] ASC
)


SET NOCOUNT ON

--Populate some test data
DECLARE @i INT = 0, @j INT = 5, @UniqueDate DATETIME, @GroupDate DATETIME

WHILE @i < 10000
BEGIN

    IF((@i + @j)%173 = 0)
    BEGIN
        SET @UniqueDate = GETDATE()+@i+5
    END
    ELSE
    BEGIN …
Run Code Online (Sandbox Code Playgroud)

performance sql-server sql-server-2012 window-functions query-performance

9
推荐指数
3
解决办法
5835
查看次数

存储数百万行非标准化数据或一些 SQL 魔法?

我的 DBA 经验只是简单的存储 + CMS 样式数据的检索 - 所以这可能是一个愚蠢的问题,我不知道!

我有一个问题,我需要查找或计算特定组大小和特定时间段内特定天数的假期价格。例如:

1 月任何时候 2 人 4 晚的酒店房间多少钱?

例如,我有 5000 家酒店的定价和可用性数据,如下所示:

Hotel ID | Date | Spaces | Price PP
-----------------------------------
     123 | Jan1 | 5      | 100
     123 | Jan2 | 7      | 100
     123 | Jan3 | 5      | 100
     123 | Jan4 | 3      | 100
     123 | Jan5 | 5      | 100
     123 | Jan6 | 7      | 110
     456 | Jan1 | 5      | 120
     456 | Jan2 …
Run Code Online (Sandbox Code Playgroud)

postgresql window-functions datetime denormalization

8
推荐指数
1
解决办法
769
查看次数

查询 PostgreSQL 9 中分组连续行的总和

我有关于在不同国家旅行的人的数据,如下所示:

country | begintimestamp      | distance    

Germany | 2015-01-01 00:00:00 | 100
Germany | 2015-01-01 01:12:13 | 30
France  | 2015-01-01 02:13:14 | 40
France  | 2015-01-01 03:14:15 | 20
Spain   | 2015-01-01 04:15:16 | 10
France  | 2015-01-01 05:16:17 | 30
France  | 2015-01-01 05:17:18 | 5
Germany | 2015-01-01 06:18:19 | 3
Run Code Online (Sandbox Code Playgroud)

我需要的是能够收到这样的结果 -distance与最早的连续行相加begintimestamp

country | begintimestamp      | distance

Germany | 2015-01-01 00:00:00 | 130  // 100+30, the distance of two first rows summed. …
Run Code Online (Sandbox Code Playgroud)

postgresql window-functions

8
推荐指数
1
解决办法
3104
查看次数