簡體   English   中英

根據具有多個值的參數過濾SQL查詢

[英]Filtering SQL query based on parameters with more than one value

我正在嘗試構建一個需要用兩個參數(2列)過濾的SQL,第二列需要匹配多個值。

下面給出的是我到目前為止構建的SQL(感謝Martijn Pieters的幫助)

import psycopg2
import pandas as pd
import datetime

# Connecting to db

con = psycopg2.connect(db_details)
cur = con.cursor()
cur.execute("select * from sales limit 10")
rows = cur.fetchall()

params = {'earliest': datetime.datetime.today() - datetime.timedelta(days=7),
      'store_name': 'store_1', 'store_2'}

df = pd.read_sql("""
     select store_name,count(*) from sales 
     where created_at >= %(earliest)s
     and store_name = %(store_name)s""",
 params=params, con=con)

上面的SQL有一個date參數,該參數在where子句中使用,我又添加了一個參數,即store_name ,其中行與兩個值之一匹配。

想知道如何將這個附加參數添加到現有查詢中。

我試圖創建一個參數(類似於日期過濾器)並將其傳遞給現有查詢,但是當我給它兩個值時會出現語法錯誤:

    'store_name': 'store_1', 'store_2'}
                                      ^
SyntaxError: invalid syntax

指向params字段。

您有兩個問題:

  • 您使用了無效的Python語法; 字典中的逗號分隔鍵值對,因此'store_2'字符串將是另一個鍵值對,但缺少: value部分。 如果要使用多個字符串定義一個值,則必須在其中使用元組或列表,如果您明確使用(...)[...]將該語法與key: value, key: value分開key: value, key: value表示法:

     params = { 'earliest': datetime.datetime.today() - datetime.timedelta(days=7), 'store_name': ('store_1', 'store_2'), # tuple with two values } 
  • 一般來說,SQL參數只能使用單個值 只能給store_name參數一個值,而不是一個值序列。 這是因為SQL參數是SQL查詢和該查詢中要使用的動態值之間的橋梁,而這些參數旨在充當每個單獨的動態值的占位符。

    也就是說, psycopg2專門支持元組 ,但這是大多數Python數據庫庫的例外。

    接下來,如果要過濾匹配'store_1''store_2' ,則正確的SQL語法將是使用兩個store_name = ...測試,在它們之間使用OR並將其括在括號中(以使該部分與date分開)測試,並使用AND將其連接到商店名稱測試), 使用store_name IN ('store_1', 'store_2') IN測試將列名與(...)括號中列出的多個值進行比較。

假設您在此處使用psycopg2 ,則可以不用引用元組值的store_name鍵,但是您確實需要對查詢使用IN

params = {
    'earliest': datetime.datetime.today() - datetime.timedelta(days=7),
    'store_name': ('store_1', 'store_2')
}

df = pd.read_sql("""
     SELECT store_name, count(*) FROM sales 
     WHERE created_at >= %(earliest)s
     AND store_name IN %(store_name)s""",
     params=params, con=con)

單獨說明: pd.read_sql()函數[明確指出在使用DBAPI連接時僅支持sqlite](如果為DBAPI2對象,則僅支持sqlite3):

如果是DBAPI2對象,則僅支持sqlite3。

您正在使用這樣的對象; 大多數Python數據庫適配器都是DBAPI2庫; DBAPI2是此類庫Python標准

您實際上應該改用SQLAlchemy連接字符串 您的代碼恰好工作,因為你永遠不會嘗試任何數據寫回到數據庫和psycopg連接和光標對象是與sqlite3的庫版本大體兼容,但你可能會遇到的道路問題。

我不明白為什么這行不通:

params = {'earliest': datetime.datetime.today() - datetime.timedelta(days=7),
          'store_name': '<put what you want here>'}

df = pd.read_sql("""
         select store_name,count(*) from sales 
         where created_at >= %(earliest)s
         and store_name = %(store_name)s""",
     params=params, con=con)

因為要兩個商店,所以有點復雜。

這應該工作:

params = {'earliest': datetime.datetime.today() - datetime.timedelta(days=7),
          'store_names': ','.join(('store_1', 'store_2'))}

df = pd.read_sql("""
         select store_name,count(*) from sales 
         where created_at >= %(earliest)s
         and store_name in (%(store_names)s)""",
     params=params, con=con)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM