我不明白 select 的 SQL 行为

发布于 2024-12-13 05:44:46 字数 257 浏览 0 评论 0原文

给定两个表:

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。

Given two tables :

A with row : [1641, 1468] Amongst others
B with row : [1641, 1468] Amongst others

If I run this :

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

I was expecting not to get that tuple back. Although when running the command it returns that tuple.

Is there an explanation for this behavior ? Using SQLite.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

以酷 2024-12-20 05:44:46

一方面,您的加入正在生成笛卡尔积。

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]。

For one thing, your join is producing a Cartesian product.

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;

Which will result in:

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

So, when running your query, the where clause will restrict the first row and the last row. Which will leave us with:

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

And running your full query, will result in:

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

But, we can construct some rows so that we will get it regardless since you're using A.c1 and B.c2:

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

Which will result in a row with [1641, 1468].

浪推晚风 2024-12-20 05:44:46

无法复制这一点。

$ 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

Can't replicate that.

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

After comments . . .

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

Still don't get the tuple {1641, 1468}.

If you just want the rows that aren't duplicated you might try something more along these lines.

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
迎风吟唱 2024-12-20 05:44:46

如果你有

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)

If you have

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

.

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

The join will first produce

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

With distinct and just the selected columns it will be

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

I suspect you want something like

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)
ㄟ。诗瑗 2024-12-20 05:44:46

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

Out of curiosity, I ran the following test on 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;

my results were:

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

As you can see, I did not get that original tuple back which is what Kassym was expecting.

I guess sqllite is different, but I would have expected it to work the way Kassym expected as well.

-m

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文