【问题标题】:Cross join N sets of rows in same table交叉连接同一表中的 N 组行
【发布时间】:2012-09-17 23:24:51
【问题描述】:

我有一个通用的“Dimension”和“DimensionMember”表。

CREATE TABLE [dbo].[Dimension]
(
    [ID] [int] NOT NULL IDENTITY(1, 1),
    [Label] [nvarchar] (255)
) 

CREATE TABLE [dbo].[DimensionMember]
(
[ID] [int] NOT NULL IDENTITY(1, 1),
[Label] [nvarchar] (255) NOT NULL,
[DimensionID] [int] NOT NULL
) 
GO
ALTER TABLE [dbo].[DimensionMember] ADD CONSTRAINT [FK_DimensionMember_DimensionID_Dimension_ID] FOREIGN KEY ([DimensionID]) REFERENCES [dbo].[Dimension] ([ID])

这些表存储了大量的维度和维度成员。

我想从可变数量的维度交叉连接维度成员。 示例:来自 'Sex'、'Employment Type'、'Contract Type' 维度的交叉连接维度成员应产生以下组合

'Male,Full time, Employee'
'Female,Full time, Employee'
'Male,Part time, Employee'
'Female,Part time, Employee'

'Male,Full time, Contractor'
'Female,Full time, Contractor'
'Male,Part time, Contractor'
'Female,Part time, Contractor'

组合的标签应通过连接维度成员的标签来创建(如上所示)。

提前谢谢你

更新

维度列表(例如“性别”、“就业类型”、“合同类型”)是动态的(由运行时的另一个查询生成)。

更新 2

修复了一个小错误(Dimension1 -> Dimension)。对不起!

【问题讨论】:

    标签: sql sql-server join cross-join


    【解决方案1】:

    这个模式怎么样? (SQL Fiddle)

    select a.label+','+b.label+','+c.label
    from (select m.label from dimension1 d
      join dimensionmember m
          on m.dimensionid = d.id and d.label = 'sex') a
    cross join (select m.label from dimension1 d
      join dimensionmember m 
          on m.dimensionid = d.id and d.label = 'Employment Type') b
    cross join (select m.label from dimension1 d
      join dimensionmember m 
          on m.dimensionid = d.id and d.label = 'Contract Type') c
    

    当然,您需要知道要构建多少个子查询,因此 SELECT 中的串联部分需要多长时间。


    编辑

    这是一个可以做到这一切的(更新SQL Fiddle

    ;with base as (
       select m.label, d.id, dense_rank() over (order by d.id) rk
         from dimension1 d
         join dimensionmember m
           on m.dimensionid = d.id
        where d.label in ('sex','Employment Type','Contract Type')
    ), cte as (
       select cast(label as varchar(max)) list, rk
         from base
        where rk=1
    union all
       select cast(cte.list+','+base.label as varchar(max)), base.rk
         from cte
         join base on base.rk=cte.rk+1
    )
       select list
         from cte
        where rk=(select max(rk) from base)
    

    【讨论】:

    • 这让我很困惑,因为您将限制放在 join 子句中,而我希望在 where 子句中看到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多