2009-12-02 3 views
4

일부 데이터가 있어야합니다. 224,000 개의 행이 SQLite 데이터베이스에 있습니다. 데이터 시각화 도구를 제공하기 위해 시계열 정보를 추출하고 싶습니다. 본질적으로, db의 각 행은 신기원 이후의 초 단위의 시간 - 날짜 그룹과 이에 대한 책임이있는 이벤트입니다 (다른 것들 중에서도 특히 중요하지 않음). 각 이름이 매주 DB에 얼마나 많은 이벤트가 있는지 추출하려고합니다. 간단한 충분SQLite 테이블 회전, SQL과 같은 setwise

:

SELECT COUNT(*), 
     name, 
     strf("%W:%Y", time, "unixepoch") 
    FROM events 
GROUP BY strf("%W:%Y", time, "unixepoch"), name 
ORDER BY time 

우리는 데이터의 약 육천 행을 얻을. 이제,

Name  23:2009  24:2009 25:2009 
fudge........23............6............19 
fish.........1.............0............12 
etc... 

: -

count   name  week:year 
23............ fudge.......23:2009 
etc... 

하지만 각 주에서 각 이름에 대한 행을하지 않으려는이 같은 각 이름에 대한 행, 각 주에 대한 열을 원하는 모니터링 프로세스는 69 주 동안 실행되었으며 고유 이름의 수는 502 개입니다. 따라서 분명히 모든 열을 하드 코딩하고 여전히 행을 줄이는 모든 솔루션에 관심이 많지 않습니다. 파이썬의 executemany()와 같이 많은 것을 반복하는 것을 포함하는 것에 대해서는 덜 신경 쓰지 만 필요하다면 받아 들일 수있다. SQL은 현명해야합니다.

+0

@yorksranter : 답변을 upvote하고 답변을 수락 하시겠습니까? –

+0

나는 명성 점수가 15 점이 아니다. – user106514

+0

@yorkstranter : 담당자가 더 높을 때 다시 방문 할 수있는 코드가 마음에 들면 괜찮습니다 .- –

답변

4

이런 경우에 좋은 접근법은 SQL을 복잡하고 이해하기 힘들고 유지하기가 어려운 시점으로 밀어 넣는 것이 아닙니다. SQL을 통해 편리하게 수행 할 수있는 작업을 수행하고 쿼리 결과를 Python으로 처리 할 수 ​​있습니다.

여기에 필자가 작성한 간단한 크로스 탭 생성기의 축소판 버전이 있습니다. 정식 버전은 행/열/총합을 제공합니다.

"group by"이 내장되어 있음을 알 수 있습니다. 원래의 사용 사례는 Python과 xlrd를 사용하여 Excel 파일에서 얻은 데이터를 요약하기위한 것입니다.

사용자가 제공하는 row_keycol_key은 예제와 같이 문자열 일 필요는 없습니다. 튜플 (예 : 귀하의 경우에 (year, week) - 또는 정수일 수 있습니다. 문자열 열 이름과 정수 정렬 키의 매핑이 있습니다.

import sys 

class CrossTab(object): 

    def __init__(
     self, 
     missing=0, # what to return for an empty cell. Alternatives: '', 0.0, None, 'NULL' 
     ): 
     self.missing = missing 
     self.col_key_set = set() 
     self.cell_dict = {} 
     self.headings_OK = False 

    def add_item(self, row_key, col_key, value): 
     self.col_key_set.add(col_key) 
     try: 
      self.cell_dict[row_key][col_key] += value 
     except KeyError: 
      try: 
       self.cell_dict[row_key][col_key] = value 
      except KeyError: 
       self.cell_dict[row_key] = {col_key: value} 

    def _process_headings(self): 
     if self.headings_OK: 
      return 
     self.row_headings = list(sorted(self.cell_dict.iterkeys())) 
     self.col_headings = list(sorted(self.col_key_set)) 
     self.headings_OK = True 

    def get_col_headings(self): 
     self._process_headings() 
     return self.col_headings 

    def generate_row_info(self): 
     self._process_headings() 
     for row_key in self.row_headings: 
      row_dict = self.cell_dict[row_key] 
      row_vals = [row_dict.get(col_key, self.missing) for col_key in self.col_headings] 
      yield row_key, row_vals 

    def dump(self, f=None, header=None, footer='',): 
     if f is None: 
      f = sys.stdout 
     alist = self.__dict__.items() 
     alist.sort() 
     if header is not None: 
      print >> f, header 
     for attr, value in alist: 
      print >> f, "%s: %r" % (attr, value) 
     if footer is not None: 
      print >> f, footer 

if __name__ == "__main__": 

    data = [ 
     ['Rob', 'Morn', 240], 
     ['Rob', 'Aft', 300], 
     ['Joe', 'Morn', 70], 
     ['Joe', 'Aft', 80], 
     ['Jill', 'Morn', 100], 
     ['Jill', 'Aft', 150], 
     ['Rob', 'Aft', 40], 
     ['Rob', 'aft', 5], 
     ['Dozy', 'Aft', 1], 
     # Dozy doesn't show up till lunch-time 
     ['Nemo', 'never', -1], 
     ] 
    NAME, TIME, AMOUNT = range(3) 
    xlate_time = {'morn': "AM", "aft": "PM"} 

    print 
    ctab = CrossTab(missing=None,) 
    # ctab.dump(header='=== after init ===') 
    for s in data: 
     ctab.add_item(
      row_key=s[NAME], 
      col_key= xlate_time.get(s[TIME].lower(), "XXXX"), 
      value=s[AMOUNT]) 
     # ctab.dump(header='=== after add_item ===') 
    print ctab.get_col_headings() 
    # ctab.dump(header='=== after get_col_headings ===') 
    for x in ctab.generate_row_info(): 
     print x 

출력 :

['AM', 'PM', 'XXXX'] 
('Dozy', [None, 1, None]) 
('Jill', [100, 150, None]) 
('Joe', [70, 80, None]) 
('Nemo', [None, None, -1]) 
('Rob', [240, 345, None]) 
1

내가 먼저 파이썬으로 처리를 게시 할 다음 쿼리

SELECT COUNT(*), 
     name, 
     strf("%W:%Y", time, "unixepoch") 
    FROM events 
GROUP BY strf("%W:%Y", time, "unixepoch"), name 
ORDER BY time 

을하고있다.

따라서 224,000 개 이상의 행에서 6,000 개가 넘는 행을 반복 할 필요가 없습니다. 6,000 개의 행을 메모리에 쉽게 저장할 수 있습니다 (Python으로 처리하기 위해). 나는 224,000 행을 메모리에 저장할 수 있다고 생각하지만 훨씬 많은 메모리가 필요하다.

그러나 새 버전의 sqlite는 집계 함수 group_concat을 지원합니다. 어쩌면이 기능을 SQL을 이용한 피봇 팅에 사용할 수 있습니까? 이전 버전을 사용하기 때문에 시도 할 수 없습니다.