SQL视图中需要的其他行

时间:2016-03-09 13:13:41

标签: mysql postgresql join view

我有以下SQL表,并且需要兼容MySQL和Postgresql的解决方案

create table price_level (
 id serial primary key,
 name varchar(200)
);

create table product (
 id serial primary key,
 name varchar(200),
 base numeric not null,
 vat int not null
);

create table product_price (
 id serial primary key,
 base numeric,
 vat numeric,
 product_id int not null references product(id) on update cascade on delete cascade,
 price_level_id int not null references price_level(id) on update cascade on delete cascade,
 unique(product_id,price_level_id)
);

对于上面的SQL结构,我创建了一个视图:

create view view_product as
select
    p.id as product_id,
    coalesce(pp.base, p.base) as base,
    coalesce(pp.vat, p.vat) as vat,
    pp.price_level_id

from
    product as p
left join
    product_price as pp on pp.product_id=p.id
;

这些是样本数据:

price_level

id  name
1   A
2   B
3   C
4   D
5   E

产品

id  name    base    vat
1   Test    100     20

product_price

id   base   vat  product_id price_level_id
1    NULL   NULL 1          1
2    200    NULL 1          2
3    NULL   10   1          3

视图 view_product 的输出为:

product_id   base    vat  price_level_id
1            100    20    1
1            200    20    2
1            100    10    3

...问题是:如何获得这样的输出?

product_id   base   vat    price_level_id
1            100    20    1
1            200    20    2
1            100    10    3
1            100    20    4
1            100    20    5

正如您在上面的示例中所看到的,我需要将 D E price_level作为附加行。如何创建此类视图/加入?它应该具有良好的性能,因为表格可以通过额外的价格水平变大。

感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

我会使用unionprice_level表中添加那些在product_price表中没有相应记录的特定产品的记录:

select
    p.id as product_id,
    coalesce(pp.base, p.base) as base,
    coalesce(pp.vat, p.vat) as vat,
    pp.price_level_id

from
    product as p
left join
    product_price as pp on pp.product_id=p.id
union distinct
select
    p.id as product_id,
    p.base,
    p.vat,
    pl.price_level_id
from
    price_level pl
join
    product as p
where (p.id, pl.id) not in (select product_id, price_level_id from product_price)

答案 1 :(得分:0)

我会使用以下方法,交叉连接表price_level和product。然后只查找product_price表中是否存在覆盖。

SELECT
  product.id as product_id,
  IFNULL(product_price.base, product.base) as `base`,
  IFNULL(product_price.vat, product.vat) as `vat`,
  price_level.id as price_level_id
FROM price_level
CROSS JOIN product
LEFT JOIN product_price ON 
  product_price.price_level_id = price_level.id AND
  product_price.product_id = product.id
WHERE product.id = 1
ORDER BY product.id, price_level.id

请记住在WHERE条件

中使用product.id而不是product_id

答案 2 :(得分:-1)

尝试:

create view view_product as
select
p.id as product_id,
coalesce(pp.base, p.base) as base,
coalesce(pp.vat, p.vat) as vat,
coalesce(pp.price_level_id,pl.id) --modified row
from
product as p
left join
product_price as pp on pp.product_id=p.id
LEFT JOIN price_level pl on pp.price_level_id=pl.id -- modified row
;

(未经测试,但肯定你必须从正确的表中捕捉价格水平)