首页 > 解决方案 > SQL Server:JOIN 查询返回太多行

问题描述

我在连接查询返回重复记录时遇到问题,我希望有人能帮我弄清楚发生了什么。

我在这里查看了类似的帖子,并根据这些信息对我的查询进行了一些改进,但我并不是真正的 SQL 专家,我似乎无法获得正确的组合。

基本上我有 2 张桌子AttribAgentLV(Live)。

Attrib(真正的表Agent_Attribute)包含有关代理所属组的信息 - 代理由 column 标识Attrib.SkillTargetID,并Attrib.AttributeID标识我们感兴趣的特定组(一个代理可以属于多个组)

表 2 包含与特定代理相关的事件。代理标识符是AgentLV.SkillTargetID。特定代理的代理事件可以从代理所属的任何组发生,并且信息包括时间戳。

我试图提取的信息是:对于特定组中的代理,该代理的最新事件是什么。

如果事件与被查询的组或代理所属的另一个组相关联,则无关紧要。我只关心那个组的特工最近在做什么。

因此,对于特定组,组中的每个代理将有 1 行,对于此查询:

SELECT TOP 100 
    Attrib.SkillTargetID AS AttribSKID,
    Attrib.AttributeID,
    [AttributeValue]
FROM 
    Agent_Attribute Attrib --returns 1 STID by itself
WHERE
    Attrib.AttributeID = 5068
ORDER BY
    AttributeValue DESC

像这样:

6221    5068    5
6210    5068    5
6197    5068    5
6192    5068    5
6184    5068    5

但是对于 AgentLV 表,会有多行。

因此,即对于代理 6221,查询返回多个事件

SELECT TOP 5 
    AgentLV.SkillTargetID AS AgntLvSKID,
    AgentLV.DateTime,
    AgentLV.Event
FROM
    [prod_awdb].[dbo].[Agent_Event_Detail] AgentLV
WHERE 
    AgentLV.SkillTargetID = 6221
    AND AgentLV.[DateTime] >  GETDATE() - 1

输出:

6221    2019-06-11 07:55:49.000 1
6221    2019-06-11 07:55:53.000 3
6221    2019-06-11 11:30:00.000 3
6221    2019-06-11 11:45:00.000 3
6221    2019-06-11 11:46:20.000 3

我的目标是为组中的每个用户构建一个返回 1 行的查询 - 带有最新的时间戳。所以对于组 5068,代理 6221 应该只返回

Attrib.SkillTargetID    AgentLV.SillTargetID    Attrip.AttributeID  AttribValue AgentLV.DateTime    AgetnLV.Event
6221            6221            5068            5       2019-06-11:46       3

为此(以最简单的形式),我尝试了以下查询:

SELECT TOP 100 
    Attrib.SkillTargetID AS AttribSKID,
    AgentLV.SkillTargetID AS AgntLvSKID,
    Attrib.AttributeID,
    [AttributeValue],
    AgentLV.DateTime
FROM 
    Agent_Attribute Attrib --returns 1 STID by itself
INNER JOIN
    [prod_awdb].[dbo].[Agent_Event_Detail] AgentLV 
         ON Attrib.SkillTargetID = (SELECT TOP 1 AgentLV.SkillTargetID 
                                    FROM [prod_awdb].[dbo].[Agent_Event_Detail] AgentLV
                                    WHERE AgentLV.SkillTargetID = Attrib.SkillTargetID
                                    ORDER BY DateTime DESC)
WHERE
    Attrib.AttributeID = 5068
    AND AgentLV.DateTime > GETDATE() - 1
ORDER BY 
    AttributeValue DESC

但即使我试图AgentLV通过返回“TOP 1”来返回 1 行,但我最终会为每个代理返回很多行,如下所示:

