【问题标题】:Selecting previous row number based on column value根据列值选择上一个行号
【发布时间】:2019-07-09 16:27:09
【问题描述】:

我正在尝试创建一个表,该表显示 Operator Shifts 将组合行 w Operator 登录和注销。由于有多个工作站和操作员,我需要根据操作员选择下一行,而不仅仅是下一个值。例如,当在下面分离连接的查询时,最后登录时间将是第 329 行,注销时间将是第 408 行。
登录 = 1 和注销 = 0

select 
    A.Operator, 
    A.Station,A.[TIME] AS "Logon", 
    B.[TIME] AS "Logoff"
from  (SELECT 
        [Operator],
        [TIME],
        [Station], 
        ROW_NUMBER() OVER (ORDER BY [TIME], [Operator], Station) AS RowNumber
       FROM 
          shiftstagenew 
       WHERE [ON-OFF] = '0' 
       AND [Operator] = 'Operator1')  A
JOIN 
      (SELECT 
        [Operator],
        [TIME],
        [Station], 
        ROW_NUMBER() OVER (ORDER BY [TIME], [Operator], Station) AS RowNumber
       FROM shiftstagenew WHERE [ON-OFF] = '1' 
       AND [Operator]  = 'Operator1') B
ON (
    A.RowNumber = B.RowNumber 
        AND 
    A.Operator = B.Operator 
        AND 
    A.Station = B.Station)

我已经更新了查询并且更接近了

   select A.Operator, A.Station,B.[TIME] AS "Logon", A.[TIME] AS "Logoff"
      from  (SELECT [TIME], [Operator], [Station], ROW_NUMBER() OVER (PARTITION 
      BY 
      [Operator], [Station] ORDER BY [Time], Station) AS RowNumber
   FROM 
      shiftstagenew WHERE [ON-OFF] = '1')  A
JOIN 
     (SELECT [Time],[Operator], [Station], ROW_NUMBER() OVER (PARTITION BY 
       [Operator], [Station] ORDER BY [Time], Station) AS RowNumber
     FROM shiftstagenew WHERE [ON-OFF] = '0') B
ON (A.Operator=B.Operator AND A.Station=B.Station AND A.RowNumber=B.RowNumber)
Query Results:
Operator    Station Logoff  Logon
Vitemeus    102 2019-07-07 08:15:19.380 2019-05-27 17:39:06.550
Vitemeus    102 2019-07-07 07:23:54.790 2019-05-27 14:50:13.687
Vitemeus    102 2019-07-07 03:45:46.890 2019-05-27 11:56:54.903
Vitemeus    102 2019-07-07 03:44:28.267 2019-05-24 23:52:49.313
Vitemeus    102 2019-07-07 03:08:16.343 2019-05-20 19:30:11.010

如您所见,上次登录后没有注销

OFF
2019-07-07 08:15:19.380 Vitemeus    102 445
2019-07-07 07:23:54.790 Vitemeus    102 444
2019-07-07 03:45:46.890 Vitemeus    102 443
2019-07-07 03:44:28.267 Vitemeus    102 442
2019-07-07 03:08:16.343 Vitemeus    102 441
2019-07-07 02:00:09.757 Vitemeus    102 440
2019-07-07 00:37:30.610 Vitemeus    102 439
2019-07-06 13:16:02.330 Vitemeus    102 438
2019-07-06 12:00:19.157 Vitemeus    102 437

ON
2019-07-07 08:02:02.500 Vitemeus    102 498
2019-07-07 06:52:34.303 Vitemeus    102 497
2019-07-07 03:44:42.427 Vitemeus    102 496
2019-07-07 03:25:28.957 Vitemeus    102 495
2019-07-07 02:52:40.210 Vitemeus    102 494
2019-07-07 01:45:00.373 Vitemeus    102 493
2019-07-07 00:32:39.800 Vitemeus    102 492

对于那些要求表结构(ON-OFF 为 0 或 1)的人:

CREATE TABLE [dbo].[ShiftStageNEW](
    [ON-OFF] [nvarchar](1) NULL,
    [Time] [datetime] NULL,
    [Station] [nvarchar](3) NULL,
    [Action] [nvarchar](4) NULL,
    [Operator] [varchar](8) NULL,
    [Data] [nvarchar](900) NULL,
    [Translation] [int] NULL,
    [LogTime] [bigint] NULL,
    [MessageId] [nvarchar](256) NULL
) ON [PRIMARY]

【问题讨论】:

  • 也许分享一下你目前拥有的和你想要的的查询结果,这里会更有帮助。
  • 在这里提问时请不要大喊大叫。全部大写的文本更难阅读和理解,并且不会更快地为您提供帮助。只是进来并大声喊出你的问题也是相当不礼貌的。谢谢。
  • 在这里查看底层表结构将非常有用。
  • Ken White - 你在哪里看到所有的大写字母?
  • @user3096487 标题以前全部大写

标签: sql tsql


【解决方案1】:

你应该看看LAG函数:

SELECT
     [Year]                         = YEAR([OrderDate])
    ,[Sales Amount]                 = SUM([SalesAmount])
    ,[Sales Amount Previous Year]   = LAG(SUM([SalesAmount])) OVER (ORDER BY YEAR([OrderDate]))
FROM [dbo].[FactResellerSales]
GROUP BY YEAR([OrderDate])
ORDER BY [Year];

来源:https://www.mssqltips.com/sqlservertutorial/9127/sql-server-window-functions-lead-and-lag/

还可以在此处查看符合您要求的我的问题:Find next record where status field is different from current

【讨论】:

    【解决方案2】:

    公用表表达式应​​该可以帮助您实现您想要实现的目标。
    但是行号的顺序似乎有点可疑。
    在排序中添加了分区。如果你需要的话,你可以坚持你原来的。

    WITH LOGON AS (
        SELECT
            [Operator],
            [TIME],
            [Station], 
            ROW_NUMBER() OVER (PARTITION BY [Operator], Station ORDER BY [TIME]) AS RowNumber
        FROM 
            shiftstagenew
        WHERE 
            [ON-OFF] = '0' 
        AND [Operator] = 'Operator1'
    ),
    LOGOFF AS (
        SELECT
            [Operator],
            [TIME],
            [Station], 
            ROW_NUMBER() OVER (PARTITION BY [Operator], Station ORDER BY [TIME]) AS RowNumber
        FROM 
            shiftstagenew
        WHERE 
            [ON-OFF] = '1' 
        AND [Operator] = 'Operator1'
    )
    select 
        LOGON.Operator, 
        LOGON.Station,
        LOGON.[TIME] AS "Logon", 
        LOGOFF.[TIME] AS "Logoff"
    FROM LOGON LEFT JOIN LOGOFF 
    ON (
        LOGON.RowNumber = LOGOFF.RowNumber 
            AND 
        LOGON.Operator = LOGOFF.Operator 
            AND 
        LOGON.Station = LOGOFF.Station)
    

    【讨论】:

    • 谢谢,但这给了我相同的结果。行号的可疑顺序是我要解决的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    相关资源
    最近更新 更多