Я не понимаю это поведение SQL для выбора - PullRequest
0 голосов
/ 29 октября 2011

Имеются две таблицы:

A со строкой: [1641, 1468] Среди других B со строкой: [1641, 1468] Среди прочих

Если я запусту это:

select distinct A.c1, B.c2
from A, B
where A.c1 <> B.c1 and A.c2 <> B.c2

Я ожидал, что не верну этот кортеж.Хотя при запуске команды она возвращает этот кортеж.

Есть ли объяснение этому поведению?Использование SQLite.

Ответы [ 4 ]

2 голосов
/ 29 октября 2011

Во-первых, ваше объединение производит декартово произведение.

create table A(c1 int, c2 int);
create table B(c1 int, c2 int);
insert into A(c1, c2) values(1641, 1468), (1, 5);
insert into B(c1, c2) values(1641, 1468), (1, 5);
select * from A, B;

Что приведет к:

+------+------+------+------+
| A.c1 | A.c2 | B.c1 | B.c2 |
+------+------+------+------+
| 1641 | 1468 | 1641 | 1468 |
|    1 |    5 | 1641 | 1468 |
| 1641 | 1468 |    1 |    5 |
|    1 |    5 |    1 |    5 |
+------+------+------+------+

Таким образом, при выполнении запроса предложение where будет ограничивать первую строку и последнюю строку. Что оставит нас с:

+------+------+------+------+
| A.c1 | A.c2 | B.c1 | B.c2 |
+------+------+------+------+
|    1 |    5 | 1641 | 1468 |
| 1641 | 1468 |    1 |    5 |
+------+------+------+------+

И выполнение вашего полного запроса приведет к:

+------+------+
| c1   | c2   |
+------+------+
|    1 | 1468 |
| 1641 |    5 |
+------+------+

Но мы можем построить несколько строк, чтобы получить их независимо от того, что вы используете A.c1 и B.c2:

insert into A(c1, c2) values(1641, 5);
insert into B(c1, c2) values(1, 1468);

Что приведет к ряду с [1641, 1468].

2 голосов
/ 29 октября 2011

Не могу скопировать это.

$ sqlite3 t.db
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"

sqlite> create table a (c1 integer, c2 integer);
sqlite> create table b (c1 integer, c2 integer);
sqlite> insert into a values (1641, 1468);
sqlite> insert into b values (1641, 1468);
sqlite> select * from a;
1641|1468
sqlite> select * from b;
1641|1468
sqlite> select distinct A.c1, B.c2
   ...> from A, B
   ...> where A.c1 <> B.c1 and A.c2 <> B.c2;
sqlite>

После комментариев. , .

sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE a (
c1 integer,
c2 integer);
INSERT INTO "a" VALUES(1641,1468);
INSERT INTO "a" VALUES(1,2);
INSERT INTO "a" VALUES(3,4);
CREATE TABLE b (
c1 integer, c2 integer
);
INSERT INTO "b" VALUES(1641,1468);
INSERT INTO "b" VALUES(1,2);
INSERT INTO "b" VALUES(5,6);
COMMIT;
sqlite> select distinct A.c1, B.c2
   ...> from A, B
   ...> where A.c1 <> B.c1 and A.c2 <> B.c2;
1|6
1|1468
3|2
3|6
3|1468
1641|2
1641|6

Все еще не получите кортеж {1641, 1468}.

Если вы просто хотите, чтобы строки не дублировались, попробуйте что-то еще в этом направлении.

sqlite> select a.c1, a.c2 from a
   ...> left join b on (b.c1 = a.c1 and b.c2 = a.c2)
   ...> where b.c1 is null and b.c2 is null
   ...> union all
   ...> select b.c1, b.c2 from b
   ...> left join a on (b.c1 = a.c1 and b.c2 = a.c2)
   ...> where a.c1 is null and a.c2 is null;
3|4
1641|73
5|6
0 голосов
/ 29 октября 2011

Из любопытства я запустил следующий тест на сервере MS SQL 05:

create table a  
(  
c1 int,  
c2 int  
)  
create table b  
(  
c1 int,  
c2 int  
)   

insert into a values(1641,1468)
insert into a values(1641,1111)
insert into b values(1641,1468)
insert into b values(1112,1345)

select distinct A.c1, B.c2
   from A, B
where A.c1 <> B.c1 and A.c2 <> B.c2;

мои результаты были:

c1   |   c2
-------------
1641 |   1345

Как видите, я этого не получилоригинальный кортеж, который ожидал Касым.

Полагаю, что sqllite отличается, но я ожидал бы, что он будет работать так же, как ожидал Кассым.

-m

0 голосов
/ 29 октября 2011

Если у вас есть

A
---
C1 C1
-----
1  2
1  3

.

B
---
C1 C1
-----
1  2
1  3

Объединение сначала произведет

A.C1 A.C2 B.C1 B.C2
-------------------
1    2    1    3
1    3    1    2

С отдельными и только выделенными столбцами это будет

A.C1 B.C2
---------
1    3
1    2

Я подозреваю, что вы хотите что-то вроде

select distinct A.c1, B.c2
from A, B
WHERE NOT EXISTS (SELECT 1 FROM B WHERE A.C1 = B.C1 AND A.C2 = B.C2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...