web-dev-qa-db-ja.com

MySQL:クエリから列名またはエイリアスを取得する

SHOW COLUMNSコマンドを要求していません。

Heidisqlと同様に機能するアプリケーションを作成します。このアプリケーションでは、SQLクエリを指定でき、実行すると、クエリ結果を表す行と列を含む結果セットが返されます。結果セットの列名は、SQLクエリで定義されている選択した列と一致する必要があります。

My Pythonプログラム(MySQLdbを使用))では、クエリは行と列の結果のみを返し、列名は返しません。次の例では、列名はexttotalsize、およびfilecount。SQLは最終的にプログラムの外部になります。

この機能を実現するための唯一の方法は、独自のSQLパーサーロジックを作成して、選択した列名を抽出することです。

提供されたSQLの列名を取得する簡単な方法はありますか?次に、クエリが返す列の数を知る必要がありますか?

# Python

import MySQLdb

#===================================================================
# connect to mysql
#===================================================================

try:
    db = MySQLdb.connect(Host="myhost", user="myuser", passwd="mypass",db="mydb")
except MySQLdb.Error, e:
    print "Error %d: %s" % (e.args[0], e.args[1])
    sys.exit (1)

#===================================================================
# query select from table
#===================================================================

cursor = db.cursor ()   

cursor.execute ("""\
     select ext,
        sum(size) as totalsize,
        count(*) as filecount
     from fileindex
    group by ext
    order by totalsize desc;
""")

while (1):
    row = cursor.fetchone ()
    if row == None:
        break
    print "%s %s %s\n" % (row[0], row[1], row[2])

cursor.close()
db.close()      
54
panofish

cursor.descriptionは、それぞれの[0]が列ヘッダーであるタプルのタプルを提供します。

num_fields = len(cursor.description)
field_names = [i[0] for i in cursor.description]
193
user625477

これはthefreemanと同じですが、リストと辞書の内包表記を使用したPython的な方法です。

columns = cursor.description 
result = [{columns[index][0]:column for index, column in enumerate(value)} for value in cursor.fetchall()]

pprint.pprint(result)
24
James

@Jamesの回答と同様に、よりPython的な方法は次のとおりです。

fields = map(lambda x:x[0], cursor.description)
result = [dict(Zip(fields,row))   for row in cursor.fetchall()]

結果のマップを含む単一の列を取得できます。

extensions = map(lambda x: x['ext'], result)

またはフィルター結果:

filter(lambda x: x['filesize'] > 1024 and x['filesize'] < 4096, result)

または、フィルター処理された列の値を累積します。

totalTxtSize = reduce(
        lambda x,y: x+y,
        filter(lambda x: x['ext'].lower() == 'txt', result)
)
10
juandesant

私はこれがあなたが必要なことをするべきだと思います(上記の答えに基づいて構築します)。私はそれを書くためのもっとパイソンな方法があると確信していますが、一般的なアイデアを得る必要があります。

cursor.execute(query)
columns = cursor.description
result = []
for value in cursor.fetchall():
    tmp = {}
    for (index,column) in enumerate(value):
        tmp[columns[index][0]] = column
    result.append(tmp)
pprint.pprint(result)
7
thefreeman

_MySQLdb.cursors.DictCursor_を使用することもできます。これは結果セットをpython辞書のリストpython辞書に変換しますが、特別なカーソルを使用するため、技術的に受け入れられた回答よりも移植性が低くなります。これを使用する編集済みの元のコードを次に示します。

_#!/usr/bin/python -u

import MySQLdb
import MySQLdb.cursors

#===================================================================
# connect to mysql
#===================================================================

try:
    db = MySQLdb.connect(Host='myhost', user='myuser', passwd='mypass', db='mydb', cursorclass=MySQLdb.cursors.DictCursor)
except MySQLdb.Error, e:
    print 'Error %d: %s' % (e.args[0], e.args[1])
    sys.exit(1)

#===================================================================
# query select from table
#===================================================================

cursor = db.cursor()

sql = 'SELECT ext, SUM(size) AS totalsize, COUNT(*) AS filecount FROM fileindex GROUP BY ext ORDER BY totalsize DESC;'

cursor.execute(sql)
all_rows = cursor.fetchall()

print len(all_rows) # How many rows are returned.
for row in all_rows: # While loops always make me shudder!
    print '%s %s %s\n' % (row['ext'], row['totalsize'], row['filecount'])

cursor.close()
db.close()  
_

たとえば、最初の行の列数をカウントするlen(row[0])、列名のリスト(最初の行)のlist(row[0])などの標準辞書関数が適用されます。助けて!

5
Eugene

MySQLdbはそのAPI呼び出しの翻訳を実際には提供していないようです。関連するC API呼び出しは mysql_fetch_fields 、および そのためのMySQLdb変換はありません

2
Daniel DiPaolo

試してください:

cursor.column_names

mysqlコネクタバージョン:

mysql.connector.__version__
'2.2.9'
1
Amin

これは受け入れられた答えへの単なるアドオンです:

def get_results(db_cursor):
    desc = [d[0] for d in db_cursor.description]
    results = [dotdict(dict(Zip(desc, res))) for res in db_cursor.fetchall()]
    return results

ここで、dotdictは次のとおりです。

class dotdict(dict):
    __getattr__ = dict.get
    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

これにより、列名で値にはるかに簡単にアクセスできます。
userおよびnameを持つemailテーブルがあるとします:

cursor.execute('select * from users')
results = get_results(cursor)
for res in results:
  print(res.name, res.email)
1
MikeL

フィールドのタイトルを取得するためにこれを行うこともできます:

table = cursor.description
check = 0
for fields in table:
    for name in fields:
        if check < 1:
            print(name),
        check +=1
    check =0
0
Adam Rhoades