需要多个子查询,分别返回每个中的所有记录

时间:2016-12-06 16:59:39

标签: sql sql-server subquery

我需要构建一个报告,向我展示每个员工(主要查询),以及每个测试的日期和/或结果,每个测试都有一个单独的列。我希望我的查询结果如下所示:

FName LName     TB Date     TB Result    XrayDate  
--------------------------------------------------

Bob   Jones     10/1/2016   P           10/1/2016  
                9/1/2015    P           8/1/2015  
                9/15/2014   N           7/1/2014  
                8/3/2013    N   
                10/1/2012   Q   
                9/4/2011    P   
                8/16/2010   P   

下面是我现在拥有的SQL,在我的FROM语句中使用子查询来提取TB日期/结果和XRayDate,但是一旦我为XRayDate添加第二个子查询,结果就会相乘,给出21个结果而不是共有7行数据。

EMPLOYEE.FLDLNAME, 
EMPLOYEE.FLDFNAME,
EMPLOYEE.FLDREC_NUM,
TUBER.FLDDATE as "TUBER Date",
TUBER.FLDCLASS as "TUBER Result",
XRayDate.FLDDATE as "XRay Date"
FROM   EMPLOYEE EMPLOYEE 
LEFT OUTER JOIN
(SELECT TUBER.FLDDATE, TUBER.FLDCLASS, TUBER.FLDEMPLOYEE
FROM   TUBER TUBER) TUBER
ON  EMPLOYEE.FLDREC_NUM = TUBER.FLDEMPLOYEE
LEFT OUTER JOIN 
(SELECT PHYSLOG.FLDDATE, PHYSLOG.FLDTYPE,PHYSLOG.FLDEMPLOYEE
FROM   PHYSLOG PHYSLOG 
WHERE PHYSLOG.FLDTYPE = 'CXR') XrayDate
ON EMPLOYEE.FLDREC_NUM = XrayDate.FLDEMPLOYEE  `EMPLOYEE.FLDLNAME

以下是使用SQL Above:

的结果示例
Fname LName TB Date     TB Result   Xray Date
---------------------------------------

Bob   Jones 10/1/2016   P          10/1/2016  
            10/1/2016   P          8/1/2015  
            10/1/2016   P          7/1/2014  
            9/1/2015    P          10/1/2016  
            9/1/2015    P          8/1/2015  
            9/1/2015    P          7/1/2014  
            9/15/2015   N          10/1/2016  
            9/15/2015   N          8/1/2015  
            9/15/2015   N          7/1/2014  
            8/3/2013    N          10/1/2016  
            8/3/2013    N          8/1/2015  
            8/3/2013    N          7/1/2014  
            10/1/2012   Q          10/1/2016  
            10/1/2012   Q          8/1/2015  
            10/1/2012   Q          7/1/2014  
            9/4/2011    P          10/1/2016   
            9/4/2011    P          8/1/2015  
            9/4/2011    P          7/1/2014  
            8/16/2010   P          10/1/2016  
            8/16/2010   P          8/1/2015  
            8/16/2010   P          7/1/2014  

我是SQL Developer中子查询的新手,所以欢迎您提出建议/反馈。

2 个答案:

答案 0 :(得分:0)

Row_number测试和rn的完全连接。交叉/外部应用结果,如

SELECT
    EMPLOYEE.FLDLNAME, 
    EMPLOYEE.FLDFNAME,
    EMPLOYEE.FLDREC_NUM,
    TUBER_FLDDATE as "TUBER Date",
    TUBER_FLDCLASS as "TUBER Result",
    XRayDate_FLDDATE as "XRay Date"
FROM   EMPLOYEE EMPLOYEE 
CROSS APPLY
    (SELECT TUBER_FLDDATE = TUBER.FLDDATE,
            TUBER_FLDCLASS = TUBER.FLDCLASS,
            XrayDate_FLDDATE = XrayDate.FLDDATE 
      FROM (SELECT rn = row_number() over(order by TUBER.FLDDATE), TUBER.FLDDATE,    TUBER.FLDCLASS
           FROM TUBER 
           WHERE EMPLOYEE.FLDREC_NUM = TUBER.FLDEMPLOYEE) TUBER
      FULL OUTER JOIN (SELECT rn = row_number() over(order by PHYSLOG.FLDDATE), PHYSLOG.FLDDATE
           FROM  PHYSLOG  
           WHERE PHYSLOG.FLDTYPE = 'CXR' AND EMPLOYEE.FLDREC_NUM = PHYSLOG.FLDEMPLOYEE) XrayDate 
              ON XrayDate.rn=TUBER.rn
    ) tests

答案 1 :(得分:0)

您可以通过以下方式显着简化查询:

  • 不使用已有的名称别名表(如上面评论中Sean Lange所述)。例如,说明FROM EMPLOYEE EMPLOYEE没有意义,因为您已经可以引用标识为EMPLOYEE的{​​{1}}表。而是尝试使用速记标识符来使查询更快地编写并更易于阅读。
  • 除非您确实需要
  • ,否则不要在EMPLOYEE中使用子查询

例如:

JOIN

应该为您提供与您问题中的查询相同的结果。

现在,如果您在包含SELECT e.FLDLNAME, e.FLDFNAME, e.FLDREC_NUM, t.FLDDATE AS [TUBER Date], t.FLDCLASS AS [TUBER Result], x.FLDDATE AS [XRay Date] FROM EMPLOYEE e LEFT OUTER JOIN TUBER t ON e.FLDREC_NUM = t.FLDEMPLOYEE LEFT OUTER JOIN PHYSLOG x ON e.FLDREC_NUM = x.FLDEMPLOYEE WHERE x.FLDTYPE = 'CXR' 时返回的记录数量大于没有它们时返回的记录数量,则表明存在以下任一记录:

  • 每个JOIN
  • 值的TUBER表中有多条记录
  • 每个FLDEMPLOYEE
  • 值的PHYSLOG表中有多条记录
  • 或两者兼而有之!

您可以通过从这些表中返回更多详细信息来检查这一点:

FLDEMPLOYEE

我建议选择一些相关字段,而不是实际使用SELECT e.FLDLNAME, e.FLDFNAME, e.FLDREC_NUM, t.*, x.* FROM EMPLOYEE e LEFT OUTER JOIN TUBER t ON e.FLDREC_NUM = t.FLDEMPLOYEE LEFT OUTER JOIN PHYSLOG x ON e.FLDREC_NUM = x.FLDEMPLOYEE WHERE x.FLDTYPE = 'CXR' t.*,但我不知道您的表格结构,因为您没有提供它。

如果您发现某x.*个表中有JOIN个值的多个记录,则需要决定如何处理此问题,最有可能是进一步过滤FLDEMPLOYEE子句中的数据,或使用WHERE子句。

例如,如果您发现GROUP BY表中有TUBER的每个值都有多条记录,您可能会发现可以过滤到您感兴趣的记录FLDEMPLOYEE表中的其他字段:

TUBER

只要你确定无论你应用什么额外的过滤只会从SELECT e.FLDLNAME, e.FLDFNAME, e.FLDREC_NUM, t.FLDDATE AS [TUBER Date], t.FLDCLASS AS [TUBER Result], x.FLDDATE AS [XRay Date] FROM EMPLOYEE e LEFT OUTER JOIN TUBER t ON e.FLDREC_NUM = t.FLDEMPLOYEE LEFT OUTER JOIN PHYSLOG x ON e.FLDREC_NUM = x.FLDEMPLOYEE WHERE x.FLDTYPE = 'CXR' AND t.OtherField = 'SomeValue' 表中每TUBER个值返回一个记录(并且总是会),这应该可以正常工作。

或者,例如,如果您发现FLDEMPLOYEE表中有PHYSLOG的每个值都有多条记录,您可能只希望返回FLDEMPLOYEE中最近日期的记录。 1}} field:

FLDDATE