I have a very complex MySql query that is to close a business's cash, first I will present the tables that I have to develop the idea in order:
Table box:
CREATE TABLE 'caja' (
'id' INT(11) NOT NULL AUTO_INCREMENT,
'fechadecierre' DATETIME NULL DEFAULT NULL,
'inicio' DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
'final' DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
'empleado' INT(11) NOT NULL DEFAULT '0',
'estado' TINYINT(1) NOT NULL DEFAULT '0',
'comprobada' TINYINT(1) NOT NULL DEFAULT '0',
'anulado' TINYINT(1) NOT NULL DEFAULT '0',
'dinerodecajainicial' DECIMAL(11,2) NOT NULL DEFAULT '0',
'dinerodecajafinal' DECIMAL(11,2) NOT NULL DEFAULT '0',
'dineroparaproximacaja' DECIMAL(11,2) NOT NULL DEFAULT '0',
'terminal' TEXT NULL DEFAULT NULL,
'registrodeentradadedinero' TINYINT(1) NOT NULL DEFAULT '0',
'primerasuntocontable' INT(11) NOT NULL DEFAULT '0',
'ultimoasuntocontable' INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY ('id'),
UNIQUE INDEX 'id' ('id')
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
Accounting table
CREATE TABLE 'contabilidad' (
'anulado' TINYINT(1) NOT NULL DEFAULT '0',
'cuentacorriente' INT(11) NOT NULL DEFAULT '0',
'cuotas' DECIMAL(10,2) NOT NULL DEFAULT '0',
'empleado' INT(11) NOT NULL DEFAULT '0',
'fecha' DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
'formadepago' INT(11) NOT NULL DEFAULT '1',
'id' INT(11) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,
'idgasto' INT(11) NOT NULL DEFAULT '0',
'interesfinanciero' DECIMAL(10,2) NOT NULL DEFAULT '0',
'interesformadepago' DECIMAL(10,2) NOT NULL DEFAULT '0',
'ticketid' INT(11) NOT NULL DEFAULT '0',
'tipodetransaccion' VARCHAR(50) NOT NULL,
'transaccion' DECIMAL(10,2) NOT NULL DEFAULT '0',
'valordecuota' DECIMAL(10,2) NOT NULL DEFAULT '0',
'valorfinal' DECIMAL(10,2) NOT NULL DEFAULT '0',
PRIMARY KEY ('id'),
INDEX 'fecha' ('fecha'),
INDEX 'ticketid' ('ticketid'),
INDEX 'idgasto' ('idgasto'),
INDEX 'formadepago' ('formadepago'),
FULLTEXT INDEX 'tipodetransaccion' ('tipodetransaccion')
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
Table tickets
CREATE TABLE 'tickets' (
'id' INT(11) NOT NULL AUTO_INCREMENT,
'fecha' DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
'anulacion' INT(11) NOT NULL DEFAULT '0',
'total' DECIMAL(11,2) NOT NULL DEFAULT '0',
'descuento' DECIMAL(5,2) NOT NULL DEFAULT '0',
'cuentacorriente' INT(11) NOT NULL DEFAULT '0',
'empleado' INT(10) NOT NULL DEFAULT '0',
'señacliente' INT(11) NOT NULL DEFAULT '0',
'terminal' TEXT NULL DEFAULT NULL,
'senacliente' INT(11) NOT NULL DEFAULT '0',
'devolucion' DECIMAL(11,2) NOT NULL DEFAULT '0',
'formasdepago' INT(11) NULL DEFAULT NULL,
UNIQUE INDEX 'id' ('id'),
INDEX 'anulacion' ('anulacion'),
INDEX 'fecha' ('fecha')
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=47321
;
Ticketproducts table
CREATE TABLE 'ticketproductos' (
'id' INT(11) NOT NULL AUTO_INCREMENT,
'notadecreditoid' INT(11) NOT NULL DEFAULT '0',
'idrubro' INT(11) NOT NULL DEFAULT '0',
'ticketid' INT(11) NOT NULL DEFAULT '0',
'productoid' INT(11) NOT NULL DEFAULT '0',
'cantidad' DECIMAL(11,2) NOT NULL DEFAULT '0',
'precio' DECIMAL(11,2) NOT NULL DEFAULT '0',
'porpeso' INT(1) NOT NULL DEFAULT '0',
'anulado' TINYINT(1) NOT NULL DEFAULT '0',
'promocionid' INT(11) NOT NULL DEFAULT '0',
'preciooriginal' DECIMAL(11,2) NOT NULL DEFAULT '0',
'pesodeprecio' DECIMAL(10,2) NOT NULL DEFAULT '1',
PRIMARY KEY ('id'),
UNIQUE INDEX 'id_2' ('id'),
INDEX 'id' ('id'),
INDEX 'idrubro' ('idrubro'),
INDEX 'ticketid' ('ticketid'),
INDEX 'productoid' ('productoid'),
INDEX 'anulado' ('anulado')
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
The operation of the database would be the following: when generating a sale, a ticket (Record in the ticket table) is generated with the detail, in the ticket it carries items that can be Services or Products, which are registered in the table "ticketproducts", these are related through the column "ticketid" of the last table named. When making the payment of the sale, a record is generated in "accounting" in which "transaction" is the amount of the money paid, and in "transaction type" it is called "payment". In the last mentioned table, it can be seen that in "transaction type" in addition to payment, "expense" may also be recorded, claiming an expense and "withdrawal" to a withdrawal of money. And each accounting movement is adjudicated for sale in relation to the field "contabilidad.ticketid" referring to "ticket.id". In all operations you can cancel it. If it is a ticket that is canceled, it is placed in the column "cancellation = 1", and all the ticketproducts referring to it are also canceled by the column "canceled = 1". On the other hand, accounting generates a new record with the amount canceled and the column "annulled = 1" where the cancellation of payment is recorded, the value of canceled is not changed but a new record is generated. The "cash" table refers to the accounting movements, in order to generate the summary. Then "caja.primerasuntacount" and "caja.ultimoasuntauntaunta" refer to "cuenta.id" where you can get all the data from the box. Then the reference would be the following.
"caja.primerasuntacount = > cuenta.id" and "contabilidad.id = < caja.ultimoasuntauntunta". Then "accounting.ticketid = ticket.id" and ticketproducts.ticketid = ticket.id "
When an expense is recorded, no reference is made to a ticket.id but an "expense.id" but it is not necessary to perform this sql query.
The query in question is the following:
SELECT id, registrodeentradadedinero, fechadecierre, inicio, final, dinerodecajafinal, primerasuntocontable, primerasuntocontable, (SELECT nombre FROM empleados WHERE id = empleado) as empleado, estado, dinerodecajainicial, dinerodecajafinal, dineroparaproximacaja, terminal,
IFNULL((SELECT COUNT(tickets.id) AS i FROM tickets INNER JOIN contabilidad ON contabilidad.ticketid = tickets.id WHERE anulacion = 0 AND (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable)),0) AS totalticketvalidos,
IFNULL((SELECT COUNT(tickets.id) AS i FROM tickets INNER JOIN contabilidad ON contabilidad.ticketid = tickets.id WHERE anulacion = 1 AND (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable)),0) AS totalticketanulados,
IFNULL((SELECT SUM(transaccion) AS i FROM tickets INNER JOIN contabilidad ON contabilidad.ticketid = tickets.id WHERE contabilidad.anulado = 0 AND (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable) AND tipodetransaccion = 'pago'),0) AS totalenventas,
IFNULL((SELECT SUM(transaccion) AS i FROM tickets INNER JOIN contabilidad ON contabilidad.ticketid = tickets.id WHERE contabilidad.anulado != 0 AND (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable) AND tipodetransaccion = 'pago'),0) AS totalenventasanulado,
IFNULL((SELECT SUM(CASE WHEN contabilidad.anulado = 0 THEN transaccion ELSE 0 END) - SUM(CASE WHEN contabilidad.anulado != 0 THEN transaccion ELSE 0 END) AS i FROM tickets INNER JOIN contabilidad ON contabilidad.ticketid = tickets.id WHERE (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable) AND tipodetransaccion = 'pago'),0) AS totalenventasingresado,
IFNULL((SELECT SUM(ticketproductos.cantidad) AS i FROM ticketproductos INNER JOIN contabilidad ON contabilidad.ticketid = ticketproductos.ticketid WHERE ticketproductos.anulado = 0 AND (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable)),0) AS cantidadproductosvendidos,
IFNULL((SELECT COUNT(tickets.id) AS i FROM tickets INNER JOIN contabilidad ON contabilidad.ticketid = tickets.id WHERE (contabilidad.id >= primerasuntocontable AND contabilidad.id <= ultimoasuntocontable)),0) AS totalticketregistrados,
IFNULL((SELECT SUM(transaccion) AS i FROM contabilidad WHERE tipodetransaccion = 'pago' AND anulado = 0 AND (id >= primerasuntocontable AND id <= ultimoasuntocontable)),0) AS totaldineroregistrado,
IFNULL((SELECT SUM(transaccion) AS i FROM contabilidad WHERE anulado != 0 AND tipodetransaccion = 'pago' AND (id >= primerasuntocontable AND id <= ultimoasuntocontable)),0) AS totaldineroanulado,
IFNULL((SELECT (SUM(CASE WHEN (anulado != 1 AND tipodetransaccion = 'pago') OR ( anulado = 1 AND tipodetransaccion = 'gasto') THEN transaccion ELSE 0 END) - SUM(CASE WHEN (anulado = 1 AND tipodetransaccion = 'pago') OR (anulado = 0 AND tipodetransaccion = 'gasto') THEN transaccion ELSE 0 END)) AS i FROM contabilidad WHERE (tipodetransaccion = 'pago' OR tipodetransaccion = 'gasto') AND (id >= primerasuntocontable AND id <= ultimoasuntocontable)),0) AS totaldineroingresado,
IFNULL((SELECT SUM(transaccion) AS i FROM contabilidad WHERE anulado = 0 AND tipodetransaccion = 'retiro' AND (id >= primerasuntocontable AND id <= ultimoasuntocontable)),0) AS totalretiros,
IFNULL((SELECT SUM(transaccion) AS i FROM contabilidad WHERE anulado = 0 AND tipodetransaccion = 'gasto' AND (id >= primerasuntocontable AND id <= ultimoasuntocontable)),0) AS totalgastos FROM caja WHERE id = 793
The results of it is as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>caja</title>
<meta name="GENERATOR" content="HeidiSQL 9.5.0.5196">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
thead tr {background-color: ActiveCaption; color: CaptionText;}
th, td {vertical-align: top; font-family: "Tahoma", Arial, Helvetica, sans-serif; font-size: 8pt; padding: 3px; }
table, td {border: 1px solid silver;}
table {border-collapse: collapse;}
thead .col0 {width: 57px;}
.col0 {text-align: right;}
thead .col1 {width: 157px;}
.col1 {text-align: right;}
thead .col2 {width: 138px;}
thead .col3 {width: 138px;}
thead .col4 {width: 138px;}
thead .col5 {width: 110px;}
.col5 {text-align: right;}
thead .col6 {width: 132px;}
.col6 {text-align: right;}
thead .col7 {width: 132px;}
.col7 {text-align: right;}
thead .col8 {width: 82px;}
thead .col9 {width: 61px;}
.col9 {text-align: right;}
thead .col10 {width: 115px;}
.col10 {text-align: right;}
thead .col11 {width: 110px;}
.col11 {text-align: right;}
thead .col12 {width: 138px;}
.col12 {text-align: right;}
thead .col13 {width: 107px;}
thead .col14 {width: 109px;}
.col14 {text-align: right;}
thead .col15 {width: 119px;}
.col15 {text-align: right;}
thead .col16 {width: 95px;}
.col16 {text-align: right;}
thead .col17 {width: 133px;}
.col17 {text-align: right;}
thead .col18 {width: 142px;}
.col18 {text-align: right;}
thead .col19 {width: 160px;}
.col19 {text-align: right;}
thead .col20 {width: 130px;}
.col20 {text-align: right;}
thead .col21 {width: 129px;}
.col21 {text-align: right;}
thead .col22 {width: 118px;}
.col22 {text-align: right;}
thead .col23 {width: 127px;}
.col23 {text-align: right;}
thead .col24 {width: 81px;}
.col24 {text-align: right;}
thead .col25 {width: 82px;}
.col25 {text-align: right;}
</style>
</head>
<body>
<table caption="caja (1 rows)">
<thead>
<tr>
<th class="col0">id</th>
<th class="col1">registrodeentradadedinero</th>
<th class="col2">fechadecierre</th>
<th class="col3">inicio</th>
<th class="col4">final</th>
<th class="col5">dinerodecajafinal</th>
<th class="col6">primerasuntocontable</th>
<th class="col7">primerasuntocontable</th>
<th class="col8">empleado</th>
<th class="col9">estado</th>
<th class="col10">dinerodecajainicial</th>
<th class="col11">dinerodecajafinal</th>
<th class="col12">dineroparaproximacaja</th>
<th class="col13">terminal</th>
<th class="col14">totalticketvalidos</th>
<th class="col15">totalticketanulados</th>
<th class="col16">totalenventas</th>
<th class="col17">totalenventasanulado</th>
<th class="col18">totalenventasingresado</th>
<th class="col19">cantidadproductosvendidos</th>
<th class="col20">totalticketregistrados</th>
<th class="col21">totaldineroregistrado</th>
<th class="col22">totaldineroanulado</th>
<th class="col23">totaldineroingresado</th>
<th class="col24">totalretiros</th>
<th class="col25">totalgastos</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col0">793</td>
<td class="col1">1</td>
<td class="col2">2018-09-22 20:39:07</td>
<td class="col3">2018-09-22 17:26:18</td>
<td class="col4">2018-09-22 19:59:19</td>
<td class="col5">1060,00</td>
<td class="col6">73932</td>
<td class="col7">73932</td>
<td class="col8">MANUELA</td>
<td class="col9">1</td>
<td class="col10">600,00</td>
<td class="col11">1060,00</td>
<td class="col12">600,00</td>
<td class="col13">root@localhost</td>
<td class="col14">16</td>
<td class="col15">0</td>
<td class="col16">1820,00</td>
<td class="col17">0,00</td>
<td class="col18">1820,00</td>
<td class="col19">29,00</td>
<td class="col20">16</td>
<td class="col21">1820,00</td>
<td class="col22">0,00</td>
<td class="col23">455,00</td>
<td class="col24">0,00</td>
<td class="col25">1365,00</td>
</tr>
</tbody>
</table>
<p>
<em>generated 2018-09-26 10:14:06 by <a href="https://www.heidisql.com/">HeidiSQL 9.5.0.5196</a></em>
</p>
</body>
</html>
The query gets box 793 as an example. It works correctly but it is too complex, the idea is that it does not return any NULL and generate the data in general. Try to summarize it in the following way but it does not work well.
SELECT caja.id, caja.registrodeentradadedinero, caja.fechadecierre, caja.inicio, caja.final, caja.dinerodecajafinal, caja.primerasuntocontable, caja.primerasuntocontable, (SELECT nombre FROM empleados WHERE id = caja.empleado) as empleado, caja.estado, caja.dinerodecajainicial, caja.dinerodecajafinal, caja.dineroparaproximacaja, caja.terminal,
IFNULL((SELECT SUM(CASE WHEN tickets.anulacion = 0 THEN 1 ELSE 0 END)),0) AS totalticketvalidos,
IFNULL((SELECT SUM(CASE WHEN tickets.anulacion != 0 THEN 1 ELSE 0 END)),0) AS totalticketanulados,
IFNULL((SELECT SUM(tickets.total)),0) AS totalenventas,
IFNULL((SELECT SUM(CASE WHEN contabilidad.anulado != 0 THEN transaccion ELSE 0 END)),0) AS totalenventasanulado,
IFNULL((SELECT DISTINCT SUM(tickets.total) - SUM(CASE WHEN contabilidad.anulado != 0 THEN transaccion ELSE 0 END)),0) AS totalenventasingresado,
IFNULL((SELECT SUM(ticketproductos.cantidad)),0) AS cantidadproductosvendidos,
IFNULL((SELECT COUNT(tickets.id)),0) AS totalticketregistrados,
IFNULL((SELECT SUM(CASE WHEN (contabilidad.tipodetransaccion = 'pago' AND contabilidad.anulado = 0) THEN contabilidad.transaccion ELSE 0 END)),0) AS totaldineroregistrado,
IFNULL((SELECT SUM(CASE WHEN (contabilidad.anulado = 1 AND contabilidad.tipodetransaccion = 'pago') THEN contabilidad.transaccion ELSE 0 END)),0) AS totaldineroanulado,
IFNULL((SELECT (SUM(CASE WHEN (contabilidad.anulado = 0 AND contabilidad.tipodetransaccion = 'pago') OR ( contabilidad.anulado != 0 AND contabilidad.tipodetransaccion = 'gasto') THEN contabilidad.transaccion ELSE 0 END) - SUM(CASE WHEN (contabilidad.anulado != 0 AND contabilidad.tipodetransaccion = 'pago') OR (contabilidad.anulado = 0 AND contabilidad.tipodetransaccion = 'gasto') THEN contabilidad.transaccion ELSE 0 END))),0) AS totaldineroingresado,
IFNULL((SELECT SUM(CASE WHEN (contabilidad.anulado = 0 AND contabilidad.tipodetransaccion = 'retiro') THEN contabilidad.transaccion ELSE 0 END)),0) AS totalretiros,
IFNULL((SELECT SUM(CASE WHEN (contabilidad.anulado = 0 AND contabilidad.tipodetransaccion = 'gasto') THEN contabilidad.transaccion ELSE 0 END)),0) AS totalgastos FROM caja, contabilidad, tickets, ticketproductos WHERE tickets.id = ticketproductos.ticketid AND tickets.id = contabilidad.ticketid AND (contabilidad.id >= caja.primerasuntocontable AND contabilidad.id <= caja.ultimoasuntocontable) AND caja.id = 793 ;
And the results that are wrong are the following
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>caja</title>
<meta name="GENERATOR" content="HeidiSQL 9.5.0.5196">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
thead tr {background-color: ActiveCaption; color: CaptionText;}
th, td {vertical-align: top; font-family: "Tahoma", Arial, Helvetica, sans-serif; font-size: 8pt; padding: 3px; }
table, td {border: 1px solid silver;}
table {border-collapse: collapse;}
thead .col0 {width: 57px;}
.col0 {text-align: right;}
thead .col1 {width: 157px;}
.col1 {text-align: right;}
thead .col2 {width: 138px;}
thead .col3 {width: 138px;}
thead .col4 {width: 138px;}
thead .col5 {width: 110px;}
.col5 {text-align: right;}
thead .col6 {width: 132px;}
.col6 {text-align: right;}
thead .col7 {width: 132px;}
.col7 {text-align: right;}
thead .col8 {width: 82px;}
thead .col9 {width: 61px;}
.col9 {text-align: right;}
thead .col10 {width: 115px;}
.col10 {text-align: right;}
thead .col11 {width: 110px;}
.col11 {text-align: right;}
thead .col12 {width: 138px;}
.col12 {text-align: right;}
thead .col13 {width: 107px;}
thead .col14 {width: 109px;}
.col14 {text-align: right;}
thead .col15 {width: 119px;}
.col15 {text-align: right;}
thead .col16 {width: 95px;}
.col16 {text-align: right;}
thead .col17 {width: 133px;}
.col17 {text-align: right;}
thead .col18 {width: 142px;}
.col18 {text-align: right;}
thead .col19 {width: 160px;}
.col19 {text-align: right;}
thead .col20 {width: 130px;}
.col20 {text-align: right;}
thead .col21 {width: 129px;}
.col21 {text-align: right;}
thead .col22 {width: 118px;}
.col22 {text-align: right;}
thead .col23 {width: 127px;}
.col23 {text-align: right;}
thead .col24 {width: 81px;}
.col24 {text-align: right;}
thead .col25 {width: 82px;}
.col25 {text-align: right;}
</style>
</head>
<body>
<table caption="caja (1 rows)">
<thead>
<tr>
<th class="col0">id</th>
<th class="col1">registrodeentradadedinero</th>
<th class="col2">fechadecierre</th>
<th class="col3">inicio</th>
<th class="col4">final</th>
<th class="col5">dinerodecajafinal</th>
<th class="col6">primerasuntocontable</th>
<th class="col7">primerasuntocontable</th>
<th class="col8">empleado</th>
<th class="col9">estado</th>
<th class="col10">dinerodecajainicial</th>
<th class="col11">dinerodecajafinal</th>
<th class="col12">dineroparaproximacaja</th>
<th class="col13">terminal</th>
<th class="col14">totalticketvalidos</th>
<th class="col15">totalticketanulados</th>
<th class="col16">totalenventas</th>
<th class="col17">totalenventasanulado</th>
<th class="col18">totalenventasingresado</th>
<th class="col19">cantidadproductosvendidos</th>
<th class="col20">totalticketregistrados</th>
<th class="col21">totaldineroregistrado</th>
<th class="col22">totaldineroanulado</th>
<th class="col23">totaldineroingresado</th>
<th class="col24">totalretiros</th>
<th class="col25">totalgastos</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col0">793</td>
<td class="col1">1</td>
<td class="col2">2018-09-22 20:39:07</td>
<td class="col3">2018-09-22 17:26:18</td>
<td class="col4">2018-09-22 19:59:19</td>
<td class="col5">1060,00</td>
<td class="col6">73932</td>
<td class="col7">73932</td>
<td class="col8">MANUELA</td>
<td class="col9">1</td>
<td class="col10">600,00</td>
<td class="col11">1060,00</td>
<td class="col12">600,00</td>
<td class="col13">root@localhost</td>
<td class="col14">28</td>
<td class="col15">0</td>
<td class="col16">4205,00</td>
<td class="col17">0,00</td>
<td class="col18">4205,00</td>
<td class="col19">29,00</td>
<td class="col20">28</td>
<td class="col21">4205,00</td>
<td class="col22">0,00</td>
<td class="col23">4205,00</td>
<td class="col24">0,00</td>
<td class="col25">0,00</td>
</tr>
</tbody>
</table>
<p>
<em>generated 2018-09-26 10:10:28 by <a href="https://www.heidisql.com/">HeidiSQL 9.5.0.5196</a></em>
</p>
</body>
</html>
My theory is that it is wrong in the part of "INNER JOIN" where the data that are returned are repeated, this happens in the last query, for example the total of the sales is repeated twice, that is to say it is added by two sales, would someone have the time to tell me where the error is? thank you very much!