Преобразование wide в длинный формат в sql server и dataframe содержит около 1000 столбцов — Оптимизировать

#python #sql #sql-server

#python #sql #sql-server

Вопрос:

У меня есть dataframe df в широком формате и содержит около 1000 столбцов. Мне нужно преобразовать это в длинный формат

Пример таблицы:

  Date   TLRA_Equity  KAMN_Equity  B_Equity  ARNC_Equity RC_Equity DAR_Equity
1/1/2000  10              20        30          40        50          60
2/1/2000  15              25        35          45        55          65
3/1/2000  17              27        37          47        57          67
  

Я могу преобразовать это в длинный формат с помощью dataframe melt и вставить в таблицу на python с помощью приведенного ниже кода

         df = df.melt(id_vars = 'Date')
        query = "insert into table values (?,?,?)"
        cursor.executemany(query, df.values.tolist())
  

Данные в длинном формате:

   investment        variable      value  
 1/1/2000      TLRA_Equity       10    
 1/1/2000      KAMN_Equity       20    
 1/1/2000      B_Equity          30 
 1/1/2000      ARNC_Equity       40
  

Но после преобразования длинного формата требуется много времени для обновления до table. Есть ли какой-либо способ вставить в таблицу базы данных в широком формате и скрыть ее в длинном формате в sql, чтобы ускорить процесс.

Вывод с помощью решения ‘John Cappelletti’

    Date         Item          Value
   1/1/2000     Date           1/1/2000
   1/1/2000     TLRA_x0020_Equity   10
   1/1/2000     KAMN_x0020_Equity   20
   1/1/2000     B_x0020_Equity      30
   1/1/2000     ARNC_x0020_Equity   40
  

Комментарии:

1. Не существует понятия длинного и короткого формата. То, что у вас вверху, денормализовано, и вы его нормализуете.

Ответ №1:

Очевидно, что Unpivot был бы более производительным, но вот подход, который будет «динамически» отключать ваши данные без необходимости использования динамического SQL.

Плюсом является то, что вам не придется указывать 1000 столбцов.

Пример

 Select A.Date
      ,C.*
 From  YourTable A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item  = xAttr.value('local-name(.)', 'varchar(100)')
                      ,Value = xAttr.value('.','varchar(max)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)','varchar(100)') not in ('Date')
             ) C
  

ВОЗВРАТ

введите описание изображения здесь

Редактировать

  ...
,Item  = replace(xAttr.value('local-name(.)', 'varchar(100)'),'_x0020_',' ')
 ...
  

Комментарии:

1. Я получаю другой результат. Можете ли вы, пожалуйста, проверить, какую ошибку я делаю? Вывод обновлен в вопросе.

2. @ArvinthKumar У вас есть пробелы в именах столбцов? Если это так, XML заменит пробел на x0020

3. Отлично, все работает нормально. Большое спасибо за вашу помощь!!