首页 > 解决方案 > MSSQL - 需要将多条记录查询到一条记录/一组结果中 - 基于 Id 和 Date

问题描述

**更新标题..

首先也是最重要的:我知道这听起来像是一个重复的问题,但我从昨天下午开始就在网上搜索解决方案。

我有 2 张桌子,这是我的测试资料:

create table #UserMaster
(
    UserId int identity(1,1),
    FirstName varchar(50),
    LastName varchar(50),
    Department smallint,
    JobCode varchar(8),
);

create table #UserUpdateInfoMain
(
    Id int identity(1,1),
    UserId int,
    DateRequested smalldatetime,
    SubmittedBy varchar(20),
    RequestedBy varchar(20),
    NameChange varchar(50),
    TransferDept smallint,
    TransferJob varchar(8),
    TerminationDate date
);

我们的人力资源部门将提交更改员工姓名的请求、调动请求(针对工作或部门)以及终止请求。此表 (UserUpdatedInfoMain) 背后的想法是容纳所有此类请求,并将它们与主要用户信息(在 UserMaster 中)适当地链接起来。因此,当我们在数据库中搜索用户时,我们的想法是能够看到他们当前的姓氏、当前的部门/工作分配,或者如果他们已经被终止 - 也能够看到所有的线索这样的变化是一个加号。

Bob 将收到一个更改姓名的请求。一周后 Bob 可能会更换职位,因此会收到部门调动请求。我正在尝试进行查询以查看:Bob -> NewName -> NewDept(一条记录,而不是多个记录)

它的诀窍是可能有多个名称更改和转移,因此我需要获取每个名称中的最新名称以显示在查询中。我发现了一些有点相似的东西,我似乎无法开始工作(包括使用 min/max - 如果它只是寻找一个结果,效果很好),我设法得到了一次结果另一行出现在某一点,只是无法丢弃所有不必要的结果。

这是我正在使用的示例数据:

插入#UserMaster(名字,姓氏,部门,工作代码)
值('约翰','史密斯',1212,'A1234'),--1
('詹姆斯','托德',1232,'B2345'),--2
('斯蒂芬','威廉姆斯',1212,'A1234'),--3
('凯西','贝茨',1212,'C2342'),--4
('Rob','Johnson',3434,'A1234'),--5
('Cindy','Lou',2314,'A1234'),
('杰西','日期',2323,'D3422'),
('苹果','苹果酒',1342,'B2312'),
('百事可乐','可乐',1432,'A1234'),
('随机','鲍勃',1342,'C3421'),
('绿巨人','霍根',3422,'C3221'),
('约翰','Cena',3432,'B2231'),
('萨沙','班克斯',2321,'B2312'),
('Jimmy','Iovine',3432,'A1234'),
('Dwayne','约翰逊',1325,'C2342'),
('悉尼','皮尔斯',1241,'A1234'),
('Expo','Marks',4321,'B2312'),
('Pat','Swizzle',2521,'C2342'),
('猴子','骨头',1212,'D3422'),
('快乐','吉尔摩',4545,'D3422');

插入#UserUpdateInfoMain(UserId、DateRequested、SubmittedBy、RequestedBy、NameChange、TransferDept、TransferJob、TerminationDate)
值 (1, cast(getdate()-5 as smalldatetime), 'rob', 'bob', 'Waters1', NULL, NULL, NULL),
(2, cast(getdate()-4 as smalldatetime), 'rob', 'bob', NULL, 7878, 'J7098', NULL),
(3, cast(getdate()-3 as smalldatetime), 'rob', 'bob', 'Cider1', NULL, NULL, NULL),
(4, cast(getdate()-4 as smalldatetime), 'rob', 'bob', NULL, NULL, NULL, cast(getdate()-3 as date)),
(5, cast(getdate()-2 as smalldatetime), 'rob', 'bob', NULL, 9898, NULL, NULL),
(1, cast(getdate()-3 as smalldatetime), 'jim', 'bob', 'Lakely2', NULL, NULL, NULL),
(1, cast(getdate() as smalldatetime), 'sue', 'bob', 'Salsa3', NULL, NULL, NULL),
(1, cast(getdate() as smalldatetime), 'sue', 'bob', NULL, 9648, 'K9487', NULL),
(2, cast(getdate()-1 as smalldatetime),'rosco', 'bob', 'Mordor1', NULL, NULL, NULL),
(2, cast(getdate() as smalldatetime), 'rosco', 'bob', 'Elves2', NULL, NULL, NULL);

最终应该出现的两个示例如下所示......当然,其他 3 个也应该出现

(#UserUpdateInfoMain)

UserId    NameChange   TransferDept    TransferJob   TerminationDate
  1         Salsa3       9648           K9487         NULL 
  2         Elves2       9343           H8898         NULL

为冗长的帖子道歉,我只是想确保我能体面地解释事情,并有一个我正在玩的工作示例。我也很抱歉没有为我查看和完成的所有内容提供链接/示例。

我尝试在每列上进行最大日期的 CTE 并将其与 #UserUpdatedInfoMain 表连接起来,但这并没有完全奏效;我无法找到正确的组合来让它们正常工作。

例子:

theNameChanged_cte (UserId, Req_Date)
as
(
select
    i2.UserId,
    max(i2.DateRequested) as Req_Date
from #UserUpdateInfoMain i2
group by i2.UserId
)

...or...

theNameChanged_cte (UserId, Req_Date, NameChange)
as
(
select
    i2.UserId,
    max(i2.DateRequested) as Req_Date,
    i2.NameChange
from #UserUpdateInfoMain i2
group by i2.UserId, i2.NameChange
having i2.NameChange is not null
)

第一个合法的 CTE 只是查找给定 UserId 的最近日期 - 好的,很酷......这已经是中途了。第二个请求所有的 NameChange 请求,所以一些 UserId 出现了两次。如果我可以将 MAX 与 where 语句一起使用,我想我可以得到它。我想我的大脑在这一点上很不幸。

任何和所有的帮助、建议和建议 - 甚至是“查看这种类型的功能”都将不胜感激(实际的解决方案会更好!但我并没有接受建议并与他们合作)。我希望我在这篇文章中获得了所有必要的信息以获得帮助。

标签: sql-servertsql

解决方案


这里有一个 SQL hack 给你:

DECLARE
    @UserId INT, @NameChange VARCHAR(50), @TransferDept smallint, @TransferJob VARCHAR(8), @TerminationDate DATE

SET @UserId = 1;
SELECT
    @NameChange = CASE WHEN @NameChange IS NULL THEN NameChange ELSE @NameChange END,
    @TransferDept = CASE WHEN @TransferDept IS NULL THEN TransferDept ELSE @TransferDept END, 
    @TransferJob = CASE WHEN @TransferJob IS NULL THEN TransferJob ELSE @TransferJob END,
    @TerminationDate = CASE WHEN @TerminationDate IS NULL THEN TerminationDate ELSE @TerminationDate END
FROM #UserUpdateInfoMain ui
WHERE
    ui.UserId = @UserId
ORDER BY
    ui.Id DESC;

SELECT
    @UserId AS UserId,
    @NameChange AS NameChange,
    @TransferDept AS TransferDept,
    @TransferJob AS TransferJob,
    @TerminationDate AS TerminationDate;

退货

+--------+------------+--------------+-------------+-----------------+
| UserId | NameChange | TransferDept | TransferJob | TerminationDate |
+--------+------------+--------------+-------------+-----------------+
|      1 | Salsa3     |         9648 | K9487       | NULL            |
+--------+------------+--------------+-------------+-----------------+

推荐阅读