来自Pandas的Sqlite的NTILE给出了OPERATIONAL ERROR

时间:2016-06-01 21:50:03

标签: python sqlite pandas

我正在尝试使用NTILE函数从pandas查询SQLite数据库,但我没有成功,即使我已多次重新检查语法。

下面的自包含示例。 设置:

import pandas as pd
from sqlalchemy import create_engine
disk_engine = create_engine('sqlite:///test.db')

marks = pd.DataFrame({'StudentID': ['S1', 'S2', 'S3', 'S4', 'S5'],
                      'Marks': [75, 83, 91, 83, 93]})
marks.to_sql('marks_sql', disk_engine, if_exists='replace')

现在尝试使用NTILE:

q = """select StudentID, Marks, NTILE(2) OVER (ORDER BY Marks DESC)
        AS groupexample FROM marks_sql"""
pd.read_sql_query(q, disk_engine)

回溯很长,但它的主要部分是:

OperationalError: near "(": syntax error
OperationalError: (sqlite3.OperationalError) near "(": syntax error [SQL: 'select StudentID, Marks, NTILE(2) OVER (ORDER BY Marks DESC)\n        AS groupexample FROM marks_sql']

谢谢!

2 个答案:

答案 0 :(得分:2)

SQLITE中没有somehow_create_an_instance_of功能

给我同样的错误,需要使用更复杂的查询或函数来创建

Here is a list of unsupported analytical functions在SQLITE

中不可用

NTILE就是其中之一

优化器首先进入查询内部以查找NTILE () OVER,它认为这是一个列名,期望OVER遵循列名,所以给你这个错误。

复制NTILE试试这个:

(

为了以这样的方式执行此操作,即表格的大小可以增加并且此技术仍然适用,我们会做一些事情:

首先我们按select * , case when (select count(*)+0.0 from marks_sql b where table.Marks >= b.Marks) /(select count(*) from marks_sql ) >0.5 then 1 else 2 end from marks_sql; 订购表格(基本上是创建排名)。这会计算具有更高或相等Marks的行:

Marks

我们添加select count(*)+0.0 from marks_sql b where table.Marks >= b.Marks --rank of Mark 使这个数字成为一个浮点数,这样我们的分数就可以用于下一步。

然后我们取等级并除以总行数

0.0

这为我们提供了分数范围内的分布,即每个学生的百分位数。但我们并不关心每个确切的百分位数,我们关心的是select count(*) from marks_sql -- row count 或者它们是否属于上半部分。

这就是NTILE(2)声明发挥作用的地方。如果学生的百分位数超过50%,则他们属于排名第50的百分位数。其他人都属于#2组。

答案 1 :(得分:1)

Window functions 自版本 3.25.0 (2018-09-15) 起在 SQLite 中受支持。 ntile(N) 是支持的窗口函数之一:

<块引用>

参数 N 作为整数处理。此函数将分区尽可能均匀地划分为 N 个组,并按照 ORDER BY 子句定义的顺序或以其他任意顺序为每个组分配一个介于 1 和 N 之间的整数。如有必要,首先出现更大的群体。此函数返回分配给当前行所属组的整数值。

您可以通过以下方式测试与您的 Python 链接的 libsqlite3 版本:

python -c "import sqlite3; print(sqlite3.sqlite_version)"

例如:

  • Ubuntu Xenial

    $ docker run --rm -it ubuntu:xenial
    # apt update 
    # apt install -y python3
    # python3 -c "import sqlite3; print(sqlite3.sqlite_version)"
    3.11.0
    
  • Debian Buster 上的官方 Python Docker 映像

    $ docker run --rm -it python:3.6-buster \
        python3 -c 'import sqlite3; print(sqlite3.sqlite_version)'
    3.27.2
    

并且您的查询在具有窗口函数支持的 SQLite 版本上运行良好:

>>> import sqlite3
>>> import pandas
>>> 
>>> conn = sqlite3.connect(':memory:')
>>> marks = pandas.DataFrame({
...     'StudentID': ['S1', 'S2', 'S3', 'S4', 'S5'],
...     'Marks': [75, 83, 91, 83, 93]
... })
>>> marks.to_sql('marks_sql', conn, if_exists='replace')
>>> 
>>> sql = '''
...     SELECT StudentID, Marks, NTILE(2) OVER (ORDER BY Marks DESC) g
...     FROM marks_sql
... '''
>>> pandas.read_sql_query(sql, conn)
  StudentID  Marks  g
0        S5     93  1
1        S3     91  1
2        S2     83  1
3        S4     83  2
4        S1     75  2