查询为行分配序列号而不分组在一起并且不更改行的顺序

Posted

技术标签:

【中文标题】查询为行分配序列号而不分组在一起并且不更改行的顺序【英文标题】:Query to assign serial number for rows without grouping together and without changing the order of rows 【发布时间】:2020-09-21 20:44:29 【问题描述】:

此表包含将集装箱运送到另一个地点的卡车行程。每次卡车运载一个集装箱时,记录都会被存储起来。如果它载有 1 个单位,那么我在 Unitcount 字段下存储“1 个单位”并将 TripCount 分配为 1。如果卡车载有 2 个单位,则 Unitcount 字段值保存为“2 个单位”,TripCount 保存为 0.5

下面是表格内容——这里Tid是主键:

我需要以下输出:

也就是说,如果驱动程序携带了 2 个单元,那么“Work Serial”值应该存储编号。他工作的旅行,并且必须为他携带 2 个单位的旅行保持恒定的价值。这个输出的目的是,我将使用这个“工作序列”列来计算他旅行的旅行成本。比如,第一次旅行他得到 20 美元,第二次旅行 20 美元,第三次旅行 25 美元,第四次旅行他得到 30 美元。我的问题是,无论我如何尝试,我的查询计算为 6 次旅行,实际上他只执行了 4 次旅行。希望我能够解释我的要求。我明白,这是一个非常简单的查询;但不幸的是我无法解决。

请注意,不应更改行的顺序。

抱歉没有解释清楚。这是我的错误,因为我只指定了一个司机姓名和一个日期。事实上,我正在计算特定周和所有司机的司机旅行费用。虽然我已经从表中复制了可能的值并粘贴到这里。

使用以下脚本创建表和插入数据(用于解决方法)

