2015-11-05 6 views
0

Представьте таблицу, в которой первичная информация определяется по дате и имени.Pivot in SQLAlchemy

|Date|Name|Value| 
|D1 | A| 2| 
|D1 | B| 3| 
|D2 | A| 3| 
|D2 | C| 1| 

Как бы один написать SQLAlchemy запрос дающую пары (дата, значение), где значения являются все значения для всех имен на эту дату? Длина кортежа значений будет len(distinct(Name)), а отсутствующие значения будут содержать некоторое значение дозорного значения (например, None).

i.e. 
[ 
(D1, 2, 3, None), 
(D2, 3, None, 1), 
... 
] 

Я не прошу полного ответа здесь, чтобы заставить меня одобрить. Если вы можете сказать мне, какие понятия искать/читать в документации (или действительно, укажите мне что-нибудь полезное или связанное), я (попробую) сам разобраться и опубликовать обновление. не

[Нет панды решения пожалуйста]

легкий ответ загрузить запрос в длинной форме и сделать поворот в NumPy с использованием numpy.searchsorted, но если представленный ответ использует это, я был бы заинтересован в некоторых для сравнения с простым решением.

+0

Что определяет положение определенного имени в кортеже? То есть почему A в позиции 1, позиции B 2 и т. д.? – codeape

+0

Предпочтительно, чтобы они были упорядочены в соответствии со списком, который я мог бы предоставить (т. Е. Произвольным порядком, насколько нам известно). – frickskit

+0

Ваша проблема похожа на http://stackoverflow.com/questions/2089661 – SGP

ответ

5

Я бы порекомендовал не делать это на стороне SQL Server, если у вас нет большого количества данных (и даже в этом случае я не уверен, что это оказывает значительное положительное влияние на производительность).

Вместо этого используют различные инструменты, где они выделяются:

  • MS-SQL (или другой СУБД) для хранения данных
  • SQLAlchemy для вставки/запроса, что данные
  • numpy подпрограммы или pandas.pivot для поворота данных

Код ниже является автономным, работает (с sqlite) и показывает, как сделать g et к окончательному результату, который вы хотите:

from sqlalchemy import create_engine, Column, Integer, String 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 
import pandas as pd 

_db_uri = 'sqlite:///:memory:' 
engine = create_engine(_db_uri, echo=True) 
Session = sessionmaker(bind=engine) 

Base = declarative_base(engine) 

class MyTable(Base): 
    __tablename__ = 'my_table' 
    id = Column(Integer, primary_key=True) 
    date = Column(String) 
    name = Column(String) 
    value = Column(Integer) 

def _test(): 
    Base.metadata.drop_all(engine) 
    Base.metadata.create_all(engine) 
    session = Session() 

    def _add_test_data(): 
     rows = [ 
      MyTable(date="D1", name="A", value=2), 
      MyTable(date="D1", name="B", value=3), 
      MyTable(date="D2", name="A", value=3), 
      MyTable(date="D2", name="C", value=1), 
     ] 
     session.add_all(rows) 
     session.commit() 

    # create test data 
    _add_test_data() 

    # use `sa` to query data from the database 
    # q = session.query(MyTable) # all columns 
    q = session.query(MyTable.date, MyTable.name, MyTable.value) # explicit 

    # read data into pandas directly from the query `q` 
    df = pd.read_sql(q.statement, q.session.bind) 
    print(df) 

    # pivot the results 
    df_pivot = df.pivot(index="date", columns="name", values="value") 
    print(df_pivot) 


if __name__ == '__main__': 
    _test() 
+0

Прости, пожалуйста, никаких панд. – frickskit

+0

@frickskit почему ненавижу панды :) Я бы сказал, что панды идеально подходят для этой любопытной работы – WoodChopper

+1

Я просто не могу ее использовать, я согласен, что это полезно и приятно :) – frickskit