【问题标题】:SQL query to join two tables and get latest data based on ApprovedByLevelSQL 查询连接两个表并根据 ApprovedByLevel 获取最新数据
【发布时间】:2020-01-03 19:42:40
【问题描述】:

数据表

.

CREATE TABLE [dbo].[Data](
    [RecordNumber] [int] NULL,
    [Data1] [nvarchar](10) NULL,
    [Data2] [nvarchar](10) NULL
) ON [PRIMARY]

审批表

CREATE TABLE [dbo].[Approval](
    [RecordNumber] [int] NOT NULL,
    [ApprovedByLevel] [int] NOT NULL,
    [ApprovedByName] [nvarchar](50) NOT NULL
) ON [PRIMARY]



在批准表中,我存储了记录号和批准记录的人。
许多人批准了同一条记录,最后我想通过结合数据表只显示最后批准人级别和姓名。

期待查询结果

使用 Ms-SQL Server 2014

更新

在这

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=d1c10b03c62b282d096a1f7d7dbfca4b

我想得到结果为

【问题讨论】:

  • 您能解释一下为什么您希望这 2 行出现在预期结果中吗?
  • 在审批表中存储了记录号和审批人。许多人批准了同一条记录,最后我想通过结合数据表只显示最后批准人级别和姓名。
  • Last 是否与最大 ApprovedByLevel 相同?
  • 试试这个select * from approval as da inner join data as dd on da.record_number = dd.record_number order by da.approved_by_level DESC 或作为你的脚本SELECT * FOM [dbo].[approval] as da inner join [dbo].[data] as dd on da.[RecordNumber] = dd.[RecordNumber] order by da.[ApprovedBylevel] DESC
  • 它让所有记录重复到 5 行。由于批准表有 5 个条目。但我只想得到 2 行结果。由于数据表仅包含 2 行数据。

标签: sql sql-server


【解决方案1】:

您可以使用row_number()窗口函数在结果中获取您想要的[ApprovedByLevel]

select d.*, 
  COALESCE(a.[ApprovedByLevel], 0) AS [ApprovedByLevel], 
  a.[ApprovedByName]
from [Data] d left join (
  select *, 
    row_number() over (partition by [RecordNumber] order by [ApprovedByLevel] desc) rn
  from [Approval]
) a
on a.[RecordNumber] = d.[RecordNumber] and a.rn = 1

请参阅demo
结果:

> RecordNumber | Data1 | Data2 | ApprovedByLevel | ApprovedByName
> -----------: | :---- | :---- | --------------: | :-------------
>         1001 | A     | AA    |               3 | Mr.C          
>         1002 | B     | BB    |               5 | Mr.DD
>         1003 | C     | CC    |               0 | 

【讨论】:

  • 只有 1 件事.. 是否可以将 ApprovedByLevel null 替换为 0?如果可能的话
  • @Sixthsense 这个答案更好,因为它解决了唯一 ID 的问题:-)
【解决方案2】:

我不知道这是否有帮助,但您可以在子选择中使用 Join with Top 1:

SELECT   *
FROM     dbo.data D
JOIN     dbo.Approval A
ON       A.ApprovedByLevel =
         (
         SELECT  TOP 1 ApprovedByLevel 
         FROM    Approval 
         WHERE   RecordNumber = D.RecordNumber
         order by ApprovedByLevel desc
         )

注意:当有更多相同的记录时,您会遇到问题 批准级别的值。您需要一个唯一的表格 ID dbo.批准。这应该在连接条件中使用。

如果您在 dbo.data 中有 RecordNumber 但在 dbo.Approval 中没有,则可以使用 left outer join:

SELECT   *
FROM     dbo.data D
LEFT OUTER JOIN dbo.Approval A
ON       A.ApprovedByLevel =
         (
         SELECT  TOP 1 ApprovedByLevel 
         FROM    Approval 
         WHERE   RecordNumber = D.RecordNumber
         order by ApprovedByLevel desc
         )

如果您需要零值而不是 NULL,您可以使用 ISNULL()-Function

SELECT   D.*, ISNULL(A.ApprovedByLevel,0), A.ApprovedByName
FROM     dbo.data D
LEFT OUTER JOIN dbo.Approval A
ON       A.ApprovedByLevel =
         (
         SELECT  TOP 1 ApprovedByLevel 
         FROM    Approval 
         WHERE   RecordNumber = D.RecordNumber
         order by ApprovedByLevel desc
         )

【讨论】:

  • 这很好用。但问题是,如果数据中有 1003 记录号,并且批准表中没有 1003 的记录。那么我需要结果也显示 1003 记录,但 ApprovedByLevel 应该为空或零。有可能吗?
  • 你可以使用left outer join。我将其添加到我的答案中。
  • 还有 1 件事.. 是否可以将 ApprovedByLevel null 替换为 0?如果可能的话
  • 如果列的值为NULLISNULL(A.ApprovedByLevel,0) 会给你一个零 - 添加到答案
【解决方案3】:

我建议您添加一个日期列 ApprovingDate 以避免在 ApprovedLevel 中有更多具有相同值的记录时出现问题:

SQL Fiddle

MS SQL Server 2017 架构设置

CREATE TABLE [dbo].[Data](
    [RecordNumber] [int] NULL,
    [Data1] [nvarchar](10) NULL,
    [Data2] [nvarchar](10) NULL
)
INSERT INTO dbo.[Data]([RecordNumber],[Data1],[Data2])
VALUES(1001,'A','AA'),(1002,'B','BB')
CREATE TABLE [dbo].[Approval](
    [RecordNumber] [int] NOT NULL,
    [ApprovedByLevel] [int] NOT NULL,
    [ApprovedByName] [nvarchar](50) NOT NULL
) 
INSERT INTO [dbo].[Approval] VALUES(1001,1,'Mr.A'),(1001,2,'Mr.B'),
                            (1002,2,'Mr.AA'),(1001,3,'Mr.C'),
                            (1002,5,'Mr.DD')

查询 1

select TOP 2 * from Approval as da 
inner join [data] as dd on da.recordnumber = dd.recordnumber 
order by da.approvedbylevel DESC

查询 2

SELECT   *
FROM     dbo.data dt
JOIN     dbo.Approval a
ON       a.ApprovedByLevel =
         (
         SELECT  TOP 1 ApprovedByLevel 
         FROM    Approval 
         WHERE   RecordNumber = dt.RecordNumber
         order by ApprovedByLevel desc
         )

Results

| RecordNumber | Data1 | Data2 | RecordNumber | ApprovedByLevel | ApprovedByName |
|--------------|-------|-------|--------------|-----------------|----------------|
|         1001 |     A |    AA |         1001 |               3 |           Mr.C |
|         1002 |     B |    BB |         1002 |               5 |          Mr.DD |

【讨论】:

  • 查询 2,这很好用。但问题是,如果数据中有 1003 记录号,并且批准表中没有 1003 的记录。那么我需要结果也显示 1003 记录,但 ApprovedByLevel 应该为空或零。有可能吗?
  • @Sixthsense 只需在审批表中插入一条记录号为 1003 的记录
  • 嗯.. 是的,你是对的。但是当没有人批准该记录时,批准表中不会有任何条目。我需要查询以从数据表中获取所有记录,我只想知道记录处于哪个阶段..(即)在批准阶段。如果批准数据中没有记录,那么我希望看到 null 或 0。
猜你喜欢
  • 1970-01-01
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多