【问题标题】:SQL Get First Value From TableSQL 从表中获取第一个值
【发布时间】:2017-10-11 18:45:46
【问题描述】:

我正在运行 MS SQL-Server-2016 我正在尝试从对 ParentId 进行分区的表中获取第一个值。我有一个这样的数据集:

CREATE TABLE #TempTable
(
    PTORequestDetailId INT,
    PTORequestId INT,
    DivisionPTOAccrualId INT,
    RequestDate DATE,
    StartTime DateTime,
    Hours Decimal(19,2),
    ResponseNotes nvarchar(500),
    Status int,
    CreatedOn DateTime,
    ModifiedOn DateTime
)

INSERT INTO #TempTable
SELECT 60,  48, 139, '2015-09-09',  '2015-09-08 20:00:00.000',  8.00,'',0, '2015-09-09 13:30:40.363',   '2015-09-09 13:30:40.313' UNION
SELECT 61,  48, 139, '2015-09-10',  '2015-09-09 20:00:00.000',  8.00,'',0, '2015-09-09 13:30:40.363',   '2015-09-09 13:30:40.313' UNION
SELECT 62,  48, 139, '2015-09-11',  '2015-09-10 20:00:00.000',  8.00,'',0, '2015-09-09 13:30:40.363',   '2015-09-09 13:30:40.313' UNION
SELECT 63,  48, 139, '2015-09-13',  '2015-09-12 20:00:00.000',  8.00,'',0, '2015-09-09 13:30:40.363',   '2015-09-09 13:30:40.313' UNION

CREATE TABLE #TempParent
(
    PTORequestId INT,
)

INSERT INTO #TempParent
SELECT 48

运行此程序将使用我正在使用的数据集创建一个临时表。 我正在尝试获取由#TempTable.PTORequestId 分区的 DivisionPTOAccrualId 的第一个值,

SELECT #TempParent.*, AccrualDetails.*
FROM #TempParent
CROSS APPLY (
        SELECT FIRST_VALUE(#TempTable.DivisionPTOAccrualId) 
            OVER (PARTITION BY #TempTable.PTORequestId 
                    ORDER BY #TempTable.PTORequestDetailId ASC
                    ROWS UNBOUNDED PRECEDING
                    ) as AccrualId
        FROM #TempTable
        WHERE #TempTable.PTORequestId = #TempParent.PTORequestId
        ) as AccrualDetails

我基本上试图从我的父级每行获取一次139,但 FIRST_VALUE 似乎返回多个结果,因此它创建了笛卡尔积。

所以不是获取单行结果集

PTORequestId:48 AccrualId: 139

第一个值应该只返回一个值 然而它返回 4 个值。 为什么会发生这种情况,如何让 FIRST_VALUE 每行返回一个值?

编辑

我认为这是因为我从 TempTable 中选择了 FIRST_VALUE,所以它为 Temp 表中的每一行选择了第一个值。但我实际上只做一次

对于任何需要澄清我做错了什么的人。 我期待我的分区按过滤表中的行。 我假设因为表上的 SUM 将返回整个表的总和,而不是每行整个表的总和。该总和工作基于分区数据,但事实并非如此。

【问题讨论】:

    标签: sql-server tsql sql-server-2016


    【解决方案1】:

    我不确定用First_Value() 做这件事,但我发现用Row_Number() 做这件事更容易,而且只记录第一条记录:

    ;With Cte As
    (
        Select  T.*,
                Row_Number() Over (Partition By T.PTORequestId Order By T.PTORequestDetailId) As RN
        From    #TempTable  T
        Join    #TempParent P   On  P.PTORequestId = T.PTORequestId
    )
    Select  PTORequestId, DivisionPTOAccrualId As AccruralId
    From    Cte
    Where   RN = 1
    

    【讨论】:

    • 第一个值函数本质上是做同样的事情。第一个值不起作用,因为我如何选择所有内容。我的联接创建了多行。
    • 但这帮助我认识到我的问题,我需要做更多的研究才能接受这个答案,但我认为你的权利我需要使用行号
    猜你喜欢
    • 2023-02-18
    • 2019-03-09
    • 1970-01-01
    • 2013-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    相关资源
    最近更新 更多