SQL 表 : Can I Pivot/Join with N rows?

标签 sql database datagrid pivot-table

首先,我是一个 SQL 菜鸟,其次如果有更好的解决方案可以稍后用代码实现,我很乐意听到。此外,数据目前存储在 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 表中的行数设置具有可变列数的 View ?

请注意,我使用 Visual Studio 创建数据 xsd 并让它自动生成表填充方法,然后在 WPF DataGrid 中显示信息,因此能够直接绑定(bind)到具有正确数据的 View 将是理想的选择.

最佳答案

是的,但仅限于使用动态 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 是一个 base64 编码的图像,在 RTR_nCode 中定义了 mime,以防万一您想知道。

关于SQL 表 : Can I Pivot/Join with N rows?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9193462/

相关文章:

c# - WPF 数据网格 : header misaligned and unnecessary scrollbar

sql - 每周总计唯一序列号

sql - 我需要对 sql 查询进行健全性检查,如果表中存在该值,则返回一个值;如果不存在,则返回默认值

wpf - 使用 IDataError 进行验证

asp.net-mvc - 防止授权用户编辑不属于他的数据

sql-server - 多答案问题的最佳数据库模型是什么

wpf - 无法将 observablecollection 绑定(bind)到 MVVM 中的数据网格

python - SQLAlchemy select_from 单个表

mysql - 在mysql中从右开始的3个字符后向字符串添加空格

mysql 查询 - 一对多关系