这是一个通用的SQL问题。我有一个查询,从Products中选择所有行以及其他表中的额外信息。问题在于它的EAV方案和最后的关系以某种方式被逆转并且加入了中断。
要求是:
我有一个工作查询(下面)使用子查询来过滤值,但我需要摆脱它。我只能使用连接。
SQL Fiddle : http://sqlfiddle.com/#!15/0576b/8
create table Products (
id int primary key,
groupId int,
code varchar(100)
);
create table Groups (
id int primary key,
code varchar(100)
);
create table Values (
id int primary key,
productId int,
typeId int,
value varchar(100)
);
create table ValueTypes (
id int primary key,
name varchar(100)
);
insert into Products values (1, 1, 'P1');
insert into Products values (2, 2, 'P2');
insert into Groups values (1, 'C1');
insert into Groups values (2, 'C2');
insert into Values values (1, 1, 1, 'Aqua');
insert into Values values (2, 1, 2, '$5');
insert into ValueTypes values (1, 'Name');
insert into ValueTypes values (2, 'Price');
我的查询有效:
SELECT *
FROM Products p
INNER JOIN Groups g ON p.groupId = g.id
LEFT JOIN Values v ON v.productId = p.id AND v.typeId = (SELECT id FROM ValueTypes WHERE name = 'Price')
问题是,如何重写它以使用连接而不是子查询?
我试过了:
SELECT *
FROM Products p
INNER JOIN Groups g ON p.groupId = g.id
LEFT JOIN Values v ON v.productId = p.id
LEFT JOIN ValueTypes vt ON vt.id = v.typeId AND vt.name = 'Price'
但它会返回重复的产品P1。另一方面,INNER JOIN省略了没有' Price'值。
答案 0 :(得分:2)
明确定义JOIN顺序
SELECT *
FROM Products p
INNER JOIN Groups g ON p.groupId = g.id
LEFT JOIN ( --product price
SELECT productId, value
FROM Values v2
JOIN ValueTypes vt ON vt.id = v2.typeId AND vt.name = 'Price'
) v ON v.productId = p.id;
修改强>
另外2个JOIN版本。与上述版本相比,优化器生成不同的计划
SELECT *
FROM ValueTypes vt
INNER JOIN Products p ON vt.name = 'Price'
INNER JOIN Groups g ON p.groupId = g.id
LEFT JOIN Values v ON v.productId = p.id AND v.typeId = vt.id;
或略有不同的v3
SELECT *
FROM (SELECT id FROM ValueTypes WHERE name = 'Price') vt
CROSS JOIN Products p
INNER JOIN Groups g ON p.groupId = g.id
LEFT JOIN Values v ON v.productId = p.id AND v.typeId = vt.id
答案 1 :(得分:1)
你可以这样做:
SELECT p.id, p.code, g.id, g.code,
max(case when vt.name='Price'
then v.value
else null end) as price
FROM Products p
LEFT JOIN Groups g ON p.groupId = g.id
LEFT JOIN Values v ON v.productId = p.id
LEFT join ValueTypes vt ON v.typeId = vt.id
group by p.id, p.code, g.id, g.code