Clarion y SQL (III)
Publicado: Vie Ago 12, 2011 9:09 am
La idea no es hacer un sistema completo pero aún así necesitaremos algunas tablas. Si quieren ver distintos modelos pueden ir a esta página http://www.databaseanswers.org/data_models/index.htm que tiene muchos ejemplos.
Los modelos de esa página difieren, sin embargo, con la forma en la que suelo definir mis tablas (no quiero decir que mi método sea mejor, solo que es diferente). Si se fijan en este modelo http://www.databaseanswers.org/data_mod ... /index.htm observarán que la tabla CUSTOMERS tiene un campo Customer_ID pero no un Customer_Number o Customer_Code. El Customer_ID es el que se usará como Clave externa en las relaciones y yo prefiero que sea intocable, por eso siempre agrego el Customer_Number. Por ejemplo:
CLIENTES
CLI_ID INT (Identity)
CLI_NUMERO INT
CLI_NOMBRE VARCHAR(30)
CLI_APELLIDO VARCHAR(30)
¿Cuál es la ventaja de trabajar así? Si cambio el número de un cliente no tengo que trasladar ese cambio a ninguna de sus tablas relacionadas ya que estas lo están por el CLI_ID que NUNCA cambiará. Imaginen en el primer caso que un Cliente tiene 100.000 Facturas (hay que ponerlo en un pedestal a un cliente así ) y que cambiamos su número. Si usamos las tablas del modelo, el cambio se debe propagar a los 100.000 registros de facturas que, aún cuando esto SQL lo haga en segundos, consume un poco de tiempo. En mi modelo esta propagación no se lleva a cabo dado que no es necesaria.
Aprovecho para hacer un comentario: habrán notado que a los campos les puse un prefijo, en este caso CLI_. La razón de esto es que siempre intento que los nombres de los campos sean únicos ya que de esta manera me evito tener que anteponer el nombre de las tablas en las consultas. Por ejemplo, supongamos que queremos saber quienes son los clientes que han tenido más de 10 facturas en el año 2010. Primero me gustaría que piensen cómo resolverían esto con Clarion y TPS. ¿Qué se les ocurre? ¿Recorrer con un LOOP las facturas del 2010 (ordenadas por fecha) e ir contando cuántas facturas tuvo cada cliente? Por supuesto necesitaríamos una queue para ir guardando el número de cliente, su nombre y la cantidad de facturas. Suena un poco complicado, ¿no?.
En SQL eso se resuelve mucho más fácil:
SELECT CLI_NUMERO, CLI_NOMBRE, COUNT(*)
FROM CLIENTES, FACTURAS
WHERE CLI_ID = FAC_CLI_ID AND FAC_FECHA BETWEEN '2010-01-01 00:00:00' AND '2010-12-31 23:59:59'
GROUP BY CLI_NUMERO, CLI_NOMBRE
HAVING COUNT(*) >= 10
ORDER BY COUNT(*) DESC
Con la ayuda de la tabla estúpida (si alguien no sabe cómo usarla me lo dice y lo explico) enviamos esta sentencia al motor y lo único que tenemos que hacer es recorrerla para luego llenar una queue con SOLO los registros que cumplen la condición ya que el motor se encargó de resolver la consulta, contar cuántas facturas tuvo cada cliente y devolvernos esos datos ordenados de mayor a menor. Una sola sentencia, menos tráfico yendo y viniendo del cliente al servidor y problema resuelto.
Y fíjense que en la relación entre las tablas CLIENTES y FACTURAS no usé en ningún momento el prefijo de las facturas o su alias dado que, al ser los campos únicos, no fue necesario.
Por si alguno no lo leyó, es interesante comprender cómo el motor resuelve el SELECT anterior. Pueden verlo aquí: viewtopic.php?f=6&t=81
Seguimos luego.
Los modelos de esa página difieren, sin embargo, con la forma en la que suelo definir mis tablas (no quiero decir que mi método sea mejor, solo que es diferente). Si se fijan en este modelo http://www.databaseanswers.org/data_mod ... /index.htm observarán que la tabla CUSTOMERS tiene un campo Customer_ID pero no un Customer_Number o Customer_Code. El Customer_ID es el que se usará como Clave externa en las relaciones y yo prefiero que sea intocable, por eso siempre agrego el Customer_Number. Por ejemplo:
CLIENTES
CLI_ID INT (Identity)
CLI_NUMERO INT
CLI_NOMBRE VARCHAR(30)
CLI_APELLIDO VARCHAR(30)
¿Cuál es la ventaja de trabajar así? Si cambio el número de un cliente no tengo que trasladar ese cambio a ninguna de sus tablas relacionadas ya que estas lo están por el CLI_ID que NUNCA cambiará. Imaginen en el primer caso que un Cliente tiene 100.000 Facturas (hay que ponerlo en un pedestal a un cliente así ) y que cambiamos su número. Si usamos las tablas del modelo, el cambio se debe propagar a los 100.000 registros de facturas que, aún cuando esto SQL lo haga en segundos, consume un poco de tiempo. En mi modelo esta propagación no se lleva a cabo dado que no es necesaria.
Aprovecho para hacer un comentario: habrán notado que a los campos les puse un prefijo, en este caso CLI_. La razón de esto es que siempre intento que los nombres de los campos sean únicos ya que de esta manera me evito tener que anteponer el nombre de las tablas en las consultas. Por ejemplo, supongamos que queremos saber quienes son los clientes que han tenido más de 10 facturas en el año 2010. Primero me gustaría que piensen cómo resolverían esto con Clarion y TPS. ¿Qué se les ocurre? ¿Recorrer con un LOOP las facturas del 2010 (ordenadas por fecha) e ir contando cuántas facturas tuvo cada cliente? Por supuesto necesitaríamos una queue para ir guardando el número de cliente, su nombre y la cantidad de facturas. Suena un poco complicado, ¿no?.
En SQL eso se resuelve mucho más fácil:
SELECT CLI_NUMERO, CLI_NOMBRE, COUNT(*)
FROM CLIENTES, FACTURAS
WHERE CLI_ID = FAC_CLI_ID AND FAC_FECHA BETWEEN '2010-01-01 00:00:00' AND '2010-12-31 23:59:59'
GROUP BY CLI_NUMERO, CLI_NOMBRE
HAVING COUNT(*) >= 10
ORDER BY COUNT(*) DESC
Con la ayuda de la tabla estúpida (si alguien no sabe cómo usarla me lo dice y lo explico) enviamos esta sentencia al motor y lo único que tenemos que hacer es recorrerla para luego llenar una queue con SOLO los registros que cumplen la condición ya que el motor se encargó de resolver la consulta, contar cuántas facturas tuvo cada cliente y devolvernos esos datos ordenados de mayor a menor. Una sola sentencia, menos tráfico yendo y viniendo del cliente al servidor y problema resuelto.
Y fíjense que en la relación entre las tablas CLIENTES y FACTURAS no usé en ningún momento el prefijo de las facturas o su alias dado que, al ser los campos únicos, no fue necesario.
Por si alguno no lo leyó, es interesante comprender cómo el motor resuelve el SELECT anterior. Pueden verlo aquí: viewtopic.php?f=6&t=81
Seguimos luego.