Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance SQL Server-按客户和时间戳日期分组的最大时间戳行的主键_Performance_Sql Server 2008_Tsql_Select_Aggregate Functions - Fatal编程技术网

Performance SQL Server-按客户和时间戳日期分组的最大时间戳行的主键

Performance SQL Server-按客户和时间戳日期分组的最大时间戳行的主键,performance,sql-server-2008,tsql,select,aggregate-functions,Performance,Sql Server 2008,Tsql,Select,Aggregate Functions,首先,我看到了这个问题: 我的问题不同之处在于,我需要的不仅仅是一行,因为我需要所有的客户Id 我认为自己是一个合格的SQL开发人员,但我一直在处理一个晦涩难懂的数据库设计,我无法控制它(但我离题了)。 我正在寻找更高效的方法,在筛选、最大聚合和分组后获取行的主键 我处理的是版本表(这意味着同一行的许多副本在“关闭”之前都会有轻微的数据元素更改)。对于包含特定OrderItem(OrderItem='1111')的一组“订单”,我需要在一个时间段(OrderDateTime)之间获取每个客户每天

首先,我看到了这个问题: 我的问题不同之处在于,我需要的不仅仅是一行,因为我需要所有的客户Id

我认为自己是一个合格的SQL开发人员,但我一直在处理一个晦涩难懂的数据库设计,我无法控制它(但我离题了)。 我正在寻找更高效的方法,在筛选、最大聚合和分组后获取行的主键

我处理的是版本表(这意味着同一行的许多副本在“关闭”之前都会有轻微的数据元素更改)。对于包含特定OrderItem(OrderItem='1111')的一组“订单”,我需要在一个时间段(OrderDateTime)之间获取每个客户每天的最后一个已关闭(Closed=1)订单。我不确定我是否理解这一点。:-)

*注意,为了简洁易懂,我已经尽力将我的用例转换为通用术语。订单和订单项(因为它们是相当学术性的)而不是我真正想要的

传统上,我写过这样的东西

SELECT
    Order.Order_ID
FROM
(
    SELECT
        Customer_ID,
        MAX(OrderedDateTime) AS OrderedDateTime
    FROM
        Order_versioned
    JOIN
        OrderItems_versioned
            ON Order_versioned.OrderID = OrderItems_versioned.OrderID
                AND OrderItem.Item_ID = '1111'
    WHERE
        Order_versioned.Closed = 1
        AND Order_versioned.OrderedDateTime BETWEEN '2012-01-01 00:00:00' AND '2012-01-31 23:59:59'
    GROUP BY
        Order.Customer_ID
        , CAST(Order.OrderedDateTime AS DATE)
) t1
JOIN
    Order
        ON t1.Customer_ID = Order.Customer_ID
            t1.OrderedDateTime = Order.OrderedDateTime
背景:Customer_ID和OrderedDateTime将构成一个独特的行,这就是为什么我可以加入它们并确信这是一个单独的行

注意:Order_versioned.Closed和所有*ID列上都有索引

问题在于,虽然Order_versioned.Customer_ID已编制索引,但Order_versioned.OrderedDateTime未编制索引,并且我无法(出于许多原因…感谢支持合同)添加索引。不用说,这种方法需要一段时间(2000万个订单中只有27400万个OrderItems)

我可以在子查询中添加更多索引字段并将其添加到联接中,但理想情况下,我需要一种新的方法

我希望有一个比我更绝地的人有一些我不知道的特征,可以为我指明正确的方向。我认为SQL Server的窗口功能(覆盖、分区等)以及适当的聚合可能会满足我的需要,我只是对这些新功能不够熟悉(是的,我知道它们是2005年的)。再说一次,考虑到我的限制,这可能是最好的方法。我希望SQL Server在MAX聚合上维护某种指向记录的内部指针,但我不知道如何访问它

谢谢您的时间。

也许这会有所帮助:
我举了一个使用货币和货币值的小例子。例如,任务是获取货币的最新货币值。我认为您可以很容易地将这个示例应用到代码中。下面是一个例子:

DECLARE @tblCurrency TABLE
    (
        pkCurrencyID INT,
        name VARCHAR(100)
    )
