【问题标题】:Create a row for each cell that has data from multiple columns为每个包含多列数据的单元格创建一行
【发布时间】:2014-10-30 04:50:27
【问题描述】:

我正在处理一项调查生成的数据,该调查以唯一的受访者 ID 作为第一列,然后有多个列与受访者在寻找员工时所查看的国家/地区的选择相关。所以我的桌子看起来像:

RespondentID  Andorra  Austria  Belgium  Cyprus  Denmark  Finland  France   

2546078180    Andorra  NULL     NULL     Cyprus  NULL     NULL     NULL 
2546077668    NULL     NULL     Belgium  NULL    NULL     NULL     NULL 
2546077120    NULL     NULL     NULL     NULL    Denmark  Finland  NULL 

我想最终得到一个表格,其中列出了给出的每个答案的受访者 ID。所以根据上面的数据,它看起来像:

RespondentID  Country   

2546078180    Andorra
2546078180    Cyprus
2546077668    Belgium
2546077120    Denmark
2546077120    Finland   

因为这应该允许我创建一个表格,详细说明与受访者相关联的国家/地区,然后我可以将此表格加入其他大部分是/否或单一答案的回复中,我们需要对数据进行报告.

这些数据是通过 Excel 电子表格输入的,因此如果需要或更好的话,在导入 SQL 之前进行一些格式化也是可以接受的。

【问题讨论】:

    标签: sql excel tsql normalization unpivot


    【解决方案1】:

    UNION 子句是要走的路:

      SELECT * FROM (
        SELECT RespondentID, Field1 as Country
        FROM myTable
        UNION
        SELECT RespondentID, Field2 as Country
        FROM myTable
        UNION
        ....
        UNION
        SELECT RespondentID, Fieldn as Country
        FROM myTable) t
      WHERE Country IS NOT NULL
    

    【讨论】:

    • 此查询的结果还将包含所有NULL 单元格的行。
    • 耶!谢谢,这很好,很简单,很容易在其他桌子上复制。也许最后一个问题,事实证明没有人在安道尔招聘人员,所以在这种特殊情况下,该列始终为 Null,我认为这将为每个响应者 ID 返回一个 Null 值: RespondentID country 2500979822 NULL 2500979822 Deutschland 2501468008 NULL 2501468008 Deutschland 2501468008 Vereinigte Staaten von Amerika 2501486940 NULL 2501486940 匈牙利现阶段有没有办法过滤掉 Null?
    • 可以在包装查询中使用 WHERE 进行修复
    • 更新了排除 NULL 的答案
    • 我很厚,你当然可以! :) 我想我只是盯着这个数据太久了!
    【解决方案2】:

    使用UNPIVOT 标准化您的表格:

    SELECT u.RespondentID, u.Country
    FROM @source
    UNPIVOT (Country FOR c IN (Andorra, Austria, Belgium, Cyprus, Denmark, Finland, France)) u
    

    @source 是一个表格,其中包含从 Excel 工作表导入的数据。

    测试数据:

    DECLARE @source TABLE
    (
        RespondentID BIGINT NOT NULL,
        Andorra VARCHAR(25),
        Austria VARCHAR(25),
        Belgium VARCHAR(25),
        Cyprus VARCHAR(25),
        Denmark VARCHAR(25),
        Finland VARCHAR(25),
        France VARCHAR(25)
    )
    
    INSERT INTO @source 
    (RespondentID, Andorra,   Austria, Belgium,  Cyprus,   Denmark,    Finland,   France)
    VALUES
    (2546078180,   'Andorra', NULL,    NULL,     'Cyprus', NULL,       NULL,      NULL),
    (2546077668,   NULL,      NULL,    'Belgium', NULL,    NULL,       NULL,      NULL),
    (2546077120,   NULL,      NULL,    NULL,      NULL,    'Denkmark', 'Finland', NULL)
    
    -- I assume that 'NULL' cell values from your Excel sheet become NULL during the import.
    

    输出:

    RespondentId         Country
    -------------------- -------------------------
    2546078180           Andorra
    2546078180           Cyprus
    2546077668           Belgium
    2546077120           Denkmark
    2546077120           Finland
    

    【讨论】:

    • 谢谢,我也会看看这个解决方案。 :)
    • 这也是一个很好的解决方案,我以前从未使用过 unpivot,所以也许你可以帮助我快速提问?原始数据的国家/地区列中的某些答案因语言而异,例如德国可以包含德国或德国。有没有办法在运行它的同时将列中非 null 的任何内容转换为特定值?
    • @user3318535:是的,这很简单:您可以SELECT 单元格的列名(u.c),而不是SELECT-ing 单元格的值(u.Country):@987654331 @。 (说明:UNPIVOT 子句的Country FOR c 部分本质上意味着c 接收单元格的列名——这就是为什么它后面跟着一个列名的IN (…) 枚举——而Country 接收单元格的值。由于您的列名称是固定语言,您可以简单地选择这些而不是单元格值本身。)
    • @user3318535:另一种解决方案是创建一个额外的查找表lookup,其中包含OriginalValueTranslatedValue 两列以及('Germany', 'DE'), ('Deutschland', 'DE'), ('Allemagne', 'DE'), ('France', 'FR'), 'Francia', 'FR'), … 等值。然后JOIN 将它放到你的未透视表ON u.Country = lookup.OriginalValue;最后,SELECT …, lookup.TranslatedValue 而不是 u.Country
    • Genius,u.c 为我做了这件事,尽管查找表也很好。改成最佳答案。谢谢一百万!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    相关资源
    最近更新 更多