如何使用t-sql从该表中提取数据并将其转换为特定格式?

时间:2019-06-05 10:26:27

标签: sql sql-server tsql

我正在使用SQL Server 2014。下面是一个名为Table1的表的摘录:

ID     Market    Adult   AdultAge   0-5   6-12   13-17
100     UK         1        50       0     0       0
105     UK         2        36       0     0       0
107     DE         1        65       0     1       0
110     FR         2        42       0     2       1 
115     BE         1        18       1     0       0  

第0-5、6-12和13-17列是年龄类别,其中包含儿童人数。

我需要将此表转换为以下格式并使用以下逻辑:

  • 如果“成人”的计数为2,则第二个成人的年龄为记录的年龄减去2。
  • 孩子的年龄将是其年龄类别的中点。也就是说,如果在特定类别(例如6-12岁)中有1个孩子(或2个或更多孩子),则该孩子(或每个孩子(如果超过1个))的年龄为(12 + 6)/ 2 = 9年。相同的逻辑适用于其他年龄段。

所以,这是我想要的最终输出:

ID      Market   Age    Category
100     UK       50      Adult
105     UK       36      Adult
105     UK       34      Adult
107     DE       65      Adult
107     DE        9      Child
110     FR       42      Adult
110     FR       40      Adult
110     FR        9      Child
110     FR        9      Child
110     FR       15      Child
115     BE       18      Adult
115     BE        2.5    Child

我正在考虑使用一些CASE语句来转换数据,但是对于如何实现这些数据我确实感到困惑。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

您需要详细的unpivot。一种方法是使用统计表创建多行,并使用cross apply

;WITH Tally (n) AS
(
    -- 1000 rows
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
    CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
)
SELECT t.id,t.market,q.*
FROM  [Table1] t
outer apply
(
    select t.adultage,'Adult' where adult>=1
    union all
    select adultage-2,'Adult' where adult=2
    union all
    select 2.5,'Child' from Tally where n<=[0-5]
    union all
    select 9,'Child' from Tally  where n<=[6-12]
    union all
    select 15,'Child' from Tally  where n<=[13-17]
)q(Age,Category)

答案 1 :(得分:1)

这有点复杂,但是数字表会有所帮助。您可以使用递归CTE(最多100个)轻松生成一个,或者您周围可能只有一个。

然后您需要取消透视并应用更多逻辑:

with numbers as (
      select 1 as n
      union all
      select n + 1
      from numbers
      where n <= 10
     )
select x.*
from table1 t1 cross apply
     (select t1.ID, t1.Market, category,
             (case when v.category = 'Adult' and n.n = 2 then v.age - 2
                   else v.age
              end) as age
      from (values (t1.AdultAge, 'Adult', t1.Adult),
                   (2.5, 'Child', t1.[0-5]),
                   (9, 'Child', t1.[6-12]),
                   (15, 'Child', t1.[13-17])
           ) v(age, category, cnt) join
           numbers n
           on n.n <= v.cnt
     ) x;

Here是db <>小提琴。