【问题标题】:Joining three tables with separate sets of identifying columns使用不同的标识列集连接三个表
【发布时间】:2013-10-09 20:28:18
【问题描述】:

我有三个表与另一个表共享一个字段,所以:

Employee_Data: EMP_ID, PHONE_EXTENSION
Outage_Data: DATE, EMP_ID
Phone_Data: DATE, PHONE_EXTENSION

我需要将代理数据与其他两个表中的数据匹配的数据组合起来。基本上,我需要将来自Outage_dataPhone_data 的数据(因为它们都按日期分组)与Employee_Data 作为“桥梁”结合起来。

我已经有了我的 SELECT 并且一切都按照它需要的方式布置;我只需要加入方面的帮助。

编辑 根据请求,这是完整的查询。为了简单起见,我尽量不这样做:

    With Epi AS
 (SELECT  EMP_ID, PHONE_EXTENSION, Name, Manager, EWFMDeptname, Location From Employee_Data)
,

Shrink AS
 (SELECT DATE, EMP_ID, START_MOMENT, STOP_MOMENT, SEG_CODE FROM Outage_Data)
,

OutIn AS
 (SELECT date, logid, login, logout From PHONE_DATA)

 SELECT
    ISNULL(Shrink.DATE,OutIn.DATE) AS RowDate,
    ISNULL(Epi.EMP_ID,RTRIM(LTRIM(Shrink.EMP_ID))) AS Badge,
    ISNULL(Epi.PHONE_EXTENSION, OutIn.logid) AS [ACD/Extension],
    Epi.Name,
    Epi.Manager,
    Epi.EWFMDeptName,
    Epi.Location,
    ISNULL(Shrink.START_MOMENT, (SELECT Shrink.START_MOMENT FROM Shrink WHERE SHRINK.SEG_CODE = 'SHIFT' AND Shrink.EMP_ID = EPI.EMP_ID AND SHRINK.DATE = OutIn.DATE)) AS ShiftStart,
    ISNULL(Shrink.STOP_MOMENT, (SELECT Shrink.STOP_MOMENT FROM Shrink WHERE SHRINK.SEG_CODE = 'SHIFT' AND Shrink.EMP_ID = EPI.EMP_ID AND SHRINK.DATE = OutIn.row_date)) AS ShiftStop,
    OutIn.login AS Login,
    OutIn.logout AS Logout,
    Shrink.SEG_CODE AS OUTSEG,
    IIF(Shrink.SEG_CODE = 'PABS' OR Shrink.SEG_CODE = 'UABS' OR Shrink.SEG_CODE = 'PPBA' OR Shrink.SEG_CODE = 'UPBA' OR Shrink.SEG_CODE = 'VACA' OR Shrink.SEG_CODE = 'JURY' OR Shrink.SEG_CODE = 'GOVT' OR Shrink.SEG_CODE = 'LOA' OR Shrink.SEG_CODE = 'BRVMNT' OR Shrink.SEG_CODE = 'FH', Shrink.START_MOMENT, NUll) AS OutStart,
    IIF(Shrink.SEG_CODE = 'PABS' OR Shrink.SEG_CODE = 'UABS' OR Shrink.SEG_CODE = 'PPBA' OR Shrink.SEG_CODE = 'UPBA' OR Shrink.SEG_CODE = 'VACA' OR Shrink.SEG_CODE = 'JURY' OR Shrink.SEG_CODE = 'GOVT' OR Shrink.SEG_CODE = 'LOA' OR Shrink.SEG_CODE = 'BRVMNT' OR Shrink.SEG_CODE = 'FH', Shrink.STOP_MOMENT, NUll) AS OutStop,
    IIF(DateADD(minute, 5, Shrink.START_MOMENT) < OutIn.Login, CONVERT(decimal(10,2), DATEDIFF(second ,Shrink.START_MOMENT,OutIn.Login)/60.0) ,0.00) AS Late,
    ISNULL(IIF(Convert(decimal(10,2), DATEDIFF(second, Shrink.STOP_MOMENT, OutIn.logout)/60.0) = NULL OR Convert(decimal(10,2), DATEDIFF(second, Shrink.STOP_MOMENT, OutIn.logout)/60.0) > 0.00, 0.00, ABS(Convert(decimal(10,2), DATEDIFF(second, Shrink.STOP_MOMENT, OutIn.logout)/60.0))), 0.00) AS [Left],
    IIF(OutIn.login IS NULL AND Shrink.SEG_CODE = 'SHIFT' ,DATEDIFF(minute,Shrink.START_MOMENT, Shrink.STOP_MOMENT), 0.00) AS NCNS
 FROM (Epi Right JOIN Shrink on Epi.EMP_ID = Shrink.EMP_ID) INNER JOIN OutIn ON (Shrink.DATE = OutIn.DATE) JOIN (
 WHERE Shrink.SEG_CODE = 'PABS' OR Shrink.SEG_CODE = 'UABS' OR Shrink.SEG_CODE = 'PPBA' OR Shrink.SEG_CODE = 'UPBA' OR Shrink.SEG_CODE = 'VACA' OR Shrink.SEG_CODE = 'JURY' OR Shrink.SEG_CODE = 'GOVT' OR Shrink.SEG_CODE = 'LOA' OR Shrink.SEG_CODE = 'BRVMNT' OR Shrink.SEG_CODE = 'FH' or Shrink.SEG_CODE = 'SHIFT'
 ORDER BY Badge;

抱歉,有点乱。再次感谢您

EDIT2

根据要求,这是我的一些数据:

收缩:

      EMP_SK    EMP_ID  EMP_LAST_NAME   EMP_FIRST_NAME  EMP_SORT_NAME   EMP_SHORT_NAME  EMP_SENIORITY   EMP_EFF_HIRE_DATE   NOM_DATE    SEG_CODE    START_MOMENT    STOP_MOMENT
-9.88181E+11    73485   BLAH    BLAH    BLAH    BLAH    20130812000 8/12/2013 0:00:00   10/6/2013 0:00:00   SHIFT   10/6/2013 12:00:00  10/6/2013 21:00:00
-9.88181E+11    73485   BLAH    BLAH    BLAH    BLAH    20130812000 8/12/2013 0:00:00   10/7/2013 0:00:00   SHIFT   10/7/2013 12:00:00  10/7/2013 21:00:00
-9.88768E+11    192329  BLAH    BLAH    BLAH    BLAH    20130715000 7/15/2013 0:00:00   10/7/2013 0:00:00   SHIFT   10/7/2013 6:00:00   10/7/2013 15:00:00
-9.88741E+11    224579  BLAH    BLAH    BLAH    BLAH    20091214000 12/14/2009 0:00:00  10/7/2013 0:00:00   SHIFT   10/7/2013 8:00:00   10/7/2013 17:00:00
-9.88741E+11    224579  BLAH    BLAH    BLAH    BLAH    20091214000 12/14/2009 0:00:00  10/8/2013 0:00:00   SHIFT   10/8/2013 8:00:00   10/8/2013 17:00:00
-9.88181E+11    73485   BLAH    BLAH    BLAH    BLAH    20130812000 8/12/2013 0:00:00   10/8/2013 0:00:00   SHIFT   10/8/2013 12:00:00  10/8/2013 21:00:00
-9.88768E+11    192329  BLAH    BLAH    BLAH    BLAH    20130715000 7/15/2013 0:00:00   10/8/2013 0:00:00   SHIFT   10/8/2013 6:00:00   10/8/2013 15:00:00

外传:

     Badge  Name    NT Login    Email   MBadge  Manager Vendor  Business Unit   Business Unit Desc  Sub-Support Name    Segment Location    Subqueue    Phone Queue Title   EWFMDeptCode    EWFMDeptName    EWFMTeamCode    EWFMTeamName    ACD/Extension   Switch Name DomsID  DomsID2 DomsID3 Tech-ID (DPS)   Tech-ID2 (DPS2) KanaUserID  NetAgentID  Part_Time   Alias   Miscellaneous   Hiredate    Cost Center Jack    Building    QueueStatus Training Class  Trainer TeamCodeName    TeamCodeAbbr
    73485   blah    blah    blah    315413  blah    blah    blah    Service Desk Delivery   blah    Tech Support    blah    blah    Client Specialty Queue  Phone Agent blah    blah    Not Assigned    Not Assigned    4341776 AC03    NULL    NULL    NULL    NULL    NULL    NULL    NULL    0   NULL    NULL    00:00.0 blah    blah    blah    Normal  Generic Class   Instructor  Not Assigned    Not Assigned
    224579  blah    blah    blah    626985  blah    blah    blah    Service Desk Delivery   blah    Tech Support    blah    blah    Client Specialty Queue  Phone Agent blah    blah    Not Assigned    Not Assigned    4341991 AC03    NULL    NULL    NULL    211212  NULL    0   0   0   NULL    NULL    00:00.0 blah    blah    blah    Normal  Generic Class   Instructor  Not Assigned    Not Assigned
    192329  blah    blah    blah    364970  blah    blah    blah    Service Desk Delivery   blah    Tech Support    blah    blah    Client Specialty Queue  Phone Agent blah    blah    Not Assigned    Not Assigned    4341937 AC03    NULL    NULL    NULL    NULL    NULL    0   0   0   NULL    NULL    00:00.0 blah    blah    blah    Normal  Generic Class   Instructor  Not Assigned    Not Assigned

输出:

row_date            logid   login                   logout
10/6/2013 0:00:00   4341776 10/6/2013 12:00:15  10/6/2013 21:00:26
10/7/2013 0:00:00   4341937 10/7/2013 6:04:48   10/7/2013 15:15:22
10/7/2013 0:00:00   4341991 10/7/2013 7:54:34   10/7/2013 17:00:39
10/7/2013 0:00:00   4341776 10/7/2013 12:00:16  10/7/2013 21:20:36
10/8/2013 0:00:00   4341937 10/8/2013 5:59:47   10/8/2013 15:01:31
10/8/2013 0:00:00   4341991 10/8/2013 7:58:46   10/8/2013 17:03:26
10/8/2013 0:00:00   4341776 10/8/2013 12:00:10  10/8/2013 14:32:20
10/8/2013 0:00:00   4341776 10/8/2013 14:32:20  10/8/2013 21:00:04

再次感谢您

最终编辑

我终于明白了。这是完整的代码:

SELECT
    a.NOM_DATE AS RowDate, 
    a.EMP_ID AS Badge,
    ISNULL(a.[Extension], a.logid) AS [Extension],
    a.Name,
    a.Manager,
    a.DeptName,
    a.Location,
    a.START_MOMENT AS ShiftStart,
    a.STOP_MOMENT AS ShiftStop,
    a.login AS Login,
    a.logout AS Logout,
    a.SEG_CODE AS OUTSEG,
    IIF(a.SEG_CODE = 'PABS' OR a.SEG_CODE = 'UABS' OR a.SEG_CODE = 'PPBA' OR a.SEG_CODE = 'UPBA' OR a.SEG_CODE = 'VACA' OR a.SEG_CODE = 'JURY' OR a.SEG_CODE = 'GOVT' OR a.SEG_CODE = 'LOA' OR a.SEG_CODE = 'BRVMNT' OR a.SEG_CODE = 'FH', a.START_MOMENT, NUll) AS OutStart,
    IIF(a.SEG_CODE = 'PABS' OR a.SEG_CODE = 'UABS' OR a.SEG_CODE = 'PPBA' OR a.SEG_CODE = 'UPBA' OR a.SEG_CODE = 'VACA' OR a.SEG_CODE = 'JURY' OR a.SEG_CODE = 'GOVT' OR a.SEG_CODE = 'LOA' OR a.SEG_CODE = 'BRVMNT' OR a.SEG_CODE = 'FH', a.STOP_MOMENT, NUll) AS OutStop,
    IIF(DateADD(minute, 5, a.START_MOMENT) < a.Login, CONVERT(decimal(10,2), DATEDIFF(second ,a.START_MOMENT,a.Login)/60.0) ,0.00) AS Late,
    ISNULL(IIF(Convert(decimal(10,2), DATEDIFF(second, a.STOP_MOMENT, a.logout)/60.0) = NULL OR Convert(decimal(10,2), DATEDIFF(second, a.STOP_MOMENT, a.logout)/60.0) > 0.00, 0.00, ABS(Convert(decimal(10,2), DATEDIFF(second, a.STOP_MOMENT, a.logout)/60.0))), 0.00) AS [Left],
    IIF(a.login IS NULL AND a.SEG_CODE = 'SHIFT' ,DATEDIFF(minute,a.START_MOMENT, a.STOP_MOMENT), 0.00) AS NCNS
 FROM (SELECT l.row_date, l.logid, l.[login], l.logout, f.NOM_DATE, f.EMP_ID, f.START_MOMENT, f.STOP_MOMENT, f.SEG_CODE,
f.Badge, f.Extension, f.Name, f.Manager, f.Deptname, f.Location FROM LogInOutActual l
right Join 
(SELECT NOM_DATE, RTRIM(LTRIM(EMP_ID)) as EMP_ID, START_MOMENT, STOP_MOMENT, SEG_CODE, Badge,
Extension, Name, Manager, Deptname, Location FROM Shrink_Raw
LEFT OUTER JOIN Epicenter ON Shrink_Raw.EMP_ID = Epicenter.Badge 
WHERE Shrink_Raw.SEG_CODE = 'PABS' OR Shrink_Raw.SEG_CODE = 'UABS' OR Shrink_Raw.SEG_CODE = 'PPBA'
OR Shrink_Raw.SEG_CODE = 'UPBA' OR Shrink_Raw.SEG_CODE = 'VACA' OR Shrink_Raw.SEG_CODE = 'JURY'
OR Shrink_Raw.SEG_CODE = 'GOVT' OR Shrink_Raw.SEG_CODE = 'LOA' OR Shrink_Raw.SEG_CODE = 'BRVMNT'
OR Shrink_Raw.SEG_CODE = 'FH' or Shrink_Raw.SEG_CODE = 'SHIFT') as f
on l.row_date = f.NOM_DATE AND l.logid = f.[ACD/Extension]) as a
WHERE Extension IS NOT NULL AND Name IS NOT NULL AND Manager IS NOT NULL and DeptName IS NOT NULL  AND Location IS NOT NULL
 ORDER BY RowDate, Badge;

睡在上面之后,我意识到该怎么做。我在一个子查询中加入了一个,然后在另一个子查询中加入了另一个。太简单了,我觉得发布它很愚蠢。感谢所有帮助思考过程的人!

【问题讨论】:

  • Outage_data.EMP_IP 是否正确,或者应该是 Outage_Data.EMP_ID 才能加入 Employee_data?
  • 共享您编写的 select 语句,这样我们就不必猜测(或为您重写 select)。加入三个表与加入一个表或 50 个表没有什么不同...您在 from 语句中加入每个表并指定连接所在的列。 employee_date 加入到 emp_id 上的 outage_date,employee_data 加入到 phone_extention 上的 phone_data。如果您需要进一步的帮助,请尝试并发布您的完整选择声明
  • @BillHall - 我刚刚纠正了这一点。很抱歉造成混乱。

标签: sql join


【解决方案1】:

假设您的意思是 Shrink 上的 RIGHT JOIN,您的查询看起来大部分都很好,这样您就不会错过任何没有匹配 Employee_Data 行的行。我删除了 FROM 子句末尾的一个无关的 JOIN (

    With Epi AS
 (SELECT  EMP_ID, PHONE_EXTENSION, Name, Manager, EWFMDeptname, Location From Employee_Data)
,

Shrink AS
 (SELECT DATE, EMP_ID, START_MOMENT, STOP_MOMENT, SEG_CODE FROM Outage_Data)
,

OutIn AS
 (SELECT date, logid, login, logout From PHONE_DATA)

 SELECT
    -- These fields are always the same because of the inner join, 
    -- no need to check for nulls 
    -- ISNULL(Shrink.DATE,OutIn.DATE) AS RowDate,
    Shrink.DATE AS RowDate, 
    -- These fields are always the same because of the right join 
    -- unless there is no matching Epi row, then Epi.EMP_ID will 
    -- be null. You can just use Shrink.EMP_ID. If this field
    -- really needs to be trimmed, then we should be trimming
    -- this field in the RIGHT JOIN clause as well. 
    -- ISNULL(Epi.EMP_ID,RTRIM(LTRIM(Shrink.EMP_ID))) AS Badge,
    Shrink.EMP_ID AS Badge,
    ISNULL(Epi.PHONE_EXTENSION, OutIn.logid) AS [ACD/Extension],
    Epi.Name,
    Epi.Manager,
    Epi.EWFMDeptName,
    Epi.Location,
    -- I've added an alias to Shrink in the subqueries 
    -- to help clarify what is getting filtered.
    -- I also changed the where clause in the subquery 
    -- a bit so give this a try.
    -- If these are the problem fields, try not doing the 
    -- subqueries so you can get the actual data in the rows, 
    -- and mess around with just the subquery using values 
    -- from the original rows until you get the right START_MOMENT/STOP_MOMENT 
    ISNULL(Shrink.START_MOMENT, (SELECT Shrink.START_MOMENT FROM Shrink s WHERE s.SEG_CODE = 'SHIFT' AND s.EMP_ID = Shrink.EMP_ID AND s.DATE = Shrink.DATE)) AS ShiftStart,
    ISNULL(Shrink.STOP_MOMENT, (SELECT Shrink.STOP_MOMENT FROM Shrink s WHERE s.SEG_CODE = 'SHIFT' AND s.EMP_ID = Shrink.EMP_ID AND s.DATE = Shrink.DATE)) AS ShiftStop,
    OutIn.login AS Login,
    OutIn.logout AS Logout,
    Shrink.SEG_CODE AS OUTSEG,
    IIF(Shrink.SEG_CODE = 'PABS' OR Shrink.SEG_CODE = 'UABS' OR Shrink.SEG_CODE = 'PPBA' OR Shrink.SEG_CODE = 'UPBA' OR Shrink.SEG_CODE = 'VACA' OR Shrink.SEG_CODE = 'JURY' OR Shrink.SEG_CODE = 'GOVT' OR Shrink.SEG_CODE = 'LOA' OR Shrink.SEG_CODE = 'BRVMNT' OR Shrink.SEG_CODE = 'FH', Shrink.START_MOMENT, NUll) AS OutStart,
    IIF(Shrink.SEG_CODE = 'PABS' OR Shrink.SEG_CODE = 'UABS' OR Shrink.SEG_CODE = 'PPBA' OR Shrink.SEG_CODE = 'UPBA' OR Shrink.SEG_CODE = 'VACA' OR Shrink.SEG_CODE = 'JURY' OR Shrink.SEG_CODE = 'GOVT' OR Shrink.SEG_CODE = 'LOA' OR Shrink.SEG_CODE = 'BRVMNT' OR Shrink.SEG_CODE = 'FH', Shrink.STOP_MOMENT, NUll) AS OutStop,
    IIF(DateADD(minute, 5, Shrink.START_MOMENT) < OutIn.Login, CONVERT(decimal(10,2), DATEDIFF(second ,Shrink.START_MOMENT,OutIn.Login)/60.0) ,0.00) AS Late,
    ISNULL(IIF(Convert(decimal(10,2), DATEDIFF(second, Shrink.STOP_MOMENT, OutIn.logout)/60.0) = NULL OR Convert(decimal(10,2), DATEDIFF(second, Shrink.STOP_MOMENT, OutIn.logout)/60.0) > 0.00, 0.00, ABS(Convert(decimal(10,2), DATEDIFF(second, Shrink.STOP_MOMENT, OutIn.logout)/60.0))), 0.00) AS [Left],
    IIF(OutIn.login IS NULL AND Shrink.SEG_CODE = 'SHIFT' ,DATEDIFF(minute,Shrink.START_MOMENT, Shrink.STOP_MOMENT), 0.00) AS NCNS
 FROM (Epi Right JOIN Shrink on Epi.EMP_ID = Shrink.EMP_ID) INNER JOIN OutIn ON (Shrink.DATE = OutIn.DATE) 
 WHERE Shrink.SEG_CODE = 'PABS' OR Shrink.SEG_CODE = 'UABS' OR Shrink.SEG_CODE = 'PPBA' OR Shrink.SEG_CODE = 'UPBA' OR Shrink.SEG_CODE = 'VACA' OR Shrink.SEG_CODE = 'JURY' OR Shrink.SEG_CODE = 'GOVT' OR Shrink.SEG_CODE = 'LOA' OR Shrink.SEG_CODE = 'BRVMNT' OR Shrink.SEG_CODE = 'FH' or Shrink.SEG_CODE = 'SHIFT'
 ORDER BY Badge;

【讨论】:

  • 啊,那就看Phone_Data是通过DATE加入Outage_Data还是通过PHONE_EXTENSION加入Employee_Data
  • 感谢您的关注。该代码在一定程度上可以工作,但它似乎是跨天组合时间。我将添加一些原始数据,以便您了解我的意思。再次感谢。
  • 这将有助于澄清您遇到的问题...我注意到您的ShiftStart 子查询使用OutIn.DATE,但ShiftStop 的子查询使用OutIn.row_date。无论如何,我会在您发布时查看您的示例数据。
  • 是的,我实际上更改了一些列名以使其对其他人更具可读性,因此这是原始文件的保留。对于那个很抱歉。我添加了数据,给你一个更好的主意。谢谢!
  • @Dantalion88,我在回答中对您的查询进行了更多调整,并添加了一些希望对您有所帮助的内联 cmets。我仍然假设结果集中的 ShiftStart/ShiftStop 列给你带来了问题,我认为这与子查询有关。如果我的更改没有解决它,那么您应该隔离这些子查询以查找它们被触发的行。
【解决方案2】:
Select * from employee_data e
join outage_data d on e.emp_id = d.emp_id
join phone_data p on d.date = p.date

【讨论】:

  • @PM 77-1 我不这么认为? 'Select date from ...' 会有,但 select * 应该没问题?
【解决方案3】:
  SELECT *
  FROM   Employee_Data ED

         INNER JOIN  Phone_Data PD ON
         ED.PHONE_EXTENSION = PD.PHONE_EXTENSION

         INNER JOIN Outage_Data OD ON
         ED.EMP_ID = OD.EMP_ID 

【讨论】:

    【解决方案4】:

    没有看到您的 SELECT 语句是什么样子,这里有一些东西会返回完整的表数据:

    SELECT *
    FROM Employee_Data E
    JOIN Outage_Data O on E.EMP_ID = O.EMP_ID
    JOIN Phone_Data P on P.DATE = O.DATE
    ORDER By P.DATE
    

    您可以根据需要进行调整。

    【讨论】:

      猜你喜欢
      • 2011-10-15
      • 2017-03-01
      • 1970-01-01
      • 2016-08-25
      • 2018-11-07
      • 2011-04-12
      相关资源
      最近更新 更多