SQL逻辑 - 两个表,表2中的多行

时间:2016-05-23 14:23:55

标签: sql

我遇到需要从两个表中检索结果的情况。表A名为'MEMBERS',表B名为'MEMBERUDFS'。我需要对表进行LEFT JOIN,因为'MEMBERS'中的所有行都不会在'MEMBERUDFS'中有一个条目。我需要从'MEMBERS'中提取符合条件的行和来自'MEMBERUDFS'的行(不是MEMBERUDFS中的所有条目都与此查询相关)。这是我需要相同帮助的地方:我当前的查询返回MEMBERS表中的所有字段以及MEMBERUDFS中的相应行,从而为每个成员返回多行。我想要做的是让MEMBERUDFS表中的字段与MEMBERS数据在同一行返回。例如,我得到:

lastname   firstname   relationship   email              entrydate   scancode   sitename   udflabel   udfvalue   expr1   expr2
doe        jane        p              janedoe@gmail.com  1/1/2016    1234       Home       Guest Pass Yes        steve   holmes
doe        jane        p              janedoe@gmail.com  1/1/2016    1234       Home       Pass Used  No         steve   holmes
doe        jane        p              janedoe@gmail.com  1/1/2016    1234       Home       Visited    yes        steve   holmes

我正在寻找的是:

doe   jane  p  janedoe@gmail.com  1/1/2016    1234   Guest Pass    Yes    steve    holmes     Pass Used     No     Visited     yes

以下是我的疑问:

SELECT MEMBERS.lname, MEMBERS.fname, MEMBERS.relationship, MEMBERS.email, MEMBERS.entrydate,
       MEMBERS.scancode, MEMBERS.siteid, SITES.sitename, 
       MEMBERUDFSETUPS.udflabel, MEMBERUDFS.udfvalue, EMPLOYEES.lname AS Expr1,
       EMPLOYEES.fname AS Expr2
FROM MEMBERS
  LEFT OUTER JOIN MEMBERUDFS ON MEMBERS.memid = MEMBERUDFS.memid
  INNER JOIN MEMBERUDFSETUPS ON MEMBERUDFS.udfid = MEMBERUDFSETUPS.udfid
  INNER JOIN SITES ON MEMBERS.siteid = SITES.siteid
  INNER JOIN EMPLOYEES ON MEMBERS.employeeid = EMPLOYEES.employeeid
WHERE (MEMBERS.relationship = 'P')
  AND (MEMBERS.siteid = @rvSite)
  AND (MEMBERUDFS.udfid = '25' OR
       MEMBERUDFS.udfid = '26' OR
       MEMBERUDFS.udfid = '27')
  AND (MEMBERS.entrydate BETWEEN @entryDateStart AND @entryDateEnd)
ORDER BY MEMBERS.entrydate DESC

2 个答案:

答案 0 :(得分:0)

您可以采取两种方法。最简单的方法是多次加入MEMBERUDFS表,对于您要检索的每个udfid一次。下面是一小段示例代码。

SELECT
    MEMBERS.lname
    ,MEMBERS.fname
    ,MEMBERS.relationship
    ,MEMBERS.email
    ,MEMBERS.entrydate
    ,MEMBERS.scancode
    ,MEMBERS.siteid
    ,SITES.sitename
    ,MUS_25.udflabel
    ,MU_25.udfvalue
    ,MUS_26.udflabel
    ,MU_26.udfvalue
    ,MUS_27.udflabel
    ,MU_27.udfvalue
    ,EMPLOYEES.lname AS Expr1
    ,EMPLOYEES.fname AS Expr2
FROM
    MEMBERS
    LEFT OUTER JOIN MEMBERUDFS MU_25
        ON MEMBERS.memid = MU_25.memid AND
            MU_25.udfid = '25'
    LEFT OUTER JOIN MEMBERUDFSETUPS MUS_25
        ON MU_25.udfid = MUS_25.udfid
    LEFT OUTER JOIN MEMBERUDFS MU_26
        ON MEMBERS.memid = MU_26.memid AND
            MU_26.udfid = '26'
    LEFT OUTER JOIN MEMBERUDFSETUPS MUS_26
        ON MU_26.udfid = MUS_26.udfid
    LEFT OUTER JOIN MEMBERUDFS MU_27
        ON MEMBERS.memid = MU_27.memid AND
            MU_27.udfid = '27'
    LEFT OUTER JOIN MEMBERUDFSETUPS MUS_27
        ON MU_27.udfid = MUS_27.udfid
    INNER JOIN SITES
        ON MEMBERS.siteid = SITES.siteid
    INNER JOIN EMPLOYEES
        ON MEMBERS.employeeid = EMPLOYEES.employeeid
WHERE
    (MEMBERS.relationship = 'P') AND
    (MEMBERS.siteid = @rvSite) AND
    (MEMBERS.entrydate BETWEEN @entryDateStart AND @entryDateEnd)
ORDER BY
    MEMBERS.entrydate DESC 

请注意,如果您的udfid一致(始终使用相同的标签),则可以使用相应的标签为每个udfvalue添加别名:

SELECT
    MEMBERS.lname
    ,MEMBERS.fname
    ,MEMBERS.relationship
    ,MEMBERS.email
    ,MEMBERS.entrydate
    ,MEMBERS.scancode
    ,MEMBERS.siteid
    ,SITES.sitename
    ,MU_25.udfvalue AS Guest_Pass
    ,MU_26.udfvalue AS Pass_Used
    ,MU_27.udfvalue AS Visited
    ,EMPLOYEES.lname AS Expr1
    ,EMPLOYEES.fname AS Expr2
FROM
    MEMBERS
    LEFT OUTER JOIN MEMBERUDFS MU_25
        ON MEMBERS.memid = MU_25.memid AND
            MU_25.udfid = '25'
    LEFT OUTER JOIN MEMBERUDFS MU_26
        ON MEMBERS.memid = MU_26.memid AND
            MU_26.udfid = '26'
    LEFT OUTER JOIN MEMBERUDFS MU_27
        ON MEMBERS.memid = MU_27.memid AND
            MU_27.udfid = '27'
    INNER JOIN SITES
        ON MEMBERS.siteid = SITES.siteid
    INNER JOIN EMPLOYEES
        ON MEMBERS.employeeid = EMPLOYEES.employeeid
WHERE
    (MEMBERS.relationship = 'P') AND
    (MEMBERS.siteid = @rvSite) AND
    (MEMBERS.entrydate BETWEEN @entryDateStart AND @entryDateEnd)
ORDER BY
    MEMBERS.entrydate DESC

答案 1 :(得分:0)

您想要做的事情通常称为 pivoting :将行转换为列。它使用case语句完成。你没有给出UDFS表的清晰描述以及你想要它如何布局,但我可以告诉你如何去做,

select lname, fname 
       , max( case udfid when 25 then 'foo' end ) as col1
       , max( case udfid when 26 then 'foo' end ) as col2
from MEMBERS left join MEMBERUDFS 
...
group by lname, fname

某些DBMS具有PIVOT运算符,可以使查询更简洁或更高效地执行。如果要搜索示例,您应该找到" fold"和"枢轴"一起讨论。