将具有太多值的行转换为列

时间:2016-05-24 22:20:55

标签: python mysql sql

假设我有这样的数据集。

ID  Item
1   A
2   B
3   A
1   C
2   B
2   B
1   A
3   B

实际数据集具有50K行和8.5K不同的Item值。

现在我想将行转换为每个Id的列,以便我们计算每个用户的每个项目的值。如下所示

ID  A   B   C
1   2   0   1
2   0   3   0
3   1   1   0

现在,如果我喜欢设置不。然后我可以在聚合语句的情况下对它们进行硬编码。

这样的东西
select ID, count(case when Item ='A' then 1 else Null end) A, 
count(case when Item='B' then 1 else Null end) B... and so on. 

但在这种情况下,我有8.5K独特的物品。这将是如上所述在sql中执行的太多任务。

我如何实现这一点是Sql和ii)Python。记住我有50K行和8.5k个独特的项目,所以python循环可能会有点慢。

但我的第一个目标是在sql中执行此操作,因为这是50K的示例数据。当数据变得越来越大时,sql仍然会保持良好状态,但是python会让我觉得变慢。在python中我也可以尝试一些代码。但是当数据超过50K时,再次python也会慢慢地

请告知

不使用Postgresql并使用HANA,因此Postgres特有的功能可能无效。请建议通用的sql方式。

3 个答案:

答案 0 :(得分:1)

如果您确实想在python中执行此操作,则应查看pandas

df = pd.DataFrame({
    'ID': [1, 2, 3, 1, 2, 2, 1, 3],
    'Item': ['A', 'B', 'A', 'C', 'B', 'B' , 'A', 'B']
})

pd.crosstab(df['ID'], df['Item'])

输出:

Item A  B   C
ID          
1   2   0   1
2   0   3   0
3   1   1   0

答案 1 :(得分:0)

对于SQL解决方案,如何使用SQL技术但是编写脚本呢?不确定它会如何保持,但如果你还没有尝试过,你可以试一试。 运行这样的东西来生成所需列的所有列的脚本:

select distinct 'sum(case when ITEM = ''' + ITEM + ''' then 1 else 0 end) ' + ITEM + ',' from YOUR_TABLE;

然后复制并粘贴结果以得出:

select 
  ID,
  **<COPY AND PASTE RESULTS HERE>**
from TEST_DATA
group by ID;

答案 2 :(得分:0)

此查询可以生成您想要的查询:

SELECT CONCAT("SELECT ID"
    , GROUP_CONCAT(DISTINCT 
        CONCAT(", COUNT(CASE Item WHEN '", Item, "' THEN 1 ELSE NULL END) AS `", Item, "`")
        ORDER BY Item
        )
    , "FROM `theTable` "
    , "GROUP BY ID"
  ) AS theQuery
FROM `theTable`
;

....但我只知道GROUP_CONCAT在MySQL中确实存在而在MSSQL中不存在;我不了解其他数据库系统。此外,在MySQL中,您需要通过在此查询之前添加类似

的语句来增加函数允许的最大长度
SET SESSION group_concat_max_len = 1000000;

...或更改服务器配置以使默认值最大值更大。 ......其中&#34; 1000000&#34;是一个足够大的长度,不会截断结果字符串。

如果查询太大以至于group_concat无论适合什么设置都不适合:您可以运行多个这些查询,使用WHERE来减少处理的Item值,以生成更小的&#34;,COUNT( ...),COUNT(&#34;列出;然后手动合并这些结果。

当然,即使这会生成查询想要的,我也不是肯定的,MySQL甚至会接受一个长的查询。