I have an internal stocks management application that I rebuild from
time to time, usually against the latest SQLite version. After moving to
SQLite 3.9.1 it started reporting crazy stock values. Previously it was
compiled with SQLite 3.8.8.3. Further investigation showed that the last
usable SQLite version is 3.8.10.2. The application is compiled with
Visual Studio 2013 Express.
The SQL statement creating the database and the temporary views is:
*****
PRAGMA case_sensitive_like = ON;
PRAGMA foreign_keys = ON;
VACUUM;
CREATE TABLE IF NOT EXISTS Categories(CatID INTEGER PRIMARY KEY
AUTOINCREMENT,
Name TEXT);
CREATE TABLE IF NOT EXISTS Components(CompID INTEGER PRIMARY KEY
AUTOINCREMENT,
CatID INTEGER REFERENCES
Categories(CatID),
Name TEXT);
CREATE TABLE IF NOT EXISTS Suppliers(SupID INTEGER PRIMARY KEY
AUTOINCREMENT,
Name TEXT);
CREATE TABLE IF NOT EXISTS Codes(CodeID INTEGER PRIMARY KEY AUTOINCREMENT,
CompID INTEGER REFERENCES
Components(CompID),
SupID INTEGER REFERENCES Suppliers(SupID),
Name TEXT);
CREATE TABLE IF NOT EXISTS Inputs(InvID INTEGER PRIMARY KEY AUTOINCREMENT,
SupID INTEGER REFERENCES
Suppliers(SupID),
Date INTEGER,
Total REAL,
CompTotal REAL,
ExchgRate REAL,
Name TEXT);
CREATE TABLE IF NOT EXISTS InputsComp(InCompID INTEGER PRIMARY KEY
AUTOINCREMENT,
InvID INTEGER REFERENCES
Inputs(InvID),
CodeID INTEGER REFERENCES
Codes(CodeID),
Total REAL,
Quantity REAL);
CREATE TABLE IF NOT EXISTS Products(ProdID INTEGER PRIMARY KEY
AUTOINCREMENT,
Code TEXT,
Name TEXT);
CREATE TABLE IF NOT EXISTS ProductsComp(ProdCompID INTEGER PRIMARY KEY
AUTOINCREMENT,
ProdID INTEGER REFERENCES
Products(ProdID),
CompID INTEGER REFERENCES
Components(CompID),
Quantity REAL);
CREATE TABLE IF NOT EXISTS Outputs(OutID INTEGER PRIMARY KEY AUTOINCREMENT,
Date INTEGER,
Name TEXT);
CREATE TABLE IF NOT EXISTS OutputsProd(OutProdID INTEGER PRIMARY KEY
AUTOINCREMENT,
OutID INTEGER REFERENCES
Outputs(OutID),
ProdID INTEGER REFERENCES
Products(ProdID),
Quantity REAL);
CREATE TABLE IF NOT EXISTS OutputsComp(OutCompID INTEGER PRIMARY KEY
AUTOINCREMENT,
OutID INTEGER REFERENCES
Outputs(OutID),
CompID INTEGER REFERENCES
Components(CompID),
Quantity REAL);
CREATE TEMP VIEW Codes_View AS
SELECT CodeID,CompID,SupID,Name,
(SELECT Name FROM Suppliers WHERE (Suppliers.SupID =
Codes.SupID)) || ' - ' || Name AS SupplierCode,
(SELECT CatID FROM Components WHERE (Components.CompID =
Codes.CompID)) AS CatID,
(SELECT Name FROM Components WHERE (Components.CompID =
Codes.CompID)) AS Component
FROM Codes;
CREATE TEMP VIEW Inputs_View AS
SELECT InvID,SupID,Date,Total,CompTotal,ExchgRate,Name,
Total/ExchgRate/CompTotal AS PriceRatio,
(SELECT Name FROM Suppliers WHERE (Suppliers.SupID =
Inputs.SupID)) AS Supplier,
(SELECT Name FROM Suppliers WHERE (Suppliers.SupID =
Inputs.SupID)) || ' - ' || Name AS FullName
FROM Inputs;
CREATE TEMP VIEW InputsComp_View AS
SELECT InCompID,InvID,CodeID,Total,Quantity,
Total*(SELECT PriceRatio FROM Inputs_View WHERE
(Inputs_View.InvID = InputsComp.InvID)) AS EffPrice,
Total*(SELECT PriceRatio FROM Inputs_View WHERE
(Inputs_View.InvID = InputsComp.InvID))/Quantity AS UnitPrice,
(SELECT CompID FROM Codes WHERE (Codes.CodeID =
InputsComp.CodeID)) AS CompID,
(SELECT SupplierCode FROM Codes_View WHERE (Codes_View.CodeID
= InputsComp.CodeID)) AS SupplierCode,
(SELECT Component FROM Codes_View WHERE (Codes_View.CodeID =
InputsComp.CodeID)) AS Component,
(SELECT FullName FROM Inputs_View WHERE (Inputs_View.InvID =
InputsComp.InvID)) AS Invoice,
(SELECT Date FROM Inputs_View WHERE (Inputs_View.InvID =
InputsComp.InvID)) AS Date
FROM InputsComp;
CREATE TEMP VIEW ProductsComp_View AS
SELECT ProdCompID,ProdID,CompID,Quantity,
(SELECT Name FROM Components WHERE (Components.CompID =
ProductsComp.CompID)) AS Component,
(SELECT MIN(UnitPrice) FROM InputsComp_View WHERE
(InputsComp_View.CompID = ProductsComp.CompID)) *
Quantity AS PriceMin,
(SELECT MAX(UnitPrice) FROM InputsComp_View WHERE
(InputsComp_View.CompID = ProductsComp.CompID)) *
Quantity AS PriceMax,
(SELECT SUM(EffPrice) FROM InputsComp_View WHERE
(InputsComp_View.CompID = ProductsComp.CompID)) /
(SELECT SUM(Quantity) FROM InputsComp_View WHERE
(InputsComp_View.CompID = ProductsComp.CompID)) *
Quantity AS PriceMed
FROM ProductsComp;
CREATE TEMP VIEW Products_View AS
SELECT ProdID,Code,Name,
(SELECT SUM(PriceMin) FROM ProductsComp_View WHERE
(ProductsComp_View.ProdID = Products.ProdID)) AS PriceMin,
(SELECT SUM(PriceMax) FROM ProductsComp_View WHERE
(ProductsComp_View.ProdID = Products.ProdID)) AS PriceMax,
(SELECT SUM(PriceMed) FROM ProductsComp_View WHERE
(ProductsComp_View.ProdID = Products.ProdID)) AS PriceMed
FROM Products;
CREATE TEMP VIEW OutputsComp_View AS
SELECT ProductsComp.CompID AS CompID,OutputsProd.OutID AS
OutID,(OutputsProd.Quantity * ProductsComp.Quantity) AS Quantity,
(SELECT Date FROM Outputs WHERE (Outputs.OutID =
OutputsProd.OutID)) AS Date,
(SELECT Name FROM Outputs WHERE (Outputs.OutID =
OutputsProd.OutID)) || ' - ' ||
(SELECT Code FROM Products WHERE (Products.ProdID =
OutputsProd.ProdID)) AS Output,
(SELECT Name FROM Components WHERE (Components.CompID =
ProductsComp.CompID)) AS Component
FROM OutputsProd,ProductsComp
WHERE (OutputsProd.ProdID = ProductsComp.ProdID)
UNION
SELECT CompID,OutID,Quantity,
(SELECT Date FROM Outputs WHERE (Outputs.OutID =
OutputsComp.OutID)) AS Date,
(SELECT Name FROM Outputs WHERE (Outputs.OutID =
OutputsComp.OutID)) AS Output,
(SELECT Name FROM Components WHERE (Components.CompID =
OutputsComp.CompID)) AS Component
FROM OutputsComp;
CREATE TEMP VIEW Outputs_View AS
SELECT OutID,Date,Name,
(SELECT SUM(Quantity * (SELECT MIN(UnitPrice) FROM InputsComp_View
WHERE (InputsComp_View.CompID = OutputsComp_View.CompID)))
FROM OutputsComp_View WHERE (OutputsComp_View.OutID =
Outputs.OutID)) AS PriceMin,
(SELECT SUM(Quantity * (SELECT MAX(UnitPrice) FROM InputsComp_View
WHERE (InputsComp_View.CompID = OutputsComp_View.CompID)))
FROM OutputsComp_View WHERE (OutputsComp_View.OutID =
Outputs.OutID)) AS PriceMax,
(SELECT SUM(Quantity * (SELECT SUM(EffPrice) FROM InputsComp_View
WHERE (InputsComp_View.CompID = OutputsComp_View.CompID)) /
(SELECT SUM(Quantity) FROM InputsComp_View WHERE
(InputsComp_View.CompID = OutputsComp_View.CompID)))
FROM OutputsComp_View WHERE (OutputsComp_View.OutID =
Outputs.OutID)) AS PriceMed
FROM Outputs;
CREATE TEMP VIEW Stocks_View AS
SELECT CompID,CatID,Name,
ifnull((SELECT SUM(Quantity) FROM InputsComp_View WHERE
(InputsComp_View.CompID = Components.CompID)),0) -
ifnull((SELECT SUM(Quantity) FROM OutputsComp_View WHERE
(OutputsComp_View.CompID = Components.CompID)),0) AS Quantity,
(SELECT MIN(UnitPrice) FROM InputsComp_View WHERE
(InputsComp_View.CompID = Components.CompID)) AS PriceMin,
(SELECT MAX(UnitPrice) FROM InputsComp_View WHERE
(InputsComp_View.CompID = Components.CompID)) AS PriceMax,
(SELECT SUM(EffPrice) FROM InputsComp_View WHERE
(InputsComp_View.CompID = Components.CompID)) /
(SELECT SUM(Quantity) FROM InputsComp_View WHERE
(InputsComp_View.CompID = Components.CompID)) AS PriceMed
FROM Components;
*****
The problem is with the Quantity field of the Stocks_View temporary
view. While the Quantity field values are correct in InputsComp_View and
OutputsComp_View (the results for a specific CompID are shown in
separate grids when checking the stocks) and the result of
ifnull((SELECT SUM(Quantity) FROM InputsComp_View WHERE
(InputsComp_View.CompID = Components.CompID)),0)
is correct, the result of
ifnull((SELECT SUM(Quantity) FROM OutputsComp_View WHERE
(OutputsComp_View.CompID = Components.CompID)),0)
is not correctly considering all rows in OutputsComp_View.
One of the offending cases is for a CompID value that produces results
in OutputsComp_View only through the second part of the UNION (it is
found only in OutputsComp).