从类似于 ESV 的元数据驱动模式查询数据
Query data from meta data driven schema similar to EAV
我们有一个类似于 EAV 的数据模型。但是,我们的属性集有限。在我们的数据模型中,我们存储了个人完成的不同活动,并且根据 activity 类型,属性会有所不同。
我们想要获取个人的活动和相应的 attribute/values。我已经描述了 Activity
、ActivityDetails
table 和预期的结果集。
能否请您指导我如何从数据模型中得出预期的结果集?我们必须做一些转变。但是,不确定是否达到相同。
在下面的示例数据中,ClickURL 是一个 Activity。它具有三个属性:URLAddress、ClickCount、ClickDate。三个属性对应的值为:www.companyurl.com,10,20140101
结果集应该如下所示:
ActivityName | Description | URLAddress | ClickCount | ClickDate
-------------------------------------------------------------------------------------------
ClickURL | Click advertisementURL | www.companyurl.com |10 |20140101
Our Data model & Expected Result
数据查询示例
CREATE TABLE [dbo].[Activity](
[ActivityTypeID] [int] IDENTITY(1,1) NOT NULL,
[ActivityName] VARCHAR(50) NULL,
[Description] VARCHAR(255) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [varchar](50) NULL,
[NumField2] [varchar](50) NULL,
[DTTMField1] [varchar](50) NULL,
[DTTMField2] [varchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ActivityDetails](
[ActivityDetailID] [int] IDENTITY(1,1) NOT NULL,
[ActivityTypeID] VARCHAR(50) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [] NULL,
[NumField2] [int] NULL,
[DTTMField1] [datetime] NULL,
[DTTMField2] [datetime] NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Activity](
[ActivityName]
,[Description]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
('ClickURL','Click advertisementURL','URLAddress',NULL,NULL,'ClickCount',NULL,'clickDate',NULL)
GO
INSERT INTO [dbo].[ActivityDetails](
[ActivityTypeID]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
(1,'www.companyurl.com',NULL,NULL,10,NULL,'20140101',NULL)
GO
我必须承认我怀疑你的方法是最好的...但是 - 至少 - 你可以试试这个:
注意: 出于测试目的,我在最后删除了创建的 table。小心真实数据!
--你的table
CREATE TABLE [dbo].[Activity](
[ActivityTypeID] [int] IDENTITY(1,1) NOT NULL,
[ActivityName] VARCHAR(50) NULL,
[Description] VARCHAR(255) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [varchar](50) NULL,
[NumField2] [varchar](50) NULL,
[DTTMField1] [varchar](50) NULL,
[DTTMField2] [varchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ActivityDetails](
[ActivityDetailID] [int] IDENTITY(1,1) NOT NULL,
[ActivityTypeID] VARCHAR(50) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [int] NULL,
[NumField2] [int] NULL,
[DTTMField1] [datetime] NULL,
[DTTMField2] [datetime] NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Activity](
[ActivityName]
,[Description]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
('ClickURL','Click advertisementURL','URLAddress',NULL,NULL,'ClickCount',NULL,'clickDate',NULL)
GO
INSERT INTO [dbo].[ActivityDetails](
[ActivityTypeID]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
(1,'www.companyurl.com',NULL,NULL,10,NULL,'20140101',NULL)
GO
--我声明一个变量并动态创建语句
DECLARE @cmd VARCHAR(MAX)=
(
SELECT
'SELECT ''' + a.ActivityName + ''' AS ActivityName'
+ ',''' + a.Description + ''' AS Description'
+ ISNULL(',''' + ad.StringField1 +''' AS ' + QUOTENAME(a.StringField1),'')
+ ISNULL(',''' + ad.StringField2 +''' AS ' + QUOTENAME(a.StringField2),'')
+ ISNULL(',''' + ad.StringField3 +''' AS ' + QUOTENAME(a.StringField3),'')
+ ISNULL(',' + CAST(ad.NumField1 AS VARCHAR(100)) +' AS ' + QUOTENAME(a.NumField1),'')
+ ISNULL(',' + CAST(ad.NumField2 AS VARCHAR(100)) +' AS ' + QUOTENAME(a.NumField2),'')
+ ISNULL(',CAST(''' + CONVERT(VARCHAR(100),ad.DTTMField1,126) +''' AS DATETIME) AS ' + QUOTENAME(a.DTTMField1),'')
+ ISNULL(',CAST(''' + CONVERT(VARCHAR(100),ad.DTTMField2,126) +''' AS DATETIME) AS ' + QUOTENAME(a.DTTMField1),'')
FROM Activity AS a
INNER JOIN ActivityDetails AS ad ON a.ActivityTypeID=ad.ActivityTypeID
)
--这里执行语句
EXEC(@cmd)
GO
--清理(注意真实数据!)
--DROP TABLE ActivityDetails;
--DROP TABLE Activity;
创建的语句是这样的:
SELECT 'ClickURL' AS ActivityName
,'Click advertisementURL' AS Description
,'www.companyurl.com' AS [URLAddress]
,10 AS [ClickCount]
,CAST('2014-01-01T00:00:00' AS DATETIME) AS [clickDate]
诀窍在于,如果其中一个元素是 NULL
,那么一个连接字符串在整个过程中都是 NULL
。这就是为什么创建的语句将仅包含使用的列的原因。
谢谢 Shnugo.I 也尝试了下面类似的方法。
DECLARE @ActivityTypeID int =1
DECLARE @ColList VARCHAR(MAX)
DECLARE @ActivityDetailsQuery VARCHAR(MAX)
SELECT @ColList = ''''+ ActivityName + ''' as ActivityName ,''' + Description + ''' as Description'
+CASE when StringField1 is not null then ',StringField1 AS '+ stringField1 else '' end
+ CASE when StringField2 is not null then ',StringField2 AS '+ stringField2 else '' end
+ CASE when StringField3 is not null then ',StringField3 AS '+ StringField2 else '' end
+ CASE when NumField1 IS NOT NULL then ',NumField1 AS '+ NumField1 else '' end
+ CASE when NumField2 IS NOT NULL then ',NumField2 AS '+ NumField2 else '' end
+ CASE when DttmField1 IS NOT NULL then ',DttmField1 AS '+ DttmField1 else '' end
+ CASE when DttmField2 IS NOT NULL then ',DttmField2 AS '+ DttmField2 else '' end
from dbo.Activity
where ActivityTypeID = @ActivityTypeID
SET @ActivityDetailsQuery = 'SELECT '+ @ColList + ' FROM dbo.ActivityDetails WHERE ActivityTypeID = ' + CAST(@ActivityTypeID as VARCHAR(10))
EXEC(@ActivityDetailsQuery)
我们有一个类似于 EAV 的数据模型。但是,我们的属性集有限。在我们的数据模型中,我们存储了个人完成的不同活动,并且根据 activity 类型,属性会有所不同。
我们想要获取个人的活动和相应的 attribute/values。我已经描述了 Activity
、ActivityDetails
table 和预期的结果集。
能否请您指导我如何从数据模型中得出预期的结果集?我们必须做一些转变。但是,不确定是否达到相同。
在下面的示例数据中,ClickURL 是一个 Activity。它具有三个属性:URLAddress、ClickCount、ClickDate。三个属性对应的值为:www.companyurl.com,10,20140101
结果集应该如下所示:
ActivityName | Description | URLAddress | ClickCount | ClickDate
-------------------------------------------------------------------------------------------
ClickURL | Click advertisementURL | www.companyurl.com |10 |20140101
Our Data model & Expected Result
数据查询示例
CREATE TABLE [dbo].[Activity](
[ActivityTypeID] [int] IDENTITY(1,1) NOT NULL,
[ActivityName] VARCHAR(50) NULL,
[Description] VARCHAR(255) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [varchar](50) NULL,
[NumField2] [varchar](50) NULL,
[DTTMField1] [varchar](50) NULL,
[DTTMField2] [varchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ActivityDetails](
[ActivityDetailID] [int] IDENTITY(1,1) NOT NULL,
[ActivityTypeID] VARCHAR(50) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [] NULL,
[NumField2] [int] NULL,
[DTTMField1] [datetime] NULL,
[DTTMField2] [datetime] NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Activity](
[ActivityName]
,[Description]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
('ClickURL','Click advertisementURL','URLAddress',NULL,NULL,'ClickCount',NULL,'clickDate',NULL)
GO
INSERT INTO [dbo].[ActivityDetails](
[ActivityTypeID]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
(1,'www.companyurl.com',NULL,NULL,10,NULL,'20140101',NULL)
GO
我必须承认我怀疑你的方法是最好的...但是 - 至少 - 你可以试试这个:
注意: 出于测试目的,我在最后删除了创建的 table。小心真实数据!
--你的table
CREATE TABLE [dbo].[Activity](
[ActivityTypeID] [int] IDENTITY(1,1) NOT NULL,
[ActivityName] VARCHAR(50) NULL,
[Description] VARCHAR(255) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [varchar](50) NULL,
[NumField2] [varchar](50) NULL,
[DTTMField1] [varchar](50) NULL,
[DTTMField2] [varchar](50) NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ActivityDetails](
[ActivityDetailID] [int] IDENTITY(1,1) NOT NULL,
[ActivityTypeID] VARCHAR(50) NULL,
[StringField1] [varchar](50) NULL,
[StringField2] [varchar](50) NULL,
[StringField3] [varchar](50) NULL,
[NumField1] [int] NULL,
[NumField2] [int] NULL,
[DTTMField1] [datetime] NULL,
[DTTMField2] [datetime] NULL
) ON [PRIMARY]
GO
INSERT INTO [dbo].[Activity](
[ActivityName]
,[Description]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
('ClickURL','Click advertisementURL','URLAddress',NULL,NULL,'ClickCount',NULL,'clickDate',NULL)
GO
INSERT INTO [dbo].[ActivityDetails](
[ActivityTypeID]
,[StringField1]
,[StringField2]
,[StringField3]
,[NumField1]
,[NumField2]
,[DTTMField1]
,[DTTMField2]
)
VALUES
(1,'www.companyurl.com',NULL,NULL,10,NULL,'20140101',NULL)
GO
--我声明一个变量并动态创建语句
DECLARE @cmd VARCHAR(MAX)=
(
SELECT
'SELECT ''' + a.ActivityName + ''' AS ActivityName'
+ ',''' + a.Description + ''' AS Description'
+ ISNULL(',''' + ad.StringField1 +''' AS ' + QUOTENAME(a.StringField1),'')
+ ISNULL(',''' + ad.StringField2 +''' AS ' + QUOTENAME(a.StringField2),'')
+ ISNULL(',''' + ad.StringField3 +''' AS ' + QUOTENAME(a.StringField3),'')
+ ISNULL(',' + CAST(ad.NumField1 AS VARCHAR(100)) +' AS ' + QUOTENAME(a.NumField1),'')
+ ISNULL(',' + CAST(ad.NumField2 AS VARCHAR(100)) +' AS ' + QUOTENAME(a.NumField2),'')
+ ISNULL(',CAST(''' + CONVERT(VARCHAR(100),ad.DTTMField1,126) +''' AS DATETIME) AS ' + QUOTENAME(a.DTTMField1),'')
+ ISNULL(',CAST(''' + CONVERT(VARCHAR(100),ad.DTTMField2,126) +''' AS DATETIME) AS ' + QUOTENAME(a.DTTMField1),'')
FROM Activity AS a
INNER JOIN ActivityDetails AS ad ON a.ActivityTypeID=ad.ActivityTypeID
)
--这里执行语句
EXEC(@cmd)
GO
--清理(注意真实数据!)
--DROP TABLE ActivityDetails;
--DROP TABLE Activity;
创建的语句是这样的:
SELECT 'ClickURL' AS ActivityName
,'Click advertisementURL' AS Description
,'www.companyurl.com' AS [URLAddress]
,10 AS [ClickCount]
,CAST('2014-01-01T00:00:00' AS DATETIME) AS [clickDate]
诀窍在于,如果其中一个元素是 NULL
,那么一个连接字符串在整个过程中都是 NULL
。这就是为什么创建的语句将仅包含使用的列的原因。
谢谢 Shnugo.I 也尝试了下面类似的方法。
DECLARE @ActivityTypeID int =1
DECLARE @ColList VARCHAR(MAX)
DECLARE @ActivityDetailsQuery VARCHAR(MAX)
SELECT @ColList = ''''+ ActivityName + ''' as ActivityName ,''' + Description + ''' as Description'
+CASE when StringField1 is not null then ',StringField1 AS '+ stringField1 else '' end
+ CASE when StringField2 is not null then ',StringField2 AS '+ stringField2 else '' end
+ CASE when StringField3 is not null then ',StringField3 AS '+ StringField2 else '' end
+ CASE when NumField1 IS NOT NULL then ',NumField1 AS '+ NumField1 else '' end
+ CASE when NumField2 IS NOT NULL then ',NumField2 AS '+ NumField2 else '' end
+ CASE when DttmField1 IS NOT NULL then ',DttmField1 AS '+ DttmField1 else '' end
+ CASE when DttmField2 IS NOT NULL then ',DttmField2 AS '+ DttmField2 else '' end
from dbo.Activity
where ActivityTypeID = @ActivityTypeID
SET @ActivityDetailsQuery = 'SELECT '+ @ColList + ' FROM dbo.ActivityDetails WHERE ActivityTypeID = ' + CAST(@ActivityTypeID as VARCHAR(10))
EXEC(@ActivityDetailsQuery)