乘以列中的值

时间:2018-01-11 22:01:01

标签: python sqlite

我通过python 2.7使用sqlite3。

我有一个表格,我希望在C列中乘以列B相同的值。

如果这些值在不同的列中,那将更加简单 我可以使用

SELECT B, C1 *C2 FROM table1;

但是当我在一个专栏中成倍增加时,我迷失了。

例如,如果这是原始表

A   B      C
1   Mike   2.5
1   Susan  4.2
1   Patti  2.0
2   Susan  1.1
2   Patti  3.7
3   Mike   0.2

然后在B列中的托盘相同,它们在C列中的值相乘,所以我的输出将是

A      B
Mike   0.5
Susan  4.62
Patti  7.4

3 个答案:

答案 0 :(得分:0)

正如评论中指出的那样,在SQLite中创建乘法的聚合函数非常困难。但是,您可以使用itertools.groupby来执行组合和乘法操作,然后创建新表。这个答案利用上下文管理器和属性修饰器来创建一个干净的类调用:

import sqlite3
import itertools
class UpdateTable:
   def __init__(self, *args):
     self.__dict__ = dict(zip(['table', 'filename'], args))
     self.new_table = None
   @property
   def newtable(self):
      return self.new_table
   @newtable.setter
   def newtable(self, new_table_name):
      self.new_table = new_table_name
   def __enter__(self):
       data = map(lambda (a, b, c):[b, float(c)], list(sqlite3.connect(self.filename).cursor().execute('SELECT * FROM {}'.format(self.table))))
       self.new_data = [(a, reduce(lambda x, y:x[-1]*y[-1], list(b))) for a, b in itertools.groupby(sorted(data, key=lambda x:x[0]), key=lambda x:x[0])]
       return self
   def __exit__(self):
       conn = sqlite3.connect(self.filename)
       conn.execute('CREATE TABLE {} (A text, B float)'.format(self.new_table))
       conn.executemany('INSERT INTO {} VALUES (?, ?)'.format(self.new_table), self.new_data)
       conn.commit()
       conn.close()


with UpdateTable('table', 'db_file.db') as t:
   t.newtable = 'table2'

Python3要求functools reduce,并且与lambda元组解包不兼容。

Python3版本:

import functools
import sqlite3
import itertools
class UpdateTable:
   def __init__(self, *args):
     self.__dict__ = dict(zip(['table', 'filename'], args))
     self.new_table = None
   @property
   def newtable(self):
      return self.new_table
   @newtable.setter
   def newtable(self, new_table_name):
      self.new_table = new_table_name
   def __enter__(self):
      data = map(lambda x:[x[1], float(x[-1])], list(sqlite3.connect(self.filename).cursor().execute('SELECT * FROM {}'.format(self.table))))
      self.new_data = [(a, functools.reduce(lambda x, y:x[-1]*y[-1], list(b))) for a, b in itertools.groupby(sorted(data, key=lambda x:x[0]), key=lambda x:x[0])]
      return self
   def __exit__(self):
      conn = sqlite3.connect(self.filename)
      conn.execute('CREATE TABLE {} (A text, B float)'.format(self.new_table))
      conn.executemany('INSERT INTO {} VALUES (?, ?)'.format(self.new_table), self.new_data)
      conn.commit()
      conn.close()


with UpdateTable('table', 'db_file.db') as t:
   t.newtable = 'table2'

答案 1 :(得分:0)

仅使用Python,查看this answer。您可以按列B对查询进行排序,然后使用itertools.groupby将查询结果分组到数据包中,然后使用the reduce built-in处理这些数据包:

curs.execute("SELECT id, user, number FROM table WHERE condition() ORDER BY user")

for person, group in itertools.groupby(curs.fetchall(), lambda row: row[1]):
    product = reduce((lambda a,b: a*b), [r[2] for r in group])
    do_something_with(person, product)

答案 2 :(得分:0)

这是使用group_concat()和方便的分隔符的方法:

import sqlite3

db = sqlite3.connect(':memory:')
db.execute('create table t(A,B,C)')
db.execute('''
insert into t values
  (1,'Mike',2.5),
  (1,'Susan',4.2),
  (1,'Patti',2.0),
  (2,'Susan',1.1),
  (2,'Patti',3.7),
  (3,'Mike',0.2)
''')

for b,expr in db.execute('''select b,group_concat(c,'*') from t group by b'''):
  #print(f'{b:10s} {eval(expr):5.2f}')            #Python 3.6
  print('%-10s %5.2f' % (b,eval(expr)))            #Python 2.7