一个比较难的行转列的问题,有测试脚本。

测试脚本如下:

USE [master]
GO
/****** Object:  Table [dbo].[类型表]    Script Date: 10/09/2011 03:59:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[类型表]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[类型表](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [类型组] [varchar](50) NULL,
    [类型名称] [varchar](50) NULL,
    [类别] [varchar](50) NULL,
CONSTRAINT [PK_类型表] PRIMARY KEY CLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[类型表] ON
INSERT [dbo].[类型表] ([id], [类型组], [类型名称], [类别]) VALUES (1, N'A', N'生产日期', N'日期')
INSERT [dbo].[类型表] ([id], [类型组], [类型名称], [类别]) VALUES (2, N'A', N'库存类型', N'选择')
INSERT [dbo].[类型表] ([id], [类型组], [类型名称], [类别]) VALUES (3, N'A', N'产品状态', N'文本')
SET IDENTITY_INSERT [dbo].[类型表] OFF
/****** Object:  Table [dbo].[库存表]    Script Date: 10/09/2011 03:59:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[库存表]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[库存表](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [批号] [varchar](50) NULL,
    [类型ID] [bigint] NULL,
    [属性值] [varchar](50) NULL,
CONSTRAINT [PK_库存表] PRIMARY KEY CLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[库存表] ON
INSERT [dbo].[库存表] ([id], [批号], [类型ID], [属性值]) VALUES (2, N'A01', 1, N'2011-06-08')
INSERT [dbo].[库存表] ([id], [批号], [类型ID], [属性值]) VALUES (3, N'A01', 2, N'1')
INSERT [dbo].[库存表] ([id], [批号], [类型ID], [属性值]) VALUES (4, N'A01', 3, N'已检验')
INSERT [dbo].[库存表] ([id], [批号], [类型ID], [属性值]) VALUES (5, N'A02', 1, N'2011-06-06')
INSERT [dbo].[库存表] ([id], [批号], [类型ID], [属性值]) VALUES (6, N'A02', 2, N'2')
INSERT [dbo].[库存表] ([id], [批号], [类型ID], [属性值]) VALUES (7, N'A02', 3, N'未检验')
SET IDENTITY_INSERT [dbo].[库存表] OFF
/****** Object:  Table [dbo].[类型属性表]    Script Date: 10/09/2011 03:59:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[类型属性表]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[类型属性表](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [类型ID] [bigint] NOT NULL,
    [属性] [varchar](50) NULL,
CONSTRAINT [PK_类型属性表] PRIMARY KEY CLUSTERED
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
SET ANSI_PADDING OFF
GO
SET IDENTITY_INSERT [dbo].[类型属性表] ON
INSERT [dbo].[类型属性表] ([id], [类型ID], [属性]) VALUES (1, 2, N'良品')
INSERT [dbo].[类型属性表] ([id], [类型ID], [属性]) VALUES (2, 2, N'次品')
SET IDENTITY_INSERT [dbo].[类型属性表] OFF
/****** Object:  ForeignKey [FK_类型属性表_类型表]    Script Date: 10/09/2011 03:59:20 ******/
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_类型属性表_类型表]') AND parent_object_id = OBJECT_ID(N'[dbo].[类型属性表]'))
ALTER TABLE [dbo].[类型属性表]  WITH CHECK ADD  CONSTRAINT [FK_类型属性表_类型表] FOREIGN KEY([类型ID])
REFERENCES [dbo].[类型表] ([id])
GO
IF  EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_类型属性表_类型表]') AND parent_object_id = OBJECT_ID(N'[dbo].[类型属性表]'))
ALTER TABLE [dbo].[类型属性表] CHECK CONSTRAINT [FK_类型属性表_类型表]
GO


我用如下行转列的代码:

declare @sql varchar(8000)
set @sql ='  
select
c.批号
'
select @sql = @sql + ' , max(case [类型名称] when ''' + ltrim(a.[类型名称]) + ''' then ltrim([属性值]) else null end) [' + a.[类型名称] + ']'
from (select distinct 类型名称 from 类型表 ) as a
set @sql =@sql + ' from dbo.库存表 c , dbo.类型表 b where b.id=c.类型ID
group by c.批号
'
exec(@sql)



得到了如下结果:
批号 产品状态 库存类型 生产日期
A01 已检验 1 2011-06-08
A02 未检验 2 2011-06-06



我现在的问题是:库存类型下的值,仍然显示的属性表的ID,而不是所对应真正的值。怎么显示真正值出来呢(当然是从类型属性表里取)?


期望结果如下:
批号 产品状态 库存类型 生产日期
A01 已检验 良品 2011-06-08
A02 未检验 次品 2011-06-06


当然最后提醒下,类型表里的行是动态的,所以转列的时候当然也是动态的,不会是定死的三种。

作者: maysoft   发布时间: 2011-10-09

在关联一次,将属性值读取出来即可。

作者: oswica   发布时间: 2011-10-09