【问题标题】:How to use a list/array of values as column name in select statement?如何在选择语句中使用值列表/数组作为列名?
【发布时间】:2020-03-09 17:57:47
【问题描述】:

假设我有 3 个用于构建新查询的数据列表。我需要获取这些数据列表并返回那些发现东西的列表的值。

所以我的问题是:

有没有标准的方法来获取列表并将其用作列?

我需要使用多个列表作为列,其中一列是“JOIN ON”或“WHERE IN”部分。

我的第一个查询的结果用于构建我的 3 列表。

假设我找回了这些数据:

[[ID, TYPE, OTHER],
 [1, C, S], 
 [2, C, O],
 [3, D, D],
 [4, D, H]]

然后将该表/二维数组转换为以下 Python 列表:

[1, 2, 3, 4]
[C, C, D, D]
[S, O, D, H]

现在我想将这两个列表用作 select 语句中的列,如下所示:

select [C, C, D, D] as TYPE # These 2 list are needed to return in the correct order
      ,[S, O, D, H] as OTHER  # as it relates to [1, 2, 3, 4] in the WHERE.
      ,table.value
      ,table.color
From table
where table.value in [1, 2, 3, 4]  # one list is used to deal with the where 

table 包含 2 列:

VALUE    COLOR
1        Red
2        Green
3        Blue
4        Black

结果应如下所示:

TYPE    OTHER    VALUE    COLOR
C       S        1        Red
C       O        2        Green
D       D        3        Blue
D       H        4        Black

【问题讨论】:

  • 您使用的是 MS SQL Server 还是 Oracle?
  • @jarlh 两者。我的一些查询将直接在 SQL Server 上进行,而一些查询将针对链接的 Oracle 服务器使用OPENQUERY。我可以获取具有单个值作为列的数据,但我需要能够使用值列表来执行此操作。否则我将不得不构建 20 个 Union 语句,我真的不认为这是有效的。
  • 不确定如何在 python 中执行此操作,但您所描述的是 sql server 中的表值参数。
  • @SeanLange 这必须传入一个查询字符串,该字符串使用 ODBC 标准驱动程序通过 pyodbc 发送到 SQL Server。同样,我可以使用单个值而不是列表来执行此操作。
  • 好吧,正如您发现的那样,您不能在标准字符串中传递值数组。你有一个二维数组。您可以使用字符串拆分器并传入分隔列表。但是您将需要一个返回每个元素的序号位置的函数,这样您就可以重新组合一个分隔列表并正确排列这些值。这是其中一个很好的例子。 sqlservercentral.com/articles/…

标签: python sql sql-server oracle


【解决方案1】:

更新:

1、将表格转换为3个列表:

import cx_Oracle
import pandas

db = cx_Oracle.connect('*******', '********', '*******')
conn = db.cursor()

sql_test = '''SELECT * FROM TEST'''

sql_table = '''SELECT * FROM "TABLE" '''

df_test = pandas.read_sql_query(sql_test,db)
df_table = pandas.read_sql_query(sql_table,db)

ser_aggCol=df_test.aggregate(lambda x: [x.tolist()], axis=0).map(lambda x:x[0])

print(ser_aggCol, sep='\n', end='\n\n\n')

print(ser_aggCol['ID'])
print(ser_aggCol['TYPE'])
print(ser_aggCol['OTHER'])

输出:

2、使用while循环逐行拼接数据帧。

sql_max = '''SELECT MAX(ID) FROM TEST'''
conn.execute(sql_max)
max_id = 0
for result in conn:
    max_id = result[0]

print(max_id)

i = 0
sql_first_row = '''select \'''' + ser_aggCol['TYPE'][i] + '''\' as TYPE, \'''' + ser_aggCol['OTHER'][i] + '''\' AS OTHER, VALUE, COLOR FROM "TABLE" WHERE VALUE = '''+ str(ser_aggCol['ID'][i])
df_result = pandas.read_sql_query(sql_first_row,db)

while i + 1 <= max_id - 1:
    new_sql = '''select \'''' + ser_aggCol['TYPE'][i+1] + '''\' as TYPE, \'''' + ser_aggCol['OTHER'][i+1] + '''\' AS OTHER, VALUE, COLOR FROM "TABLE" WHERE VALUE = '''+ str(ser_aggCol['ID'][i+1])
    df_new = pandas.read_sql_query(new_sql, db)
    df_result = pandas.concat([df_result,df_new])
    i = i + 1

print(df_result)

输出:


原帖:

我的做法是:

1、将SQL结果读入dataframes

pandas.read_sql_query(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, chunksize=None)

2、使用 Pandas 加入数据框

DataFrame.join(self, other, on=None, how='left', lsuffix='', rsuffix='', sort=False)


测试:

我的新 PC 上没有 SQL Server 客户端,所以我只在 Oracle 中创建了这两个表。您只需在 Python 中添加 SQL Server 连接。 如果你被困在这里,请告诉我。

在 Oracle 中创建了两个表:

测试:

表格:

然后是 Python:

import cx_Oracle
import pandas

db = cx_Oracle.connect('********', '********', '********')
conn = db.cursor()

sql_test = '''SELECT * FROM TEST'''

sql_table = '''SELECT * FROM "TABLE" '''

df_test = pandas.read_sql_query(sql_test,db)
df_table = pandas.read_sql_query(sql_table,db)

print(df_test) 
print(df_table)

print(df_test.set_index('ID').join(df_table.set_index('VALUE')))

输出:

   ID TYPE OTHER
0   1    C     S
1   2    C     O
2   3    D     D
3   4    D     H

   VALUE  COLOR
0      1    Red
1      2  Green
2      3   Blue
3      4  Black

ID  TYPE OTHER  COLOR                  
1     C     S    Red
2     C     O  Green
3     D     D   Blue
4     D     H  Black

【讨论】:

  • 我更新了我的问题以提供更多背景信息以及我计划如何使用这些数据。我将不得不等到明天恢复工作才能针对外部服务器测试代码。
  • @Mike-SMT 我刚刚更新了我的答案。如果您有任何问题,请告诉我。
  • 有趣的是df_test.set_index('ID').join(df_table.set_index('VALUE'))JOIN ON基本一样。我在这里担心的是,它看起来是 2 个表之间的全表扫描,这将是 spool 空间的高昂代价。拉下所有数据是行不通的。我需要以某种方式将 say TEST 列作为选择语句发送到 Oracle 服务器,这样它只会拉回我需要的值。
  • @Mike-SMT,你能测试一下吗?据我所知,pandas 现在拥有最快的内存数据库连接运算符之一。
  • @Mike-SMT,另外,您可以在加入表格后使用 DataFrame.where() 来提取您需要的数据。
【解决方案2】:

好的,这是我必须采用的解决方案。

我不会在客户端管理数据,而是在 SQL Server 上创建一个新数据库,然后该工具将与之交互的所有需要​​的表。

然后我将让程序根据使用该工具的用户在每个表中插入和删除行。

获取用户名很简单:

import os

print(os.getlogin())

因为在 99% 的情况下,每次为 10 个用户中的任何一个用户添加和删除的行数都少于 100 行,这足以有效地处理工作。

此解决方案比我当前的 UNION 方法效率更高,并且还允许每个用户仅查看和使用与其登录相关的数据。

看到每个表的总行数可能永远不会超过 10,000 行,我认为即使没有可使用的主键,这也不是什么大问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2020-04-11
    相关资源
    最近更新 更多