Объединить две таблицы и показать все записи (включая нулевые)

У меня есть две таблицы в Microsoft Access 2013:

tblService

ID PART_ID SERV_DATE SERV_REMARK
1   A0001  11/1/2013   GOOD#1
2   A0001  11/13/2013  GOOD#2
3   A0001  11/25/2013  GOOD#3
4   B0001  11/26/2013  GOOD#4
5   C0001  12/1/2013   GOOD#5
6   C0001  12/10/2013  GOOD#6
7   C0001  12/20/2013  GOOD#7

tblВывести

ID PART_ID DRAWN_DATE DRAWN_REASON DRAWN_TO
1   A0001  11/6/2013       PM        OW601
2   A0001  11/20/2013    120 PM      OW603
3   A0001  11/30/2013  REPLACEMENT   OW605 
4   C0001  12/2/2013      30 PM      OW701
5   C0001  12/15/2013    180 PM      OW702

Я хотел бы присоединиться к двум таблицам, чтобы получить результат, как показано ниже:

PART_ID SERV_DATE SERV_REMARK DRAWN_DATE DRAWN_REASON DRAWN_TO
 A0001  11/1/2013   GOOD#1    11/6/2013       PM        OW601
 A0001  11/13/2013  GOOD#2    11/20/2013    120 PM      OW603
 A0001  11/25/2013  GOOD#3    11/30/2013  REPLACEMENT   OW605
 B0001  11/26/2013  GOOD#4
 C0001  12/1/2013   GOOD#5    12/2/2013       PM        OW701
 C0001  12/10/2013  GOOD#6    12/15/2013    180 PM      OW702
 C0001  12/20/2013  GOOD#7

Я работаю неделями, но до сих пор не может получить результат. Может ли кто-нибудь показать мне запрос? Большое спасибо!

Отредактировано 18 ноября 1035 года:

Я пытался:

ВЫБЕРИТЕ s.PART_ID, s.SERV_DATE, s.SERV_REMARK,
w.DRAWN_DATE, w.DRAWN_REASON, w.DRAWN_TO
ИЗ tblService AS s
ЛЕВОЕ СОЕДИНЕНИЕ tblWithdraw AS w
ON s.PART_ID = w.PART_ID

Результат был:

PART_ID SERV_DATE   SERV_REMARK DRAWN_DATE  DRAWN_REASON    DRAWN_TO
 A0001  11/1/2013     GOOD #1   11/6/2013        PM           OW601
 A0001  11/1/2013     GOOD #1   11/20/2013     120 PM         OW602
 A0001  11/1/2013     GOOD #1   11/30/2013  REPLACEMENT       OW603
 A0001  11/13/2013    GOOD #2   11/6/2013        PM           OW601
 A0001  11/13/2013    GOOD #2   11/20/2013     120 PM         OW602
 A0001  11/13/2013    GOOD #2   11/30/2013  REPLACEMENT       OW603
 A0001  11/25/2013    GOOD #3   11/6/2013        PM           OW601
 A0001  11/25/2013    GOOD #3   11/20/2013     120 PM         OW602
 A0001  11/25/2013    GOOD #3   11/30/2013  REPLACEMENT       OW603
 B0001  11/26/2013    GOOD #4           
 C0001  12/1/2013     GOOD #5   12/2/2013        PM           OW701
 C0001  12/1/2013     GOOD #5   12/15/2013     180 PM         OW702
 C0001  12/10/2013    GOOD #6   12/2/2013        PM           OW701
 C0001  12/10/2013    GOOD #6   12/15/2013     180 PM         OW702
 C0001  12/20/2013    GOOD #7   12/2/2013        PM           OW701
 C0001  12/20/2013    GOOD #7   12/15/2013     180 PM         OW702

person user2652375    schedule 18.11.2013    source источник
comment
Какое условие присоединения?   -  person Preet Sangha    schedule 18.11.2013


Ответы (3)


Я изначально думал, что следующее будет работать для вас:

SELECT s.PART_ID, s.SERV_DATE, s.SERV_REMARK, 
  w.DRAWN_DATE, w.DRAWN_REASON, w.DRAWN_TO
FROM tblService AS s
  LEFT JOIN tblWithdraw AS w
  ON s.PART_ID = w.PART_ID

Однако это не сработает, поскольку идентификатор детали не уникален в таблице tblService. Затем я начал искать поле даты, которое совпадало в двух таблицах. Поля даты не совпадают.

Итак, исходя из того, что вы здесь показываете, у вас нет возможности связать две таблицы вместе.

