我正在构建一个系统,我必须使用数据库数据找到计算机系统的总价。第一个屏幕截图是系统表的构建。
系统表
零件表
不同的种类有:主板,外壳,内存,CPU,图形。 我需要的是将列转换成行的一些方法,从而总结每个系统的价格。
以下是表格和内容。
CREATE TABLE Component (
nome VARCHAR(30),
kind VARCHAR(10), /*cpu, ram, mainboard, cases*/
price INT,
PRIMARY KEY(nome)
);
CREATE TABLE Computer_system (
nome VARCHAR(30),
ram VARCHAR(20),
cpu VARCHAR(20),
mainboard VARCHAR(20),
cases VARCHAR(20),
gfx VARCHAR(20),
PRIMARY KEY(nome)
);
INSERT INTO Computer_system VALUES('SERVER1','D31','XEON1','LGA2011_D3_E_OGFX','CASE_A',null);
INSERT INTO Computer_system VALUES('SERVER2','D43','XEON3','LGA2011_D4_E_OGFX','CASE_A',null);
INSERT INTO Computer_system VALUES('CONSUMER1','D43','I71','LGA1150_D4_ATX_OGFX','CASE_B',null);
INSERT INTO Computer_system VALUES('GAMING1', 'D51', 'FX','AM3+_D5_ATX','BLACK_PEARL', 'NVIDIA_TITAN_BLACK_X');
INSERT INTO Computer_system VALUES('BUDGETO', 'D31', 'XEON1','LGA2011_D3_ATX','CASE_B', null);
答案 0 :(得分:1)
在Postgres using UNNEST( ARRAY( ...) )
中有一个关于unpivot的巧妙技巧这有效地(在表的一次通过中)将表computer_system的多列展开成多行(在这种情况下)3列:“nome”,“colkind”和“colnome”。不透明数据的一个例子:
| nome | colkind | colnome |
|-----------|-----------|----------------------|
| BUDGETO | ram | D31 |
| BUDGETO | gfx | (null) |
| BUDGETO | cases | CASE_B |
| BUDGETO | mainboard | LGA2011_D3_ATX |
| BUDGETO | cpu | XEON1 |
一旦该数据以该格式提供,就可以很容易地加入到Components表中,如下所示:
SELECT
*
FROM (
/* this "unpivots" the source data */
SELECT
nome
, unnest(array[ram, cpu, mainboard,cases,gfx]) AS colnome
, unnest(array['ram', 'cpu', 'mainboard','cases','gfx']) AS colkind
FROM Computer_system
) unpiv
INNER JOIN Components c ON unpiv.colnome = c.nome AND unpiv.colkind = c.kind
;
从这里可以很容易地得出这个结果:
| nome | sum_price |
|-----------|-----------|
| BUDGETO | 291 |
| GAMING1 | 515 |
| CONSUMER1 | 292 |
| SERVER1 | 285 |
| SERVER2 | 289 |
使用:
SELECT
unpiv.nome, sum(c.price) sum_price
FROM (
/* this "unpivots" the source data */
SELECT
nome
, unnest(array[ram, cpu, mainboard,cases,gfx]) AS colnome
, unnest(array['ram', 'cpu', 'mainboard','cases','gfx']) AS colkind
FROM Computer_system
) unpiv
INNER JOIN Components c ON unpiv.colnome = c.nome AND unpiv.colkind = c.kind
GROUP BY
unpiv.nome
;
查看此SQLfiddle演示&请注意执行计划
QUERY PLAN
HashAggregate (cost=487.00..488.00 rows=100 width=82)
-> Hash Join (cost=23.50..486.50 rows=100 width=82)
Hash Cond: ((((unnest(ARRAY[computer_system.ram, computer_system.cpu, computer_system.mainboard, computer_system.cases, computer_system.gfx])))::text = (c.nome)::text) AND ((unnest('{ram,cpu,mainboard,cases,gfx}'::text[])) = (c.kind)::text))
-> Seq Scan on computer_system (cost=0.00..112.00 rows=20000 width=368)
-> Hash (cost=15.40..15.40 rows=540 width=120)
-> Seq Scan on components c (cost=0.00..15.40 rows=540 width=120)
答案 1 :(得分:0)
我认为你需要将你的表设计分解为3个表,有Component,Computer_System和Computer_component。以下是字段列表: Computer_System - > computer_id和名字 组件 - > nome_component,种类,价格 Computer_Component - > computer_id,nome_component。使用该表,您可以通过将计算机组件连接到计算机组件上来计算每个computer_id的总价格b on a.computer_id = b.Computer id JOIN组件c ON b.nome_component = c.nome_component
答案 2 :(得分:0)
您只需将Computer_system
表加入Component
for each kind
,就像下面的查询一样,您就可以做到这一点:
select c.nome as name,
(coalesce(ram.price,0)
+coalesce(cpu.price,0)
+coalesce(+mainboard.price,0)
+coalesce(cases.price,0)
+coalesce(gfx.price,0)) as price
from Computer_system c
left join Components ram on c.ram=ram.nome
left join Components cpu on c.cpu=cpu.nome
left join Components mainboard on c.mainboard=mainboard.nome
left join Components cases on c.cases=cases.nome
left join Components gfx on c.gfx=gfx.nome
答案 3 :(得分:0)
这很棘手,因为您的表格结构不适合此类查询。此外,如果您希望构建中有多个gfx
,则它不灵活。
以下是我建议的答案:
select sum(price)
from components
where nome in (
select ram from computer_system where nome = 'GAMING1'
UNION ALL
select cpu from computer_system where nome = 'GAMING1'
UNION ALL
select mainboard from computer_system where nome = 'GAMING1'
UNION ALL
select cases from computer_system where nome = 'GAMING1'
UNION ALL
select gfx from computer_system where nome = 'GAMING1'
)
;
这是一个工作小提琴:http://sqlfiddle.com/#!15/228d7/8
如果我重组了表格,我会在这个小提琴中做出类似的事情:http://sqlfiddle.com/#!15/f4ed06/1和parts_list
表:
CREATE TABLE parts_list (
system_nome VARCHAR(30),
component_kind VARCHAR(10),
component_nome VARCHAR(30),
PRIMARY KEY (system_nome, component_kind, component_nome)
);
,您对GAMING1系统成本的查询变得更加简单:
select sum(price)
from components as c
inner join parts_list as PL ON c.kind = pl.component_kind and c.nome = pl.component_nome
where pl.system_nome = 'GAMING1'
;