EAV模型
create table people_details
( id number
, name varchar2(30)
, det_number number
, det_text varchar2(30)
, prop_id number
);
create table properties
( id number
, description varchar2(30)
);
insert into properties values (1,'EYE COLOR');
insert into properties values (2,'INCOME');
insert into properties values (3,'EDUCATION');
INSERT INTO people_details VALUES (1,'JOHN',NULL,'BLUE',1);
INSERT INTO people_details VALUES (2,'JOHN',5000,NULL,2);
INSERT INTO people_details VALUES (3,'JOHN',NULL,'HIGHSCHOOL',3);
INSERT INTO people_details VALUES (4,'PHILIP',NULL,'GREEN',1);
INSERT INTO people_details VALUES (5,'PHILIP',7000,NULL,2);
INSERT INTO people_details VALUES (6,'PHILIP',NULL,'COLLEGE',3);
INSERT INTO people_details VALUES (7,'SANDY',NULL,'BROWN',1);
INSERT INTO people_details VALUES (8,'SANDY',9000,NULL,2);
INSERT INTO people_details VALUES (9,'SANDY',NULL,'COLLEGE',3);
现在选择所有蓝眼睛或收入高于平均水平的人。 这就是我所做的
WITH PEOPLE AS (
SELECT * FROM(
SELECT NAME, DESCRIPTION, NVL(DET_TEXT, TO_CHAR(DET_NUMBER)) AS DETAIL
FROM PEOPLE_DETAILS PPL
JOIN PROPERTIES PRO ON PPL.PROP_ID = PRO.ID
)
PIVOT (
MAX(DETAIL)
FOR DESCRIPTION IN ('EYE COLOR' as EYE_COLOR, 'EDUCATION' AS EDUCATION, 'INCOME' AS INCOME)
)
)
SELECT * FROM PEOPLE WHERE EYE_COLOR = 'BLUE'
UNION
SELECT * FROM PEOPLE WHERE INCOME > (SELECT AVG(INCOME) FROM PEOPLE);
有没有更好的方法呢?在这里我将收入转换为字符,avg函数可能会进行隐式转换。不确定它是否适用于程序。 你会如何解决这个问题?
答案 0 :(得分:0)
我会使用group by
和having
解决此问题:
with p as (
select pd.name,
max(case when p.description = 'EYE COLOR' then det_text end) as eye_color,
max(case when p.description = 'INCOME' then cast(det_text as number) end) as income,
max(case when p.description = 'EDUCATION' then det_text end) as education
from people_details pd join
properties p
on pd.prop_id = p.id
group by pd.name
)
select p.*
from (select p.*, avg(income) over () as avg_income
from p
) p
where income > avg_income or eye_color = 'BLUE';
此方法的一个优点是,您可以在计算时立即将income
表示为数字。