嗨,大家好我在香草系统上工作,我们可以在其中添加许多系统,包括数据集和字段。我们可以在运行时添加每个系统的字段和数据,而无需改变数据库的结构。
CREATE TABLE Type(
ID int,
Name varchar(255),
PRIMARY KEY (ID)
);
INSERT INTO Type VALUES (1, 'cust_obj_7');
INSERT INTO Type VALUES (2, 'cust_obj_8');
CREATE TABLE Object(
ID int,
Name varchar(255),
Description varchar(255),
TypeID int,
PRIMARY KEY (ID),
FOREIGN KEY (TypeID ) REFERENCES Type(ID)
);
INSERT INTO Object VALUES (1, 'First', 'First_desc', 1);
INSERT INTO Object VALUES (2, 'Second', 'Second_desc', 1);
CREATE TABLE TypeFields(
ID int,
Name varchar(255),
NameType varchar(255),
TypeID int,
PRIMARY KEY (ID),
FOREIGN KEY (TypeID ) REFERENCES Type(ID)
);
INSERT INTO TypeFields VALUES (1, 'First', 'str', 1);
INSERT INTO TypeFields VALUES (2, 'Seond', 'str', 1);
INSERT INTO TypeFields VALUES (3, 'Third', 'int', 1);
CREATE TABLE FieldsData(
ID int,
ObjectID int,
FieldID int,
FieldName varchar(255),
TypeID int,
value varchar(255),
PRIMARY KEY (ID),
FOREIGN KEY (TypeID ) REFERENCES Type(ID),
FOREIGN KEY (ObjectID ) REFERENCES Object(ID),
FOREIGN KEY (FieldID ) REFERENCES TypeFields(ID)
);
INSERT INTO VALUES (1, 1, 1, 'First', 1, "a");
INSERT INTO VALUES (2, 1, 2, 'Second', 1, "b");
INSERT INTO VALUES (3, 1, 3, 'Third', 1, "120");
INSERT INTO VALUES (4, 2, 1, 'First', 1, "c");
INSERT INTO VALUES (5, 2, 2, 'Second', 1, "d");
INSERT INTO VALUES (6, 2, 3, 'Third', 1, "130");
CREATE TABLE FinalTable(
ObjID int,
ObjName varchar(255),
ObjDesc varchar(255),
First varchar(255),
Second varchar(255),
Third int
);
Insert Into FinalTable
select *
from object, fieldsdata
where object.iD = fieldsdata.objectiD
Values(object.ID , object.Name, object.Description, ....... );
我想从这些表中创建一个数据集作为finaltable,如上所示。我可以使用密钥获取所有数据,但我有问题将这些数据写入不同行的列中的单行。我坚持认为如何在sas-base中使用sql来实现这一点。
答案 0 :(得分:1)
首先,“我的自定义表格”应该是源自“字段数据”的视图。 “字段数据”有点用词不当,因为它包含字段的值。因此,在抽象中,区分对于您正在构建的框架内的理解非常重要。
“我的自定义表格”中的一行似乎用于投影TypeID = 1。您没有显示其他TypeID值,但我认为它们将用于不同的自定义表。
自定义表应该是视图,否则每个对象对于存储要求的乘数来说可能是+1
在您的示例图像中,“我的自定义表格”的第二行具有ObjID = 2,但显示对应于ObjID = 2的“字段数据”中的值。我会假设一个错字。
“对象类型”名称不会在自定义表格中呈现,因此我认为它只是一个类型目录。
您提出的设计尚不正常。不确定为什么在“字段数据”中复制FieldName,你有FieldID引用具有名称的记录。不确定为什么TypeID出现在“字段数据”中,因为TypeID本质上是一个目录项选择器,用于“字段数据”的所需投影
这种设计可能会导致很多重新发明,并且需要花费大量时间来充实不同的值类型,例如日期,值渲染格式,多值类型等等。
无论如何,将值数据作为对象类型投影到自定义表本质上是组合对象,类型字段和字段数据的连接的转置。 SAS SQL没有PIVOT运算符(例如在MS SQL Server中找到)。在SQL中使用“旧学校”的方式涉及通过分组聚合案例陈述。 Search SO
有一些“仲裁”的设计只会杀死所有中间人,并且拥有一个巨大的价值单块,例如20个ID字段,1,000个数字字段,1,000个字符字段和100个日期字段,每个“对象”是一个用例SQL视图。
**编辑 - 以下添加**
添加了展示“老派”支点的代码:
PROC SQL;
CREATE TABLE Type(
ID int,
Name varchar(255)/*,
PRIMARY KEY (ID)*/
);
INSERT INTO Type VALUES (1, 'cust_obj_7');
INSERT INTO Type VALUES (2, 'cust_obj_8');
CREATE TABLE Object(
ID int,
Name varchar(255),
Description varchar(255),
TypeID int/*,
PRIMARY KEY (ID),
FOREIGN KEY (TypeID ) REFERENCES Type(ID);*/
);
INSERT INTO Object VALUES (1, 'First', 'First_desc', 1);
INSERT INTO Object VALUES (2, 'Second', 'Second_desc', 1);
CREATE TABLE TypeFields(
ID int,
Name varchar(255),
NameType varchar(255),
TypeID int/*,
PRIMARY KEY (ID),
FOREIGN KEY (TypeID ) REFERENCES Type(ID) */
);
INSERT INTO TypeFields VALUES (1, 'First', 'str', 1);
INSERT INTO TypeFields VALUES (2, 'Seond', 'str', 1);
INSERT INTO TypeFields VALUES (3, 'Third', 'int', 1);
CREATE TABLE FieldsData(
ID int,
ObjectID int,
FieldID int,
FieldName varchar(255),
TypeID int,
value varchar(255)/*,
PRIMARY KEY (ID),
FOREIGN KEY (TypeID ) REFERENCES Type(ID),
FOREIGN KEY (ObjectID ) REFERENCES Object(ID),
FOREIGN KEY (FieldID ) REFERENCES TypeFields(ID)*/
);
INSERT INTO FieldsData VALUES (1, 1, 1, 'First', 1, "a");
INSERT INTO FieldsData VALUES (2, 1, 2, 'Second', 1, "b");
INSERT INTO FieldsData VALUES (3, 1, 3, 'Third', 1, "120");
INSERT INTO FieldsData VALUES (4, 2, 1, 'First', 1, "c");
INSERT INTO FieldsData VALUES (5, 2, 2, 'Second', 1, "d");
INSERT INTO FieldsData VALUES (6, 2, 3, 'Third', 1, "130");
CREATE TABLE FinalTable(
ObjID int PRIMARY KEY,
ObjName varchar(255),
ObjDesc varchar(255),
First varchar(255),
Second varchar(255),
Third int
);
create view example_type1_realized as
select
FieldsData.ObjectID as ObjID
, max(Object.Name) as ObjName
, max(Object.Description) as ObjDesc
, max(case when FieldID=1 then Value end) as First
, max(case when FieldID=2 then Value end) as Second
, max(case when FieldID=3 then input(Value,best12.) end) as Third
from FieldsData
join Object
on FieldsData.ObjectID = Object.ID
where TypeID = 1
group by ObjID
;
现在,对于每个TypeID,您将需要构建一个代码生成器,该代码生成器可以创建源代码壁纸... max(来自TypeFields数据的情况......构造。
这是一种方式:
* Now a codegener macro that can produce the example realization: ;
%macro realize (TypeID=, out=);
%local wallpaper;
proc sql noprint;
select cat
(
', max(case when FieldID=', cats(ID), ' then '
, case
when NameType='str' then 'Value'
when NameType='int' then 'input(Value,12.)'
else 'cats(Value) || " (' || NameType || ') unhandled"'
end
, ' end)'
, ' as ', Name
) length=32000
into :wallpaper separated by ' '
from TypeFields
where TypeID = &TypeID
;
%put NOTE: wallpaper=%SUPERQ(wallpaper);
create &out as
select
FieldsData.ObjectID as ObjID
, max(Object.Name) as ObjName
, max(Object.Description) as ObjDesc
&wallpaper
from FieldsData
join Object
on FieldsData.ObjectID = Object.ID
group by ObjID
;
quit;
%mend;
options mprint;
%realize(TypeID=1, out=table type1_replicate)
您可以修改代码生成器,以便将行插入out =而不是重新创建。
您应该看到您的系统可行,但需要很多注意力才能变得通用。每个FieldType可能会获得格式,信息,长度,日期处理,类型,字段序列等超出范围值的错误处理...