DECLARE @tblCurrencyValues TABLE
    (
        pkCurrencyValueID INT,
        currencyDate DATETIME,
        fkCurrencyID INT,
        rate FLOAT
    )

INSERT INTO @tblCurrency
(
    pkCurrencyID,
    name
)
SELECT 1,'SEK' 
UNION ALL 
SELECT 2,'EURO'
UNION ALL
SELECT 3, 'DKK'

INSERT INTO @tblCurrencyValues
(
    pkCurrencyValueID,
    fkCurrencyID,
    currencyDate,
    rate
)
SELECT 1,1,GETDATE(),1.4
UNION ALL
SELECT 2,1,GETDATE()-2,1.4
UNION ALL
SELECT 3,1,GETDATE()-1,5
UNION ALL
SELECT 4,2,GETDATE(),1.4
UNION ALL
SELECT 5,2,GETDATE()-2,1.4
UNION ALL
SELECT 6,2,GETDATE()-1,5
UNION ALL
SELECT 7,3,GETDATE(),1.4
UNION ALL
SELECT 8,3,GETDATE()-2,1.4
UNION ALL
SELECT 9,3,GETDATE()-1,5

;WITH CTE
AS
(
    SELECT
        RANK() OVER(PARTITION BY tblCurrencyValues.fkCurrencyID order by tblCurrencyValues.currencyDate) as currencyValueRank,
        tblCurrencyValues.fkCurrencyID,
        tblCurrencyValues.currencyDate,
        tblCurrencyValues.rate
    FROM
        @tblCurrencyValues AS tblCurrencyValues
)
SELECT 
    *
FROM
    CTE
    JOIN @tblCurrency AS tblCurrency
        ON CTE.fkCurrencyID=tblCurrency.pkCurrencyID
WHERE 
    CTE.currencyValueRank=1
也许这会有帮助:
我举了一个使用货币和货币值的小例子。例如,任务是获取货币的最新货币值。我认为您可以很容易地将这个示例应用到代码中。下面是一个例子:

DECLARE @tblCurrency TABLE
    (
        pkCurrencyID INT,
        name VARCHAR(100)
    )
DECLARE @tblCurrencyValues TABLE
    (
        pkCurrencyValueID INT,
        currencyDate DATETIME,
        fkCurrencyID INT,
        rate FLOAT
    )

INSERT INTO @tblCurrency
(
    pkCurrencyID,
    name
)
SELECT 1,'SEK' 
UNION ALL 
SELECT 2,'EURO'
UNION ALL
SELECT 3, 'DKK'

INSERT INTO @tblCurrencyValues
(
    pkCurrencyValueID,
    fkCurrencyID,
    currencyDate,
    rate
)
SELECT 1,1,GETDATE(),1.4
UNION ALL
SELECT 2,1,GETDATE()-2,1.4
UNION ALL
SELECT 3,1,GETDATE()-1,5
UNION ALL
SELECT 4,2,GETDATE(),1.4
UNION ALL
SELECT 5,2,GETDATE()-2,1.4
UNION ALL
SELECT 6,2,GETDATE()-1,5
UNION ALL
SELECT 7,3,GETDATE(),1.4
UNION ALL
SELECT 8,3,GETDATE()-2,1.4
UNION ALL
SELECT 9,3,GETDATE()-1,5

;WITH CTE
AS
(
    SELECT
        RANK() OVER(PARTITION BY tblCurrencyValues.fkCurrencyID order by tblCurrencyValues.currencyDate) as currencyValueRank,
        tblCurrencyValues.fkCurrencyID,
        tblCurrencyValues.currencyDate,
        tblCurrencyValues.rate
    FROM
        @tblCurrencyValues AS tblCurrencyValues
)
SELECT 
    *
FROM
    CTE
    JOIN @tblCurrency AS tblCurrency
        ON CTE.fkCurrencyID=tblCurrency.pkCurrencyID
WHERE 
    CTE.currencyValueRank=1

采取阿里昂建议的进一步行动。下面是我在原始问题中使用windowing和CTE(Arion的建议)提供的确切端口


它非常快。但我正在做更多的调查,以确保这是产生最好的性能。

进一步采取Arion建议的措施。下面是我在原始问题中使用windowing和CTE(Arion的建议)提供的确切端口

它非常快。但我正在做更多的调查,以确保这是产生最好的性能