横向明确行联合的SQL查询建议

时间:2014-07-21 16:40:31

标签: sql sql-server tsql

表格Family就像

No.  ADD  Member  Det1  Det2  Det3  Det4

1    Add1  Dad1    q     w     e     r
1    Add1  Mom1    q     w     e     r
1    Add1  Chd1    q     w     e     r
1    Add1  Chd1    q     w     e     r
1    Add2  Mom2    q     w     e     r
1    Add2  Chd2    q     w     e     r
1    Add2  Chd2    q     w     e     r
这里的

ADD 就像每个家庭唯一的家庭ID一样,会员是会员姓名,家庭可以有任意号码。

期望的输出:

No.  ADD  Member  Det1  Det2  Det3  Det4  Member  Det1  Det2  Det3  Det4 .. more
1    Add1 Dad1    q     w     e     r     Mom1    q     w     e     r    .. more
2    Add2 Mom2    q     w     e     r     Chd1    q     w     e     r    .. more

我尝试为成员数量

创建别名
SELECT a.ADD
    ,a.Member
    ,a.Det1
    ,a.Det2
    ,a.Det3
    ,a.Det4
    ,b.bDD
    ,b.Member
    ,b.Det1
    ,b.Det2
    ,b.Det3
    ,b.Det4
FROM Family a
    ,Family b
WHERE a.ADD = b.ADD

1 个答案:

答案 0 :(得分:0)

编辑:太平洋标准时间11:26我认为你需要动态SQL来做你想做的事情。当您正在执行一个复杂的块集时,您将逐列添加并重复列名称。

declare @Temp table ( [No] int, [Add] varchar(4), Member varchar(4), Det1 char, Det2 char, Det3 char, Det4 char);

insert into @Temp values
(1,    'Add1', 'Dad1', 'q','w','e','r'),
(1,    'Add1', 'Mom1', 'q','w','e','r'),
(1,    'Add1', 'Chd1', 'q','w','e','r'),
(1,    'Add1', 'Chd1', 'q','w','e','r'),
(1,    'Add2', 'Mom2', 'q','w','e','r'),
(1,    'Add2', 'Chd2', 'q','w','e','r'),
(1,    'Add2', 'Chd2', 'q','w','e','r')


if object_id('tempdb..#Temp') is not null
    drop table #temp

select 
    No
,  [Add]
,  Member
,  Det1
,  Det2
,  Det3
,  Det4
,  dense_rank() over(order by [Add]) as part
,  row_number() over(partition by [Add] order by Member) as rwn

into #Temp
from @Temp

declare 
    @Cursor int = 1
,   @Max int

,   @Addendum varchar(max) = ''
,   @NL char = char(10)
,   @SQL nvarchar(max) 
,   @Part int
;

-- set up my loop prep

-- statement to execute later
select @SQL = 'Select No, [Add] ' + @NL + 'from #Temp' + @NL + 'group by No, [Add]';

-- max iteration of an occurence
Select @Max = max(rwn) from #Temp 

-- ensure we use the part that has the max occurrence, less we get less results than we need
Select @Part = max(part) from #Temp where rwn = @Max

-- While the statement is looping it is adding to itself dynamically to select your values.  I could do a loop of a loop 
-- to get only certain values you want too, but this is enough for an example.  EG, set a bit for Det1, Det2 and then make a statement for those things too.
While @Cursor <= @Max
BEGIN
    Select @Addendum += @NL + ', max(case when rwn = ' + cast(@Cursor as varchar) + ' then Member end) as Member ' +
        @NL + ', max(case when rwn = ' + cast(@Cursor as varchar) + ' then Det1 end) as Det1 ' +
        @NL + ', max(case when rwn = ' + cast(@Cursor as varchar) + ' then Det2 end) as Det2 ' +
        @NL + ', max(case when rwn = ' + cast(@Cursor as varchar) + ' then Det3 end) as Det3 ' +
        @NL + ', max(case when rwn = ' + cast(@Cursor as varchar) + ' then Det4 end) as Det4 '
    from #Temp where part = @Part and rwn = @Cursor

    Select @Cursor += 1;