CREATE TABLE [dbo].[Test_Table](
[Tid] [bigint] NOT NULL,
[DriverName] [nvarchar](50) NULL,
[Cardgdate] [date] NULL,
[Dircid] [int] NULL,
[Load] [nvarchar](50) NULL,
[UnitCount] [nchar](10) NULL,
[Result] [int] NULL,
CONSTRAINT [PK_Test_Table] PRIMARY KEY CLUSTERED 
(
    [Tid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253293, N'Naveed Khan', '20200823 00:00:00.000', 34, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253320, N'Aas Muhammad', '20200823 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253358, N'Danish Imtiaz', '20200823 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253407, N'Naveed Khan', '20200823 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253434, N'Aas Muhammad', '20200823 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253449, N'Danish Imtiaz', '20200823 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253492, N'Naveed Khan', '20200823 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253516, N'Danish Imtiaz', '20200824 00:00:00.000', 34, N'Agent', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253520, N'Naveed Khan', '20200824 00:00:00.000', 34, N'Agent', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253525, N'Aas Muhammad', '20200824 00:00:00.000', 34, N'Agent', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253576, N'Danish Imtiaz', '20200824 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253592, N'Aas Muhammad', '20200824 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (253599, N'Naveed Khan', '20200824 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254647, N'Danish Imtiaz', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254659, N'Naveed Khan', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254664, N'Aas Muhammad', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254711, N'Danish Imtiaz', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254743, N'Chandra Shekar', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254744, N'Aas Muhammad', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254745, N'Naveed Khan', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254783, N'Danish Imtiaz', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254785, N'Chandra Shekar', '20200825 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254802, N'Naveed Khan', '20200826 00:00:00.000', 39, N'Terminal', N'2 Units   ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254803, N'Naveed Khan', '20200826 00:00:00.000', 39, N'Terminal', N'2 Units   ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254815, N'Chandra Shekar', '20200826 00:00:00.000', 34, N'Agent', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254833, N'Aas Muhammad', '20200826 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254900, N'Naveed Khan', '20200826 00:00:00.000', 39, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254904, N'Naveed Khan', '20200826 00:00:00.000', 39, N'Terminal', N'2 Units   ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254905, N'Naveed Khan', '20200826 00:00:00.000', 39, N'Terminal', N'2 Units   ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254927, N'Chandra Shekar', '20200826 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254964, N'Aas Muhammad', '20200826 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254986, N'Danish Imtiaz', '20200826 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254987, N'Naveed Khan', '20200826 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)
INSERT INTO [dbo].[Test_Table]([Tid], [DriverName], [Cardgdate], [Dircid], [Load], [UnitCount], [Result]) VALUES (254992, N'Chandra Shekar', '20200826 00:00:00.000', 30, N'Terminal', N'1 Unit    ', 0)

【问题讨论】:

您的结果似乎取决于行的顺序,但没有指定顺序的列。另外,如果tid是主键,为什么值会重复? @GordonLinoff,对不起,桌子实际上很大。我复制粘贴在 Excel 中以解释上下文。对不起..我在粘贴时忽略了......抱歉。我现在已经编辑了。 【参考方案1】:

当你用 1 个单位计算行程时,我有点困惑,但如果我理解正确的主要目标,这应该会有所帮助。

drop table if exists test_table;
create table test_table as
select 254802 as id, 0.5 as TripCount,'Abdul' as DriverName,'2units' as units union
select 254803 as id, 0.5 as TripCount, 'Abdul' as DriverName,'2units' as units  union
select 254987 as id, 1 as TripCount, 'Abdul' as DriverName,'1units' as units  union
select 254910 as id, 0.5 as TripCount,'Abdul' as DriverName,'2units' as units  union
select 254911 as id, 0.5 as TripCount,'Abdul' as DriverName,'2units' as units  union
select 254912 as id, 1 as TripCount,'Abdul' as DriverName,'1units' as units  ;

select id,TripCount,DriverName,unit_flg,
sum (TripCount) over (partition by DriverName,unit_flg order by  id rows unbounded preceding )   cumulative_trips
from (select *,case when units='2units' then 1 else 0 end as unit_flg
from test_table ) a where a.unit_flg>0 group by 1,2,3,4;

【讨论】:

我正在使用 MSSQL2012。我很欣赏你的建议。我试过你的代码;并得到 4 行,其值为 Cumaltive_trips 为 1、2、3 和 4...实际上我的要求是将“2 个单位”值的行合并为 1。我的查询表有 6 行。查询必须将其减少到 4 行(将 2 个单位的行程视为 1 次行程)。虽然我非常感谢你的努力。非常感谢你 @Shaaaan 我知道您已经得到了答案,如果您只是将 sum 更改为 unit_flag - 您将获得 4 次旅行。要删除 1units 行程 - 您可以添加 where 语句 where units<>'1units' 否则您可以保留所有内容 - 它不会更改累积行程计数。 (select b.*, sum (unit_flg) over (partition by DriverName order by id rows unbounded preceding ) as cumulative_trips from(select id,TripCount,DriverName,unit_flg from (select *,case when units='2units' then 1 else 0 end as unit_flg from test_table ) a group by 1,2,3,4) b group by 1,2,3,4;【参考方案2】:

我猜tid 确实是一个主键,代表你关心的顺序。

您可以通过查看某些列相同的行来分配您想要的值——我猜这些是驱动程序名称、cardgdate、dircid、load 和 unitcount。然后,您可以将其视为间隙和孤岛问题。检查这些值何时发生变化并进行累计:

select t.*,
       sum(case when prev_tid_grp = prev_tid then 0  -- no change in the key columns
                else 1                               -- count the change!
           end) over (order by tid) as workserial
from (select t.*,
             lag(tid) over (order by tid) as prev_tid,
             lag(tid) over (partition by rivername, cardgdate, dircid, load, unitcount order by tid) as prev_tid_grp
      from t
     ) t;

【讨论】:

非常感谢您的建议。确实,我正在使用您的代码...然后我得到了结果..感谢您的即时支持....非常感谢 @Shaaaan 。 . .我很惊讶你当时没有接受这个答案。 好吧,我在 *** 中查询已经有好几年了……当我立即得到解决方案并忙于继续我的工作时,我已经不知所措了……:)【参考方案3】:

据我了解您的问题,您希望每次单位计数更改时索引计数都会增加。

如果是这样,您可以使用lag(),然后使用窗口count()。不清楚哪一列可以用来对行进行排序,所以我假设id

select t.*,
    sum(case when unitcount = lag_unitcount then 0 else 1 end)
        over(partition by drivename order by id) worserial      
from (
    select t.*, 
        lag(unitcount) over(partition by drivename order by id) lag_unitcount
    from mytable t
) t

【讨论】:

非常感谢......哇......我不知道***可以做魔法......伙计......这正是我所需要的。我欠你很多。

以上是关于查询为行分配序列号而不分组在一起并且不更改行的顺序的主要内容,如果未能解决你的问题,请参考以下文章

大查询 |根据运行总和为行分配数字

将查询的行分组在一起

mysql分组后,取每组的前3条数据(并且有顺序)

TSQL - 将 Sales_Rep 行分组到列并将 DESCRIP 列显示为行 无聚合

为每个类别分配最小值和最大值,而不按类别分组

如何根据特定字段的值更改行的颜色?