【发布时间】:2022-01-02 11:49:12
【问题描述】:
假设我有 3 个表:users、customattributes 和 customattributevalues。最终用户可以通过选择属性的名称和类型来添加自定义属性,并为任何用户编辑值。
这是我的用户:
| id | firstname | lastname | active | datecreated | username | |
|---|---|---|---|---|---|---|
| 3 | Ellen | Ripley | 1 | 3/25/2235 | 78439 | Rip8439@Weyland-Yutani.com |
| 5 | Johnny | Rico | 1 | 4/16/2675 | Roughneck31 | RicoJ31@Roughnecks.com |
自定义属性(可以随时添加)
| id | fullname | uniquename | type |
|---|---|---|---|
| 1 | Hire Date | hiredate | date |
| 2 | Employee ID | eeid | int |
| 3 | Supervisor | supervisor | nvarchar(50) |
| 4 | Assigned Ship | assignedship | nvarchar(50) |
| 5 | Job Title | jobtitle | nvarchar(50) |
我目前拥有的类型为 sysname 数据类型。
自定义属性值(可以随时编辑)
| id | attributeid | userid | value |
|---|---|---|---|
| 1 | 1 | 3 | 2335-03-25 |
| 2 | 2 | 3 | 78439 |
| 3 | 3 | 3 | Burke, Carter |
| 4 | 4 | 3 | Sulaco |
| 5 | 5 | 3 | Consultant |
| 6 | 1 | 5 | 2675-04-16 |
| 7 | 2 | 5 | 78440 |
| 8 | 3 | 5 | LT Rasczak |
| 9 | 4 | 5 | Rodger Young |
| 10 | 5 | 5 | Private |
我目前拥有sql_variant 数据类型的值
所以这是我的问题:如何在不知道有多少自定义属性的情况下创建一个显示所有员工及其属性的报告,每个员工 1 行 -- 并且 -- 至关重要的是,我想明确将每一列转换为正确的数据类型
期望的输出:
| firstname | lastname | datecreated | username | Hire Date | Employee ID | Supervisor | Assigned Ship | Job Title | |
|---|---|---|---|---|---|---|---|---|---|
| Ellen | Ripley | 2235-03-25 | 78439 | Rip8439@Weyland-Yutani.com | 2335-03-25 | 78439 | Burke, Carter | Sulaco | Consultant |
| Johnnie | Rico | 2675-04-16 | Roughneck31 | RicoJ31@Roughnecks.com | 2675-04-16 | 78440 | LT Rasczak | Rodger Young | Private |
我已经学会了使用dynamic queries 来做动态列标题,但这是我逃避的类型转换。
我正在适应this solution for custom fields,但此解决方案的限制是您必须知道每个自定义字段才能进行类型转换。
这是我尝试过的。我得到了正确的输出,除了类型转换。
查询:
DECLARE @columns NVARCHAR(MAX) = '';
DECLARE @sqlcmd NVARCHAR(MAX) = '';
SELECT @columns += QUOTENAME(fullname) + ','
FROM customattributesx ca
ORDER BY ca.id;
SET @columns = LEFT(@columns, LEN(@columns) - 1);
--PRINT @columns;
SET @sqlcmd = '
SELECT * FROM (
SELECT userid
,firstname
,lastname
,datecreated
,username
,email
,fullname
,value
FROM (
SELECT u.id as userid
,u.firstname
,u.lastname
,u.datecreated
,u.username
,u.email
,ca.id
,ca.fullname as fullname
,ca.uniquename
,ca.type
,cav.value as value
FROM dbo.users u
CROSS JOIN customattributesx ca
INNER JOIN customattributevaluesx cav
ON cav.attributeid = ca.id AND cav.userid = u.id
--ORDER BY u.id asc, ca.id asc
) t1
) t2
PIVOT (
MIN(value)
FOR fullname IN ('+@columns+')
) as pivottable
';
--print @sqlcmd
EXECUTE (@sqlcmd)
创建表:
USE [CTMS]
GO
/****** Object: Table [dbo].[users] Script Date: 11/24/2021 9:29:16 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[users](
[id] [int] IDENTITY(1,1) NOT NULL,
[firstname] [nvarchar](max) NULL,
[lastname] [nvarchar](max) NULL,
[active] [bit] NOT NULL,
[datecreated] [datetime2](7) NOT NULL,
[username] [nvarchar](256) NULL,
[email] [nvarchar](256) NULL,
[emailconfirmed] [bit] NOT NULL,
[passwordhash] [nvarchar](max) NULL,
[twofactorenabled] [bit] NOT NULL,
[lockoutend] [datetimeoffset](7) NULL,
[eockoutenabled] [bit] NOT NULL,
[accessfailedcount] [int] NOT NULL,
[qrcode] [nvarchar](50) NULL,
CONSTRAINT [PK_id] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_email] UNIQUE NONCLUSTERED
(
[email] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_qrcode] UNIQUE NONCLUSTERED
(
[qrcode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_username] UNIQUE NONCLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] ADD DEFAULT (getutcdate()) FOR [datecreated]
GO
USE [CTMS]
GO
/****** Object: Table [dbo].[customattributesx] Script Date: 11/24/2021 9:31:09 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customattributesx](
[id] [smallint] IDENTITY(1,1) NOT NULL,
[fullname] [nvarchar](50) NOT NULL,
[uniquename] [nvarchar](50) NOT NULL,
[type] [sysname] NOT NULL,
CONSTRAINT [PK_customattributesx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk1_customattributesx] UNIQUE NONCLUSTERED
(
[uniquename] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [CTMS]
GO
/****** Object: Table [dbo].[customattributevaluesx] Script Date: 11/24/2021 9:31:27 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customattributevaluesx](
[id] [int] IDENTITY(1,1) NOT NULL,
[attributeid] [smallint] NOT NULL,
[userid] [int] NOT NULL,
[value] [sql_variant] NOT NULL,
CONSTRAINT [PK_customattributevaluesx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk1_customattributevaluesx] UNIQUE NONCLUSTERED
(
[attributeid] ASC,
[userid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[customattributevaluesx] WITH CHECK ADD CONSTRAINT [fk1_customattributesvaluesx] FOREIGN KEY([attributeid])
REFERENCES [dbo].[customattributesx] ([id])
GO
ALTER TABLE [dbo].[customattributevaluesx] CHECK CONSTRAINT [fk1_customattributesvaluesx]
GO
ALTER TABLE [dbo].[customattributevaluesx] WITH CHECK ADD CONSTRAINT [fk2_customattributesvaluesx] FOREIGN KEY([userid])
REFERENCES [dbo].[users] ([id])
GO
ALTER TABLE [dbo].[customattributevaluesx] CHECK CONSTRAINT [fk2_customattributesvaluesx]
GO
【问题讨论】:
-
“将每一行转换为正确的数据类型”还是每一列?你当然知道给定列的每一行都必须具有相同的数据类型?
-
@DaleK 我的意思是输入“将每一列转换为正确的数据类型”。这些值存储为 sql_variants,但是当透视时,每列都有一致的类型、日期、int、nvarchar 等。
-
@DaleK 我添加了对我一直在解决的解决方案的另一个参考。
-
由于
pivot必须有一个锚列围绕它旋转结果,您将基于员工id进行旋转,然后在员工表上加入旋转结果以查找 @ 987654332@ 和lastname. -
我们想看看您实际尝试了什么,而不是其他解决方案的链接。
标签: sql sql-server tsql dynamic pivot