2016-05-23 3 views
0

У меня возникла ситуация, когда мне нужно получить результаты из двух таблиц. Таблица A называется «ЧЛЕНЫ», а таблица B называется «MEMBERUDFS». Мне нужно LEFT JOIN на таблицах, потому что не все строки в «MEMBERS» будут иметь запись в «MEMBERUDFS». Мне нужно вывести строки из «ЧЛЕНОВ», которые соответствуют критериям, и то же самое из «MEMBERUDFS» (не все записи в MEMBERUDFS относятся к этому запросу). Здесь мне нужна такая же помощь: мой текущий запрос возвращает все поля из таблицы MEMBERS и соответствующие строки из MEMBERUDFS, что приводит к нескольким строкам для каждого члена. Я бы хотел, чтобы поля из таблицы MEMBERUDFS возвращались в той же строке, что и данные MEMBERS. Например, я получаю:SQL Logic - две таблицы, несколько строк из таблицы 2

lastname firstname relationship email    entrydate scancode sitename udflabel udfvalue expr1 expr2 
doe  jane  p    [email protected] 1/1/2016 1234  Home  Guest Pass Yes  steve holmes 
doe  jane  p    [email protected] 1/1/2016 1234  Home  Pass Used No   steve holmes 
doe  jane  p    [email protected] 1/1/2016 1234  Home  Visited yes  steve holmes 

То, что я ищу это:

doe jane p [email protected] 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 
+1

Переместите условия MEMBERUDFS.udfid из предложения WHERE в предложение 'ON', если вы хотите получить истинное поведение левого соединения. (Так как теперь вы получаете регулярный результат внутреннего соединения.) – jarlh

+1

Насколько я знаю, так работают объединения, если вы делаете это по-другому, как бы вы назвали дополнительные столбцы? и что, если каждый член имеет разное количество связанных UDF? – ArturoAP

+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 
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 

Некоторые СУБД имеют PIVOT оператор, который может сделать запрос немного менее подробный или более эффективный для выполнения. Если вы ищете примеры, вы должны найти «сгиб» и «поворот», обсужденный вместе.

Смежные вопросы