sqlite如何优化第N个百分位数的查询

时间:2013-12-20 19:03:47

标签: python sql sqlite query-optimization

以下是一段代码,使用sqlite3 python module来获取表value中ID为itemid的项目的第N个百分位数history

def getNthPercentile(cursor, itemId, N=99.9):
    # get 99.9 percentile
    # find count of values
    cursor.execute("SELECT COUNT(value) FROM history WHERE itemid=?", [itemId])
    cnt = int(cursor.fetchone()[0])
    # offset gives us teh position of the value in sorted list that represents Nth percentile
    offset = int(cnt * (N / 100) - 1)
    # sort values
    cursor.execute("SELECT value FROM history WHERE itemid = ? ORDER BY value ASC LIMIT 1 OFFSET ?", [itemId, offset])
    percentile = float(cursor.fetchone()[0]);
    l.debug('itemId=%d, count=%d, offset=%d, %fth percentile=%f' % (itemId, cnt, offset, N, percentile))
    # find the (count * pctlVal)th item in sorted values
    return percentile

cursor = getDbCursor()
for itemId in listOfItemIds:
    print 'Nth percentile for %d is %f' % (itemId, getNthPercentile(cursor, itemId))

问题是:

  • 是否可以在单个查询中执行此操作?
  • 是否可以在单个查询中为itemId(而不是一次)列表执行此操作?

1 个答案:

答案 0 :(得分:1)

我认为在单个查询中不可能。 使用cursor.executescript在一次执行中调用这两个语句,并将cnt存储为sqlite中的临时变量。

cursor.executescript("SELECT COUNT(value) AS itemcount FROM history WHERE itemid=?; \
    SELECT value FROM history WHERE itemid = ? ORDER BY value ASC LIMIT 1 OFFSET itemcount * (? / 100) - 1)", \
    [itemId, itemId, percentile])

^^我根本没有测试过这个,但它应该是关闭的。

我不知道某种形式的executecript是否可以与executemany结合使用。因此,您可能需要为每个itemid决定两个executemanys或executioncripts。