19

MySQL が Python を使用してコンソールに出力するのと同じ方法で、MySQL クエリの結果を出力する最も簡単な方法は何ですか? たとえば、次のようなものを取得したいと思います。

+---------------------+-----------+---------+
| font                | documents | domains |
+---------------------+-----------+---------+
| arial               |     99854 |    5741 |
| georgia             |     52388 |    1955 |
| verdana             |     43219 |    2388 |
| helvetica neue      |     22179 |    1019 |
| helvetica           |     16753 |    1036 |
| lucida grande       |     15431 |     641 |
| tahoma              |     10038 |     594 |
| trebuchet ms        |      8868 |     417 |
| palatino            |      5794 |     177 |
| lucida sans unicode |      3525 |     116 |
| sans-serif          |      2947 |     216 |
| times new roman     |      2554 |     161 |
| proxima-nova        |      2076 |      36 |
| droid sans          |      1773 |      78 |
| calibri             |      1735 |      64 |
| open sans           |      1479 |      60 |
| segoe ui            |      1273 |      57 |
+---------------------+-----------+---------+
17 rows in set (19.43 sec)

注意:各列の最大幅はアプリオリにはわかりませんが、テーブルを2回調べずにそれができるようにしたいと考えています。各列のクエリ length() に追加する必要がありますか? メモリや処理時間に深刻な影響を与えないように、MySQL はどのようにそれを行うのでしょうか?

編集

質問に関連しているとは思いませんでしたが、これは私が送信したクエリです。

SELECT font.font as font,count(textfont.textid) as documents, count(DISTINCT td.domain) as domains
FROM textfont 
RIGHT JOIN font
ON textfont.fontid = font.fontid
RIGHT JOIN (
        SELECT text.text as text,url.domain as domain, text.textid as textid 
        FROM text 
        RIGHT JOIN url 
        ON text.texturl = url.urlid) as td 
ON textfont.textid = td.textid
WHERE textfont.fontpriority <= 0 
AND textfont.textlen > 100
GROUP BY font.font 
HAVING documents >= 1000 AND domains >= 10
ORDER BY 2 DESC;

そして、これは私が使用するpythonコードです:

import MySQLdb as mdb

print "%s\t\t\t%s\t\t%s" % ("font","documents","domains")
res = cur.execute(query , (font_priority,text_len,min_texts,min_domains))
for res in cur.fetchall():
    print "%s\t\t\t%d\t\t%d" % (res[0],res[1],res[2])

しかし、このコードは幅が異なるため、乱雑な出力を生成します。

4

6 に答える 6

27

外部ライブラリは必要ありません。は、列名とともにデータを出力します。列名が必要ない場合は、'columns' 変数を含むすべての行を削除できます。

sql = "SELECT * FROM someTable"
cursor.execute(sql)
conn.commit()
results = cursor.fetchall()

widths = []
columns = []
tavnit = '|'
separator = '+' 

for cd in cursor.description:
    widths.append(max(cd[2], len(cd[0])))
    columns.append(cd[0])

for w in widths:
    tavnit += " %-"+"%ss |" % (w,)
    separator += '-'*w + '--+'

print(separator)
print(tavnit % tuple(columns))
print(separator)
for row in results:
    print(tavnit % row)
print(separator)

これは出力です:

+--------+---------+---------------+------------+------------+
| ip_log | user_id | type_id       | ip_address | time_stamp |
+--------+---------+---------------+------------+------------+
| 227    | 1       | session_login | 10.0.0.2   | 1358760386 |
| 140    | 1       | session_login | 10.0.0.2   | 1358321825 |
| 98     | 1       | session_login | 10.0.0.2   | 1358157588 |
+--------+---------+---------------+------------+------------+

マジックは各行の 3 列目にありますcursor.description(コードで呼び出さcd[2]れます)。この列は、最長値の文字数を表します。したがって、表示される列のサイズは、それと列ヘッダー自体の長さ ( max(cd[2], len(cd[0]))) の間の大きい方になります。

于 2013-12-04T18:26:08.510 に答える
19

使用するprettytable

x = PrettyTable(["City name", "Area", "Population", "Annual Rainfall"])
x.set_field_align("City name", "l") # Left align city names
x.set_padding_width(1) # One space between column edges and contents (default)
x.add_row(["Adelaide",1295, 1158259, 600.5])
x.add_row(["Brisbane",5905, 1857594, 1146.4])
x.add_row(["Darwin", 112, 120900, 1714.7])
x.add_row(["Hobart", 1357, 205556, 619.5])
x.add_row(["Sydney", 2058, 4336374, 1214.8])
x.add_row(["Melbourne", 1566, 3806092, 646.9])
x.add_row(["Perth", 5386, 1554769, 869.4])
print x

+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide  | 1295 |  1158259   |      600.5      |
| Brisbane  | 5905 |  1857594   |      1146.4     |
| Darwin    | 112  |   120900   |      1714.7     |
| Hobart    | 1357 |   205556   |      619.5      |
| Sydney    | 2058 |  4336374   |      1214.8     |
| Melbourne | 1566 |  3806092   |      646.9      |
| Perth     | 5386 |  1554769   |      869.4      |
+-----------+------+------------+-----------------+
于 2012-06-02T20:17:16.037 に答える
2

データはいくつかのリストにあるようで、ヘッダーを印刷しています。次のような書式設定を検討してください。

res = ['trebuchet ms', 8868, 417]
res = ['lucida sans unicode', 3525, 116]

print(' {0[0]:20s} {0[1]:10d} {0[2]:10d}'.format(res))

あなたにあげる

 trebuchet ms               8868        417
 lucida sans unicode        3525        116

リストへのインデックス付けは文字列内で行われることに注意してくださいformat。リストまたはタプルを指定するだけで済みます。

または、プログラムで幅を指定することもできます。

wid1 = 20
wid2 = 10
wid3 = 10
print(' {:{}s} {:{}d} {:{}d}'.format(res[0], wid1, res[1], wid2, res[2], wid3))

上記と同じ出力が得られます。

必要に応じてフィールド幅を調整し、サンプル行を作成する代わりに、データの行ごとにリストをループする必要があります。数値は自動的に右寄せされ、文字列は自動的に左寄せされます。

もちろん、一部の人にとっての利点は、これが外部ライブラリに依存せず、Python が既に提供しているもので行われることです。

文字列フォーマットの詳細については、こちらをご覧ください

于 2012-06-02T20:10:53.323 に答える
2

次の 2 つのパスを実行する必要があります。

  1. 列幅を計算する
  2. 表を印刷する

そう

table = cur.fetchall()
widths = [0]*len(table[0])  # Assuming there is always one row
for row in table:
    widths = [max(w,len(c)) for w,c in zip(widths,row)]

これで、テーブルを簡単に印刷できます。

string.rjust数字を印刷するときの方法を覚えておいてください。

アップデート

より機能的な計算方法widthsは次のとおりです。

sizetable = [map(len,row) for row in table]
widths = map(max, zip(*sizetable))
于 2012-06-02T20:20:36.927 に答える