Ваш вывод выглядит так, как будто вы хотите выполнить итерацию по таблице tblService, а затем найти соответствующую запись в таблице tblWithdraw и сопоставить их вместе. Затем, если есть вторая запись с тем же PART_ID в таблице tblService, сопоставьте ее со вторым вхождением того же PART_ID в таблице tblWithdraw. Затем повторите это столько раз, сколько потребуется. Если в tblWithdraw нет совпадающей записи, которая соответствует nму вхождению в tblService, то в любом случае выведите информацию, найденную в tblService.

Вы не можете выполнить такой запутанный запрос в SQL. Если вы действительно хотите это сделать, вы можете использовать такой код, как VBA, C# и/или т. д., для перебора tblService и затем повторите tblWithdraw, чтобы найти то, что вы ищете.

Лучшая альтернатива: если отображаемые таблицы содержат только те поля, которые вы показываете, вам необходимо изменить таблицы и добавить уникальное поле первичного ключа в tblService. Затем добавьте внешний ключ в таблицу tblWithdraw, соответствующий первичному ключу tblService.

Тогда будет работать следующее:

SELECT s.PART_ID, s.SERV_DATE, s.SERV_REMARK, 
  w.DRAWN_DATE, w.DRAWN_REASON, w.DRAWN_TO
FROM tblService AS s
  LEFT JOIN tblWithdraw AS w
  ON s.tblServiceID = w.tblServiceID 
person Linger    schedule 18.11.2013
comment
Привет, Лингер. Спасибо за ваш ответ. Я понимаю, что вы имеете в виду. Я попробую. Большое спасибо! - person user2652375; 18.11.2013

Используйте коррелированный подзапрос, чтобы получить следующий DRAWN_DATE для каждой комбинации PART_ID и SERV_DATE. Используя ваши образцы данных в Access 2007, это результат следующего запроса.

PART_ID SERV_DATE  SERV_REMARK next_drawn_date
A0001    11/1/2013 GOOD#1            11/6/2013
A0001   11/13/2013 GOOD#2           11/20/2013
A0001   11/25/2013 GOOD#3           11/30/2013
B0001   11/26/2013 GOOD#4 
C0001    12/1/2013 GOOD#5            12/2/2013
C0001   12/10/2013 GOOD#6           12/15/2013
C0001   12/20/2013 GOOD#7 

SELECT
    s.PART_ID,
    s.SERV_DATE,
    s.SERV_REMARK,
    (
        SELECT Min(DRAWN_DATE)
        FROM tblWithDraw
        WHERE
                PART_ID = s.PART_ID
            AND DRAWN_DATE >= s.SERV_DATE
    ) AS next_drawn_date
FROM tblService AS s;

Затем вы можете использовать это как подзапрос и присоединить его к tblWithdraw.

SELECT
    sub.PART_ID,
    sub.SERV_DATE,
    sub.SERV_REMARK,
    sub.next_drawn_date AS DRAWN_DATE,
    w.DRAWN_REASON,
    w.DRAWN_TO
FROM
    (
        SELECT
            s.PART_ID,
            s.SERV_DATE,
            s.SERV_REMARK,
            (
                SELECT Min(DRAWN_DATE)
                FROM tblWithDraw
                WHERE
                        PART_ID = s.PART_ID
                    AND DRAWN_DATE >= s.SERV_DATE
            ) AS next_drawn_date
        FROM tblService AS s
    ) AS sub
    LEFT JOIN tblWithdraw AS w
    ON
            (sub.PART_ID = w.PART_ID)
        AND (sub.next_drawn_date = w.DRAWN_DATE);
person HansUp    schedule 18.11.2013
comment
Привет, Гансуп! Спасибо за ваш ответ! Ты действительно гений! Это ответ, который я ищу. Большое спасибо! - person user2652375; 18.11.2013
comment
ГансАп, мне так жаль отбирать у тебя метку. Ваш код великолепен, но он приведет к зависанию моей системы, возможно, из-за большого объема данных. Моя система работает безупречно после тестирования решения Linger. Так что я думаю, Лингер заслуживает отметки. Простите за это! - person user2652375; 21.05.2014

SELECT s.PART_ID, s.SERV_DATE, s.SERV_REMARK, w.DRAWN_DATE, w.DRAWN_REASON, w.DRAWN_TO FROM tblService AS s LEFT JOIN tblWithdraw AS w ON s.tblServiceID = w."TWLWITHDRAW" -- небольшое исправление

person SGR8687    schedule 23.03.2014