END

-- 'stuff' is a sql syntax to insert in a specific place a chunk of something.
Select @SQL = stuff(@SQL, charindex('from', @SQL), 0,  @Addendum + @NL);

-- I want to now 'execute' the statement I just built up in memory to select what I need
exec sp_executesql @SQL

看起来你只是在做一个复杂的分组,但我不确定你的例子,如果你想要明确地遗漏你的一些成员。这将按原样在SQL Server 2008及更高版本上运行:

declare @Temp table ( [No] int, [Add] varchar(4), Member varchar(4), Det1 char, Det2 char, Det3 char, Det4 char);

insert into @Temp values
(1,    'Add1', 'Dad1', 'q','w','e','r'),
(1,    'Add1', 'Mom1', 'q','w','e','r'),
(1,    'Add1', 'Chd1', 'q','w','e','r'),
(1,    'Add1', 'Chd1', 'q','w','e','r'),
(1,    'Add2', 'Mom2', 'q','w','e','r'),
(1,    'Add2', 'Chd2', 'q','w','e','r'),
(1,    'Add2', 'Chd2', 'q','w','e','r')

Select *
from @Temp

select 
    No
,   [Add]
,   Member
,   max(Det1) as Det1
,   max(Det2) as Det2
,   max(Det3) as Det3
,   max(Det4) as Det4
from @Temp
group by No, [Add], Member

A&#39; Pivot&#39;程序适用于获取一组通常与单一类型相关联的值。值。这适用于查找值为多行的事物。

就像你有一个人,他们被链接到一个订单表,订单表有一个类型列与查找表相关,查找表是一个密钥对表,如

1 =衬衫,2 =裤子,3 =鞋子,4 =袜子,5 =腰带,6 =帽子,7 =手表等。

你可以通过简单的左连接和表达&#39;类型&#39;来为一些事情做一个转移。你想要转移。 EG:

from person p
left join order o1 on p.personid = o1.personid and o1.type = 1
left join order o2 on p.personid = o2.personid and o2.type = 2

引擎中没有规则表明你只能加入一次表,所以如果我指定你加入关系并特别是某种类型,我可以像这样评估我的选择:

 Select p.PersonName, o1.Value, o2.Value

通常情况下,如果您拥有一大堆类型并且您不想进行多个左连接,则会使用Pivot。当你做一组你想要分组的序列时,你真的只需要做一个&#39;组。对于简单的集合。我可以通过以下方式做到这一点:

  1. 上面列出的标准组,其中&#39;组中的每一列按&#39;控制流量,然后进行聚合(上面使用的最大值),只能找到该分组最大出现次数的单个值。如果您的No,Add和Member将具有单个值,则表示此方法有效。
  2. 在下面的表达式中为我做分组的最大值(case then then then end)语句:

    选择     y.PersonName ,max(OrderID = 1然后OrderAmount结束的情况) ,max(OrderID = 2然后OrderAmount结束的情况) ,max(OrderID = 3然后OrderAmount结束的情况) 来自@Person y     在x.PersonId = y.PersonId上加入@Orders x 按人名分组

  3. 窗口函数可以为我提供动态分组功能,而不需要&#39;组。子句。

    选择     y.PersonName , 订单金额 ,row_number()over(按OrderName的PersonName顺序分区)orderbyAmount ,row_number()over(由OrderAmount desc按PersonName顺序分区)orderbyAmountDesc ,max(OrderID = 1然后OrderAmount结束时的情况)over(按PersonName分区)

    ,max(OrderID = 2然后OrderAmount结束时的情况)over(按PersonName分区) ,max(OrderID = 3然后OrderAmount结束时的情况)over(按PersonName分区) 来自@Person y     加入@Orders x on x.PersonId = y.PersonId

  4. 如果有人想要一些疯狂的报告,列出第二次或最后一次出现的复杂过程,这给了我灵活性。