我不理解select的这种SQL行为

时间:2011-10-29 16:56:13

标签: sql select sqlite

给出两个表:

A with row:[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 个答案:

答案 0 :(得分:2)

无法复制。

$ 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

答案 1 :(得分:2)

首先,您的加入是生产笛卡尔积。

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.c1B.c2,我们都会得到它:

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

这将与[1641,1468]产生一行。

答案 2 :(得分:0)

如果你有

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)

答案 3 :(得分:0)

出于好奇,我在ms sql server 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

正如你所看到的,我没有得到Kassym期待的原始元组。

我猜sqllite是不同的,但我希望它能像Kassym预期的那样工作。

-m