首先,我是一个SQL noob,第二,如果有更好的解决方案可以在以后的代码中实现,我很乐意听到它。此外,数据当前存储在MySQL中,但最终必须移植到MSSQL,因此跨数据库解决方案最好(如果存在)。
现在,问题是,我的简化数据如下所示:
[STYLES]
ID NAME
1 A Style
2 B Style
...
N N Style
[EQUIPMENT]
ID NAME
1 A Equipment
2 B Equipment
...
N N Equipment
[AVAILABILITY]
STYLE EQUIPMENT TYPE
1 1 Standard
1 2 Optional
2 1 Optional
... #items will be missing and represent not available
2 2 Standard
现在我需要一个看起来像这样的表:
[DESIRED_VIEW]
EQUIPMENT_NAME A_STYLE_TYPE B_STYLE_TYPE ... N_STYLE_TYPE
A Equipment Standard Optional ... NULL
B Equipment Optional NULL ... Standard
我已经看到了许多简单的数据透视示例,它们都依赖于具有一定数量的列。有没有办法根据STYLES表中有多少行来设置具有可变列数的视图?
作为一个注释,我使用Visual Studio创建Data xsd并让它自动生成表填充方法,然后在WPF DataGrids中显示信息,这样能够直接绑定到具有正确数据的视图将是理想的
答案 0 :(得分:2)
是的,但仅限于使用动态SQL(存储过程)时。 这是现实生活中的一个例子
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_RPT_Report_Translation]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[sp_RPT_Report_Translation]
GO
-- ===========================================================
-- Author: [CENSORED]
-- Create date: 14.04.2011
-- Last modified: 17.01.2012
-- Description: Übersetzung für Berichte
-- ===========================================================
-- Pre: Valid Report Name & datetime
-- Post: Translation for language in first row with rownames as defined
-- for each item in T_RPT_Translations.RTR_ItemCaption
CREATE PROCEDURE [dbo].[sp_RPT_Report_Translation]
@in_mandant varchar(3)
,@in_sprache varchar(2)
,@in_stichtag varchar(50)
,@in_report_name nvarchar(1000)
AS
BEGIN
DECLARE
@strSQL NVARCHAR(MAX)
,@strReportName NVARCHAR(1000)
,@strPivotColumns NVARCHAR(MAX)
,@stichtag DATETIME
-- Abrunden des Eingabedatums auf 00:00:00 Uhr
SET @stichtag = CONVERT(DATETIME, @in_stichtag)
SET @stichtag = CAST(FLOOR(CAST(@stichtag AS Float)) AS DateTime)
SET @in_stichtag = CONVERT(varchar(50), @stichtag)
SET NOCOUNT ON;
SET @strReportName = REPLACE(@in_report_name, N'''', '''''')
-- http://geekswithblogs.net/baskibv/archive/2008/07/03/123567.aspx
SELECT
@strPivotColumns = COALESCE(@strPivotColumns, '') + '[' + [RTR_ItemCaption] + '], '
FROM T_RPT_Translations
WHERE (RTR_Status = 1)
AND (RTR_MDT_ID = @in_mandant)
AND
(
(RTR_ReportName = @strReportName)
OR
(RTR_ReportName = 'PARA_ALL')
)
--AND (RTR_ItemCaption != 'RPT_Title')
AND (RTR_ItemCaption IS NOT NULL)
AND
(
(RTR_IsFlag != 1)
OR
(RTR_IsFlag IS NULL)
)
AND (RTR_ItemCaption != '')
ORDER BY RTR_Sort
SET @strPivotColumns = SUBSTRING(@strPivotColumns, 0, LEN(@strPivotColumns))
SET @strPivotColumns = REPLACE(@strPivotColumns, N'''', '''''')
--PRINT @strPivotColumns
SET @strSQL = '
SELECT TOP(1) * FROM
(
SELECT
RTR_ItemCaption
--,RTR_Kurz_' + @in_sprache + '
,RTR_Lang_' + @in_sprache + '
FROM T_RPT_Translations
WHERE (RTR_MDT_ID = ''' + @in_mandant+ ''')
AND
(
(RTR_ReportName = ''' + @strReportName + ''')
OR
(RTR_ReportName = ''PARA_ALL'')
)
--AND (RTR_ItemCaption != ''RPT_Title'')
AND (RTR_Status = 1)
AND (RTR_ItemCaption IS NOT NULL)
AND
(
(RTR_IsFlag != 1)
OR
(RTR_IsFlag IS NULL)
)
AND (RTR_ItemCaption != '''')
) AS SourceTable
PIVOT
(
MAX(RTR_Lang_' + @in_sprache + ')
FOR RTR_ItemCaption IN
( '
+ @strPivotColumns +
' )
) AS PivotTable
--ORDER BY RPT_RM_SO_Bezeichnung, RPT_RM_GB_Bezeichnung, RPT_RM_NutzungGruppeCode
'
DECLARE @ProzedurParameter nvarchar(max)
SET @ProzedurParameter = '
DECLARE @in_mandant varchar(3)
,@in_sprache varchar(2)
,@in_stichtag varchar(50)
,@in_report_name nvarchar(1000)
;
SET @in_mandant = ''' + REPLACE(@in_mandant, '''', '''''') + ''';
SET @in_sprache = ''' + REPLACE(@in_sprache, '''', '''''') + ''';
SET @in_stichtag = ''' + REPLACE(@in_stichtag, '''', '''''') + ''';
SET @in_report_name = ''' + REPLACE(@in_report_name, '''', '''''') + ''';
'
EXECUTE sp_RPT_DEBUG_LOG_ProzedurRun
'sp_RPT_Report_Translation'
,@ProzedurParameter
,@strSQL
,'' --@ProzedurDetail
;
--PRINT @strSQL
EXECUTE (@strSQL)
END
GO
表格:
CREATE TABLE [dbo].[T_RPT_Translations](
[RTR_UID] [uniqueidentifier] NULL,
[RTR_ReportName] [nvarchar](1000) NULL,
[RTR_MDT_ID] [int] NULL,
[RTR_ItemCaption] [nvarchar](50) NULL,
[RTR_Code] [int] NULL,
[RTR_nCode] [nvarchar](100) NULL,
[RTR_Kurz_DE] [nvarchar](20) NULL,
[RTR_Kurz_FR] [nvarchar](20) NULL,
[RTR_Kurz_IT] [nvarchar](20) NULL,
[RTR_Kurz_EN] [nvarchar](20) NULL,
[RTR_Lang_DE] [nvarchar](100) NULL,
[RTR_Lang_FR] [nvarchar](100) NULL,
[RTR_Lang_IT] [nvarchar](100) NULL,
[RTR_Lang_EN] [nvarchar](100) NULL,
[RTR_Img_DE] [varchar](max) NULL,
[RTR_Img_FR] [varchar](max) NULL,
[RTR_Img_IT] [varchar](max) NULL,
[RTR_Img_EN] [varchar](max) NULL,
[RTR_Img_Width] [int] NULL,
[RTR_Img_Height] [int] NULL,
[RTR_Img_PaddingLeft] [float] NULL,
[RTR_Img_PaddingRight] [float] NULL,
[RTR_Img_PaddingTop] [float] NULL,
[RTR_Img_PaddingBottom] [float] NULL,
[RTR_Img_Hide] [bit] NULL,
[RTR_IsLogo] [bit] NULL,
[RTR_IsFlag] [bit] NULL,
[RTR_Sort] [int] NULL,
[RTR_Status] [int] NULL,
[RTR_DatumVon] [datetime] NULL,
[RTR_DatumBis] [datetime] NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_UID] DEFAULT (newid()) FOR [RTR_UID]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_ReportName] DEFAULT (N'InsertError') FOR [RTR_ReportName]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_MDT_ID] DEFAULT ((0)) FOR [RTR_MDT_ID]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_ItemCaption] DEFAULT (N'InsertError') FOR [RTR_ItemCaption]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_IsLogo] DEFAULT ((0)) FOR [RTR_IsLogo]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_IsFlag] DEFAULT ((0)) FOR [RTR_IsFlag]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_Sort] DEFAULT ((0)) FOR [RTR_Sort]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_Status] DEFAULT ((1)) FOR [RTR_Status]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_DatumVon] DEFAULT ('17530101') FOR [RTR_DatumVon]
GO
ALTER TABLE [dbo].[T_RPT_Translations] ADD CONSTRAINT [DF_T_RPT_Translations_RTR_DatumBis] DEFAULT ('99991231') FOR [RTR_DatumBis]
GO
如果您不理解德语参数:
@in_sprache: in_language
@in_stichtag: in_ReportingDate
DatumVon: DateFrom
DatumBis: DateTo
rest is clear
RTR_Img_XX是一个基于64位编码的图像,其中mime在RTR_nCode中定义,万一你想知道。
答案 1 :(得分:0)
否 - 无法编写具有动态列数的查询。
您的选择(按优先顺序排列):
如果您对最大数量的样式感到满意(它可以是任意大的,但是有限的),您的数据透视代码将如下所示:
select
e.name as equipment_name,
a1.type as a_style_type,
a2.type as b_style_type,
a3.type as c_style_type,
...
an.type as n_style_type
from equipment e
left join availability a1 on a1.equipment = e.id and a1.style = 1
left join availability a2 on a2.equipment = e.id and a2.style = 2
left join availability a3 on a3.equipment = e.id and a3.style = 3
...
left join availability an on an.equipment = e.id and an.style = 999;
如果给定样式没有可用性类型,您将获得NULL
。
此外,您需要知道样式ID,并且它们需要在所有environemtns上相同。如果不是这种情况(例如测试/产品环境不同),您可以将a1.style = 1
更改为a1.style = (select id from style where name = 'A Style')
等 - 它仍然可以正常运行。