Problema: La mejor manera de entender los datos es a menudo visualizarlos a través de un gráfico o diagrama. Si bien SQL Server incluye SSRS como una herramienta de inteligencia empresarial, SSRS no siempre es la mejor opción ni siempre está disponible para proporcionar visualización de datos. Esta publicación del blog explorará una solución alternativa utilizando Python 2.x con Matplotlib y PyQT4 como una opción de visualización para los datos de SQL Server.
Solución: Normalmente, la mejor manera de proporcionar un gráfico basado en datos en SQL Server es crearlo en una herramienta de inteligencia empresarial como SSRS. SSRS es una herramienta altamente versátil que permite la creación fácil de una amplia variedad de gráficos y diagramas, incluyendo gráficos de trellis, gráficos de bala, gráficos de caja estadística y paneles para organizar todo. Sin embargo, hay ocasiones en las que una herramienta de inteligencia empresarial dedicada no se ajusta a la situación. En estos casos, una forma de resolver el problema es crear los gráficos en Python con Matplotlib y luego mostrar los resultados en una GUI basada en PyQT.
Para demostrar cómo se puede hacer esto, creemos una tabla simple con algunos datos de ventas:
create database TestDb
Go
use TestDb
Go
create table SalesData(SalesPerson varchar(100), mon int, amount money)
GO
--Uses a table value constructor from 2008 or later
insert into dbo.SalesData
(SalesPerson, mon, amount)
values
('Jack', 1, 202.55),
('Jack', 2, 301.77),
('Jack', 3, 403.88),
('Jack', 4, 400.11),
('Jill', 1, 410.11),
('Jill', 2, 305.99),
('Jill', 3, 412.99),
('Jill', 4, 412.99);
Para trazar los datos, podemos usar la biblioteca Matplotlib. Matplotlib se puede usar en scripts sin ninguna otra biblioteca de GUI para mostrar o guardar gráficos de datos, y se puede usar tanto en scripts como de forma interactiva desde un indicador de Python. Sin embargo, generalmente se puede hacer más fácil de usar para los no programadores al incluirlo en una GUI construida con una biblioteca como PyQT.
Primero, necesitamos importar las bibliotecas necesarias:
#PyQt4 y matplotlib no vienen con la distribución de código de Python,
#pero vienen con distribuciones más completas como
#Python(X,Y), o se pueden descargar por separado.
from PyQt4 import QtGui, QtCore
from matplotlib.backends.backend_qt4agg import (FigureCanvasQTAgg,
NavigationToolbar2QT)
from matplotlib.figure import Figure
A continuación, necesitaremos crear una clase de lienzo. Esta clase proporcionará el lienzo que se colocará en la GUI:
class mplCanvasWidget(FigureCanvasQTAgg):
"""Un QWidget que proporciona el lienzo que se colocará en la GUI.
Variaciones de esto se incluyen con PythonXY."""
def __init__(self, parent=None, x=[0, ], y=[0, ]):
mplFig = Figure()
self.axes = mplFig.add_subplot(1, 1, 1)
self.plot(x, y)
FigureCanvasQTAgg.__init__(self, mplFig)
self.setParent(parent)
FigureCanvasQTAgg.setSizePolicy(self, QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
FigureCanvasQTAgg.updateGeometry(self)
def plot(self, x, y):
"""traza las listas x e y pasadas, sobrescribirá cualquier dato
que ya esté allí."""
self.axes.clear()
self.axes.plot(x, y)
Luego, definimos la clase que invocará la GUI. Esta clase creará la GUI y organizará los widgets:
class guiWindow(QtGui.QMainWindow):
"""A menudo esto sería creado por una herramienta como QT Designer"""
def __init__(self, sqlConn):
QtGui.QMainWindow.__init__(self)
self.sqlConn = sqlConn
self.coreWidget = QtGui.QWidget(self)
self.salesPersonChoice = QtGui.QComboBox(parent=self.coreWidget)
self.pyPlot = mplCanvasWidget(parent=self.coreWidget)
self.mpl_toolbar = NavigationToolbar2QT(canvas=self.pyPlot,
parent=self.coreWidget)
layout = QtGui.QVBoxLayout(self.coreWidget)
layout.addWidget(self.salesPersonChoice)
layout.addWidget(self.pyPlot)
layout.addWidget(self.mpl_toolbar)
QtCore.QObject.connect(self.salesPersonChoice,
QtCore.SIGNAL('activated(const QString&)'),
self.updatePlot)
self.salesPersonChoice.addItems(self.getSalesPeople())
self.coreWidget.setFocus()
self.setCentralWidget(self.coreWidget)
def getSalesPeople(self):
salesPeopleList=['',]
curs = self.sqlConn.cursor()
sql = "select distinct SalesPerson from dbo.SalesData"
curs.execute(sql)
for row in curs:
salesPeopleList.append(row.SalesPerson)
curs.close()
curs.close()
return QtCore.QStringList(salesPeopleList)
def updatePlot(self):
curs = sqlConn.cursor()
person = str(self.salesPersonChoice.currentText())
sql = """select mon, amount
from dbo.SalesData
where SalesPerson = ?
order by mon"""
curs.execute(sql, (person,) )
rows = curs.fetchall()
x = [row.mon for row in rows]
y = [row.amount for row in rows]
self.pyPlot.plot(x, y)
self.pyPlot.draw()
Finalmente, necesitamos hacer la conexión a SQL Server e invocar la GUI:
sqlConnStr = ('DRIVER={SQL Server};Server=(local);Database=TestDb;'+
'Trusted_Connection=YES')
sqlConn = pyodbc.connect(sqlConnStr)
import sys
app = QtGui.QApplication(sys.argv)
QtGui.QApplication()
appGui = guiWindow(sqlConn)
appGui.show()
sys.exit(app.exec_())
Como se puede ver, Python con PyQt y Matplotlib puede proporcionar excelentes capacidades de gráficos que se pueden incrustar en una GUI completa. Aunque esta sería generalmente una opción inferior cuando SSRS podría manejar el trabajo, puede proporcionar la capacidad de insertar gráficos desde SQL Server en programas más grandes o proporcionar más versatilidad y control cuando sea necesario.