AttribSKID  AgntLvSKID  AttributeID AttributeValue  DateTime    
6192        5461        5068            5   2019-06-11 21:01:12.007 11:59:08.050
6184        5461        5068            5   2019-06-11 21:01:12.007 11:59:08.050
6221        5461        5068            5   2019-06-11 21:01:12.007 11:59:08.050
6184        5461        5068            5   2019-06-11 21:01:12.000 11:59:08.000
6221        5461        5068            5   2019-06-11 21:01:12.000 11:59:08.000
6192        5461        5068            5   2019-06-11 21:01:12.000 11:59:08.000
6192        6758        5068            5   2019-06-11 21:01:05.007 18:52:13.077
6184        6758        5068            5   2019-06-11 21:01:05.007 18:52:13.077
6221        6758        5068            5   2019-06-11 21:01:05.007 18:52:13.077
6192        5798        5068            5   2019-06-11 21:01:02.007 11:58:21.550
6184        5798        5068            5   2019-06-11 21:01:02.007 11:58:21.550
6221        5798        5068            5   2019-06-11 21:01:02.007 11:58:21.550
6192        6419        5068            5   2019-06-11 21:01:01.007 10:02:28.563
6184        6419        5068            5   2019-06-11 21:01:01.007 10:02:28.563
6221        6419        5068            5   2019-06-11 21:01:01.007 10:02:28.563

我也尝试将第一行更改为

SELECT Distinct TOP 100 

谁能告诉我我做错了什么?

松鼠,这是我试过的修改版本,你的查询:

SELECT *
FROM   (

       SELECT rn = row_number() over (partition by Attrib.SkillTargetID

                                          order by AgentLV.DateTime desc),
   Attrib.SkillTargetID --AS AttribSKID
   ,AgentLV.SkillTargetID AS AgntLvSKID
  ,Attrib.AttributeID
  --,Attrib.Description
  ,[AttributeValue]
  ,AgentLV.Duration
  ,AgentLV.DateTime
  --,AgentLV.LoginDateTime
       FROM   Agent_Attribute Attrib

       INNER JOIN [prod_awdb].[dbo].[Agent_Event_Detail] AgentLV
       ON     Attrib.SkillTargetID = AgentLV.SkillTargetID 
   ) AS D
WHERE  D.rn = 1
  AND D.AttributeID>5067 AND D.AttributeID<5071
  AND D.[DateTime] >  GetDate()-1 --specify fraction of day
  order by D.AttributeID

我希望得到如下所示的返回数据:

AttribSKID  AgntLvSKID  AttributeID AttributeValue  DateTime
6197        6197        5068        5       2019-6-12 8:40
6183        6183        5068        5       2019-6-12 8:40
6221        6221        5068        5       2019-6-12 8:39
6192        6192        5068        5       2019-6-12 8:39
6184        6184        5068        5       2019-6-12 8:40
6210        6210        5068        5       2019-6-12 8:40

实际上最终它会看起来像这样 - 但稍后会出现:

AttribSKID  AgntLvSKID  AgentDTStgsID   DTsettings  Attrib      AttributeID AttributeValue  AgentNm     DN      Duration    DateTime    LoginDateTime
6197        6417        5012        US.Dtsettings   US.Attrib.Name  5068        5       US.NameHere 15551112222 185     2019-6-12 8:40  2019-6-12 8:15

即使是两个表的小测试数据提取也会非常大 - 有没有办法在这里附加文件?我找不到它。对于第二个表 Id 需要显示大约 500 行才能有用。

标签: sql-serverjoin

解决方案


您可以使用或row_number()窗口函数生成一个序列 no perSkillTargetID

SELECT *
FROM   (
           SELECT rn = row_number() over (partition by Attrib.SkillTargetID
                                              order by AgentLV.DateTime desc),
                  {other columns that you required}
           FROM   Agent_Attribute Attrib
           INNER JOIN [prod_awdb].[dbo].[Agent_Event_Detail] AgentLV
           ON     Attrib.SkillTargetID = AgentLV.SkillTargetID 
       ) AS D
WHERE  D.rn = 1

推荐阅读