Две обединения в mysql заявка не връщат очакван резултат

Работя върху присъединяване и изглежда не мога да получа набора от резултати, от който се нуждая. Нека нарисувам сценария:

Имам 2 маси:

Таблица с данни

+----+-------+
| ID | Name  |
+----+-------+
| 10 | Test1 |
| 11 | Test2 |
| 12 | Test3 |
| 13 | Test4 |
| 14 | Test5 |
| 15 | Test6 |
+----+-------+

Присъединете се към масата

+----+-----+-----+-----+
| ID | FID | GID | Val |
+----+-----+-----+-----+
| 10 |   3 |     | abc |
| 10 |     |   1 | def |
| 11 |   3 |     | ijk |
| 12 |     |   1 | lmn |
| 13 |   4 |     | opq |
+----+-----+-----+-----+

Очакван набор от резултати

+---------------+-----------------+---------------+----------------+----------------+
| Data table id | Data table name | Join Tabe FID | Join Table GID | Join Table Val |
+---------------+-----------------+---------------+----------------+----------------+
|            10 | Test1           |             3 |                | abc            |
|            11 | test2           |             3 |                | ijk            |
|            12 | test3           |               |              1 | lmn            |
+---------------+-----------------+---------------+----------------+----------------+

Моето запитване

Select
   *
from
   datatable A
join jointable b
on
   A.ID = B.ID
   and B.FID = 3
join jointable c
on
   A.ID = C.ID
   and C.GID = 1
   and C.FID <> null

Това, което се случва, е, че свързването на таблица C се извършва върху набора от резултати на съединението между таблица A и B, следователно наборът от резултати е празен.

Искам обединяването на таблица C да се приложи върху таблица A, а не върху набора от резултати от обединението между таблица A и B; което ще доведе до очаквания набор от резултати.

Може ли някой да помогне?

Благодаря


person Yash    schedule 15.03.2016    source източник
comment
Няма записи с id от 3, така че очаквам B.ID = 3 да филтрира всички записи.   -  person Gordon Linoff    schedule 15.03.2016
comment
Мисля, че това, от което се нуждаете, е ляво външно съединение, но не разбирам напълно въпроса ви.   -  person mh-dev    schedule 15.03.2016
comment
@GordonLinoff Съжалявам, беше правописна грешка, коригирана   -  person Yash    schedule 15.03.2016
comment
@mh-dev ляво външно съединение ще върне ID 13, който не ми е необходим   -  person Yash    schedule 15.03.2016
comment
може ли някой да обясни какво иска OP? Не го разбирам от бившия.   -  person Zahiro Mor    schedule 15.03.2016
comment
@ZahiroMor проверете отговора на Spencer7593: stackoverflow.com/a/36014355/439002 . Може би това ще помогне да разбера от какво имах нужда   -  person Yash    schedule 15.03.2016


Отговори (5)


Изразът C.FID <> null никога няма да се изчисли като true, той винаги ще връща NULL. Сравнение на неравенство с NULL винаги ще се оценява на NULL. (В SQL, в булев контекст, изразът en ще даде оценка на една от три възможни стойности: TRUE, FALSE или NULL.)

Ако искате сравнение с NULL да върне TRUE или FALSE, използвайте сравнителен тест IS [NOT] NULL. Израз като

foo IS NULL

or

foo IS NOT NULL

Или можете да използвате специфичния за MySQL null-safe оператор за сравнение (космически кораб):

foo <=> NULL

or

NOT (foo <=> NULL)

Що се отнася до резултата, който искате да върнете, малко е объркващо как да стигнете до това, което искате да върнете.

За мен изглежда, че искате да получите съвпадащите редове от jointable... ако има съвпадащи редове с fid=3, върнете само тези редове. Ако няма съвпадащи редове с fid=3, върнете редове, които имат NULL стойност в fid и gid=1.

Ако това е, което искаме да бъде върнато, можем да напишем заявка, която прави това. Ако това не е това, което искаме да бъде върнато, тогава останалата част от този отговор няма значение.

Можем да използваме предикат NOT EXISTS, за да проверим за липса на съвпадащи редове.

Например:

SELECT d.id 
     , d.name
     , j.fid
     , j.gid
     , j.val
  FROM datatable d
  JOIN jointable j
    ON j.id = d.id
 WHERE ( j.fid = 3 )
    OR ( j.fid IS NULL
         AND j.gid = 1 
         AND NOT EXISTS ( SELECT 1
                            FROM jointable t
                           WHERE t.id = d.id
                             AND t.fid = 3
                        )
       )
person spencer7593    schedule 15.03.2016

SELECT
*
FROM datatable A
LEFT JOIN jointable B ON A.ID = B.ID 
WHERE B.FID = 3 OR B.GID = 1;

Това ще ви върне:

10  Test1   10  3       abc
10  Test1   10      1   def
11  Test2   11  3       ijk
12  Test3   12      1   lmn

Сега изглежда, че искате да филтрирате:

10  Test1   10  3       abc

и запази

10  Test1   10      1   def

Това ли искаш?

за разбирането

person White Feather    schedule 15.03.2016
comment
Лявото JOIN тук е ненужно, WHERE B го превръща във INNER JOIN - person Mihai; 15.03.2016

SELECT *
FROM   table1 a
INNER JOIN table2 b ON a.ID = b.ID
WHERE b.FID = 3 OR b.GID = 1

Но въпросът ви не е много конкретен по отношение на клаузите WHERE

person L Kefalas    schedule 15.03.2016

SELECT * FROM db1 
INNER JOIN db2 ON db1.id = db2.id
WHERE db1.FID = 3 or db2.GID = 1;

Защо използвате C.FID ‹> null, когато B.GID = 1? Трябва да е нула.

person Justinas Jakavonis    schedule 15.03.2016

Честно казано, не съм сигурен дали разбирам какво искате, така че това може да не е правилно. Това, което мисля, че искаш е. Имате две таблици и искате да обедините всички редове от таблицата за присъединяване, където id съвпада и fid= 3 или gid=1 и fid не е null. Заявката за това трябва да бъде нещо подобно. (едно присъединяване трябва да е достатъчно)

Select
   *
from
   datatable A
join jointable b
on
   A.ID = B.ID
where b.fid = 3 or (b.gid = 1 and b.fid <> null)
person mh-dev    schedule 15.03.2016