PostgreSQL 3 Table 连接乘法
PostgreSQL 3 Table Join Multiplying
我有 3 个 table。第一个有我想要的记录。其他两个具有要应用于第一个 table 的类别。如果在描述中找到 table3 的查找值,我想 return 该类别。否则,return table2 中的类别。我认为我的逻辑是正确的,但结果正在成倍增加。如何将结果限制为我想要的 table1 条记录,但应用正确的类别?
这是我的查询示例架构。它应该只有 return table1 中的前 6 行,无论哪个类别是正确的,但它 returns 10。http://sqlfiddle.com/#!15/fc6fa/49/0
SELECT table1.product_code, table1.date_signed, table1.description,
CASE
WHEN lower(table1.description) LIKE ('%' || lower(table3.lookup_value) || '%')
THEN table3.category
ELSE table2.category
END
FROM table1
LEFT JOIN table2 ON table2.psc_code = table1.product_code
LEFT JOIN table3 ON table3.psc_code = table1.product_code
WHERE date_signed = '2017-02-01';
create table table1 (
product_code int,
date_signed timestamp,
description varchar(20)
);
insert into table1
(product_code, date_signed, description)
values
(1, '2017-02-01', 'i have a RED car'),
(2, '2017-02-01', 'i have a blue boat'),
(3, '2017-02-01', 'i have a dark cat'),
(1, '2017-02-01', 'i have a green truck'),
(2, '2017-02-01', 'i have a blue rug'),
(3, '2017-02-01', 'i have a dark dog'),
(1, '2017-02-02', 'i REd NO SHOW'),
(2, '2017-02-02', 'i blue NO SHOW'),
(3, '2017-02-02', 'i dark NO SHOW');
create table table2 (
psc_code int,
category varchar(20)
);
insert into table2
(psc_code, category)
values
(1, 'vehicle'),
(2, 'vehicle');
create table table3 (
psc_code int,
lookup_value varchar(20),
category varchar(20)
);
insert into table3
(psc_code, lookup_value, category)
values
(1, 'fox', 'animal'),
(1, 'red', 'color'),
(1, 'box', 'shipping'),
(2, 'cat', 'animal');
是的,你会得到一个笛卡尔积。
您的问题是每个 product_code 有多行与 table1 匹配。因此,当您在 table3 上加入时,您会得到 id 为 1 的 6 个记录。其他加入条件不会造成双方都有多个匹配项的情况,所以这就是您获得 6 个产品的方式代码1行,2产品代码2行,2产品代码3行。
解决方案是以外键针对目标中的唯一行的方式加入 table。
这真的应该是一个有用的例子,说明为什么规范化和密钥意识很重要。如果你打破了函数依赖的基本规则,坏问题就会成倍增加。
您正在尝试将 1 连接到多,而您只需要一个值。
SELECT table1.product_code, table1.date_signed, table1.description,
CASE
WHEN EXISTS (select 1 from table3
where table3.psc_code = table1.product_code and
lower(table1.description) LIKE ('%' || lower(table3.lookup_value) || '%'))
THEN (select table3.category from table3
where table3.psc_code = table1.product_code and
lower(table1.description) LIKE ('%' || lower(table3.lookup_value) || '%') limit 1)
ELSE (select table2.category
from table2
where table2.psc_code = table1.product_code
limit 1)
END
FROM table1
WHERE date_signed = '2017-02-01';
http://rextester.com/TQIY93378
+--------------+---------------------+----------------------+----------+
| product_code | date_signed | description | category |
+--------------+---------------------+----------------------+----------+
| 1 | 01.02.2017 00:00:00 | i have a RED car | color |
| 2 | 01.02.2017 00:00:00 | i have a blue boat | vehicle |
| 3 | 01.02.2017 00:00:00 | i have a dark cat | NULL |
| 1 | 01.02.2017 00:00:00 | i have a green truck | vehicle |
| 2 | 01.02.2017 00:00:00 | i have a blue rug | vehicle |
| 3 | 01.02.2017 00:00:00 | i have a dark dog | NULL |
+--------------+---------------------+----------------------+----------+
我有 3 个 table。第一个有我想要的记录。其他两个具有要应用于第一个 table 的类别。如果在描述中找到 table3 的查找值,我想 return 该类别。否则,return table2 中的类别。我认为我的逻辑是正确的,但结果正在成倍增加。如何将结果限制为我想要的 table1 条记录,但应用正确的类别?
这是我的查询示例架构。它应该只有 return table1 中的前 6 行,无论哪个类别是正确的,但它 returns 10。http://sqlfiddle.com/#!15/fc6fa/49/0
SELECT table1.product_code, table1.date_signed, table1.description,
CASE
WHEN lower(table1.description) LIKE ('%' || lower(table3.lookup_value) || '%')
THEN table3.category
ELSE table2.category
END
FROM table1
LEFT JOIN table2 ON table2.psc_code = table1.product_code
LEFT JOIN table3 ON table3.psc_code = table1.product_code
WHERE date_signed = '2017-02-01';
create table table1 (
product_code int,
date_signed timestamp,
description varchar(20)
);
insert into table1
(product_code, date_signed, description)
values
(1, '2017-02-01', 'i have a RED car'),
(2, '2017-02-01', 'i have a blue boat'),
(3, '2017-02-01', 'i have a dark cat'),
(1, '2017-02-01', 'i have a green truck'),
(2, '2017-02-01', 'i have a blue rug'),
(3, '2017-02-01', 'i have a dark dog'),
(1, '2017-02-02', 'i REd NO SHOW'),
(2, '2017-02-02', 'i blue NO SHOW'),
(3, '2017-02-02', 'i dark NO SHOW');
create table table2 (
psc_code int,
category varchar(20)
);
insert into table2
(psc_code, category)
values
(1, 'vehicle'),
(2, 'vehicle');
create table table3 (
psc_code int,
lookup_value varchar(20),
category varchar(20)
);
insert into table3
(psc_code, lookup_value, category)
values
(1, 'fox', 'animal'),
(1, 'red', 'color'),
(1, 'box', 'shipping'),
(2, 'cat', 'animal');
是的,你会得到一个笛卡尔积。
您的问题是每个 product_code 有多行与 table1 匹配。因此,当您在 table3 上加入时,您会得到 id 为 1 的 6 个记录。其他加入条件不会造成双方都有多个匹配项的情况,所以这就是您获得 6 个产品的方式代码1行,2产品代码2行,2产品代码3行。
解决方案是以外键针对目标中的唯一行的方式加入 table。
这真的应该是一个有用的例子,说明为什么规范化和密钥意识很重要。如果你打破了函数依赖的基本规则,坏问题就会成倍增加。
您正在尝试将 1 连接到多,而您只需要一个值。
SELECT table1.product_code, table1.date_signed, table1.description,
CASE
WHEN EXISTS (select 1 from table3
where table3.psc_code = table1.product_code and
lower(table1.description) LIKE ('%' || lower(table3.lookup_value) || '%'))
THEN (select table3.category from table3
where table3.psc_code = table1.product_code and
lower(table1.description) LIKE ('%' || lower(table3.lookup_value) || '%') limit 1)
ELSE (select table2.category
from table2
where table2.psc_code = table1.product_code
limit 1)
END
FROM table1
WHERE date_signed = '2017-02-01';
http://rextester.com/TQIY93378
+--------------+---------------------+----------------------+----------+
| product_code | date_signed | description | category |
+--------------+---------------------+----------------------+----------+
| 1 | 01.02.2017 00:00:00 | i have a RED car | color |
| 2 | 01.02.2017 00:00:00 | i have a blue boat | vehicle |
| 3 | 01.02.2017 00:00:00 | i have a dark cat | NULL |
| 1 | 01.02.2017 00:00:00 | i have a green truck | vehicle |
| 2 | 01.02.2017 00:00:00 | i have a blue rug | vehicle |
| 3 | 01.02.2017 00:00:00 | i have a dark dog | NULL |
+--------------+---------------------+----------------------+----------+