Creating a Scalar Function in SQL-Server To get Stock Preview - sql

So I'm having trouble creating a function to get a Preview of the stock of a product.
Simplified Model explanation:
My database has a table of Products, Sales and Orders, and I need to create a function that receives as parameter the Product's NumberID and a date, and return the preview stock on that specific date.
Basically if I have in store 5 bottles, and have an order for tomorrow of 3 bottles, given the 'day after tomorrow' date, then the Stock Preview will be 2.
My problem is, given a date before the current one, I think I'll need to go and see the sales between that date and now and add them to the preview right? and only after that I'll check the orders table.
I've been using many if's and cursors and it's driving me crazy

Related

How to get current stock of a product using stock_quant and sql query by date in odoo?

I can get current stock of a product in a warehouse in current time using stock_quant table and sql query.
But how is it possible to get the current stock in a specific date using stock_quant table and sql query?
It is not possible to get the stock of a product at a specific date using the stock.quant table. If you need to get the stock of a product at a certain date, you can try using the qty_available field in product.product model. You can pass to_date as context while fetching the qty_available field which will get you the stock at a specific date.

creating materialized view for annual report based on slow function

Consider the following scenario:
I have a table with 1 million product ids products :
create table products (
pid number,
p_description varchar2(200)
)
also there is a relatively slow function
function gerProductMetrics(pid,date) return number
which returns some metric for the given product at given date.
there is also an annual report executed every year that is based on the following query:
select pid,p_description,getProductMetrics(pid,'2019-12-31') from
products
that query takes about 20-40 minutes to execute for a given year.
would it be correct approach to create Materialized View (MV) for this scenario using the following
CREATE TABLE mydates
(
mydate date
);
INSERT INTO mydates (mydate)
VALUES (DATE '2019-12-31');
INSERT INTO mydates (mydate)
VALUES (DATE '2018-12-31');
INSERT INTO mydates (mydate)
VALUES (DATE '2017-12-31');
CREATE MATERIALIZED VIEW metrics_summary
BUILD IMMEDIATE
REFRESH FORCE ON DEMAND
AS
SELECT pid,
getProductMetrics(pid,mydate AS annual_metric,
mydate
FROM products,mydates
or it would take forever?
Also, how and how often would I update this MV?
Metrics data is required for the end of each year.
But any year's data could be requested at any time.
Note, that I have no control over the slow function - it's just a given.
thanks.
First, you do not have a "group by" query, so you can remove that.
An MV would be most useful if you needed to recompute all of the data for all years. As this appears to be a summary, with no need to reprocess old data, updated only when certain threshold dates like end of year are passed, I would recommend putting the results in a normal table and only adding the updates as often as your threshold dates occur (annually?) using a stored procedure. Otherwise your MV will take longer to run and require more system resources with every execution that adds a new date.
Do not create a materialized view. This is not just a performance issue. It is also an archiving issue: You don't want to run the risk that historical results could change.
My advice is to create a single table with a "year" column. Run the query once per year and insert the rows into the new table. This is an archive of the results.
Note: If you want to recalculate previous years because the results may have changed (say the data is updated somehow), then you should store those results in a separate table and decide which version is the "right" version. You may find that you want an archive table with both the "as-of" date and the "run-date" to see how results might be changing.

How to create a relationship where all columns have many details

I am working in a small personal project about capital expenses. There is one part I can't figure it out.
The tables i have are the following:
capex_form
capex_cashflow
When I create a capex_form I am able to request money and divide this money however I want in 13 months including this month (to show how I I will pay it in the next year). this will reflect in capex_cashflow who has 13 columns with either an amount or 0.
The problem comes here:
I need to be able to add many descriptions for each payment. For example:
in July 2019 I will spend 200 ( this is done), I need to enter a breakdown of this 200 dollars and a description. 50 dollars on one thing and 150 on another thing.
I added 3 columns per month which works, But then it will only let me add one description per month.
I was thinking I might be able to create another table for description, but how this is going to related to a specific column(month). As far as my brain gives, you relate one table with another table not column.
I also was thinking to create 13 tables for 13 months, but I think there should be something I am missing to avoid to create 13 unnecessary tables.
I appreciate any kind of help or guidance
This is pretty straightforward and a common thing.
Put an index column in the "header" table. The header table is a summary of the information, so in your case may you create a table that just takes the capex_income.
CAPEX_FORM
Capex_id
Capex_Amount
Then create a payment table, the payment table can have a month column (only 1) and a capex_Id column, along with a description or whatever else you need
CAPEX_PAYMENT
Capex_payment_id
Capex_id
Payment_Amount
Month (1-13)
Description
Now because you have the Capex_id in this table, it will be related to the CAPEX table and you will be able to query all the payments that are associated like so
select payment_amount, month, description from capex_payment p join capex_form f on p.capex_id = f.capex_id

I need to calculate values for a record in a database based off of other values in other records

I need to calculate values for a record in a database based off of other values in other records. Using SqlServer 2012, what would be the best way to do this? I'm thinking some type of script that runs on the server that may be able to query for the values it needs to compute, compute them, and insert them into the record it needs to. I know you can have computed columns based off of other columns in SqlServer, but what about new records based off of different columns in different records?
Thanks!
EDIT:
I'm using a google charts table on an MVC4 Razor website to show items purchased by specific users by month and year; looks something like this:
Email Address | Purchase Value | Year | Month
This currently works absolutely fine. I query the database for purchases by user and group by month and year and sum the purchases, and I put the values in the table. I also have category filters that only show one month and one year, so only one user is shown at a time.
Now management wants an 'All' selection on the category filter, which means that for every month of every year, and every year total, I'm going to have to compute a cumulative purchase value for each user and put it in the table; you can imagine, if the users list gets very long, this could take some time. So, I think the best option would probably be to have a script that groups purchases by year and by user and updates a new record every time a donation is made anytime within that year; obviously, you'd do the same for each month of the year. That way, I wouldn't have to worry about computing this when the user requests the page. I'm just not sure how to go about writing a script for SQLServer that would be able to do something like this.
This shows how to calculate values for a record in a database based off of other values in other records. The example is written in TSQL and can be executed on SQL Server. You will need to change the script to use your tables and columns.
DECLARE #total dec(12,2), #num int --Variable declaration
SET #total = (SELECT SUM(Salary) FROM Employee) --Capture sum of employee salaries
SET #num = (SELECT COUNT(ID) FROM Employee) --Capture the number of employees
SELECT #total 'Total', --calculate values for a record in a database based off of other values in other records
#num 'Number of employees',
#total/#num 'Average'
INTO
dbo.AverageSalary
Hope this helps.

Crystal Report XI - Conditional Sum Issue

I have a table with data called InvoiceShipments. It continues a row for each product shipped on an invoice. Each product belongs to a product category, which I can query and filter by. Some of the products are finished good products with a Bill of Material, where the Bill of Materials (BOM) is a list of the parts that combine to make the finished good.
In the InvoiceShipments table, the finished good is listed with a price but no cost. It is then followed by the components (BOM) of that finished good, which in turn have a cost but no price. I have a separate table that lists all of the component items and which finished goods it goes to. Note that component goods can belong to more than one BOM.
I can currently filter the InvoiceShipments by the products that I want based on the product category (from a join to a different table). What I want to do is grab that finished good number, and get a list of all the part #s that make up that BOM, then go back to the InvoiceShipments and sum the costs for all of the rows that match those component #s and invoice#. But I haven't been using Crystal long enough to know what to do at the query level, what to do with a command table, what to do with a formula, etc.
Sample Screenshots:
Top table in the gallery is BOM table, second table is the InvoiceShipments, and the third is the desired outcome.
Any help would be appreciated.
From what I gather you want to combine the invoice number but use the finished product information. I've done something similar, solution is a little weird but it works. You only need your InvoiceShipments table
Group by invoice number
Create a formula for Order ID, SKU and ProductName
IF Price <> 0 AND Cost = 0 THEN
Orider ID '<-Change this according to the formula (SKU, ProductName)
ELSE
""
Insert-> Summary on each of the formula as Maximum and place it on the grouped invoice line.
Since the Quantity is constant you can put that field on the grouped invoice line.
Insert-> Summary on Price then on Cost using SUM and place it on the grouped invoice line.
Hide the details.
This should give you the result you need. What's happening is because your formula is only printing the finished goods information, the other items are blank. So when you use MAXIMUM, the non-blank items will print.
Hope this helps.
NEW SOLUTION
I don't have any tables or views that is setup like your data so I can't test this solution, but hopefully there is enough info that you can formulate a good solution
I noticed that you can't use the materials in the InvoiceShipments to idenfity the Finished Product in BillofMaterials. The Materials repeats itself. We'll have to identify them using the finished product.
Add in InvoiceShipments and rename it InvoiceShipments1 (when adding tables, the right side windows, right click on the table and rename.
Using select expert, isolate your finished products. (Price <> 0 and Cost = 0)
Database -> Database Expert. Add in your BillofMaterials table. Link SKU to ProductSKU. Left Outer Join
Now the materials are associated with an invoice number, We can try and link another copy of the INvoiceShipments to the BOM. This is tricky.
Database -> Database Expert. Add in your InvoiceShipments table rename to InvoiceShipments2. Link InvoiceShipments2.invoice# to InvoiceShipments1.Invoice#, and InvoiceShipments2.SKU to Material#. Use Left Outer Join
Create a formula that alternates between InvoiceShipments1 and InvoiceShipments2 on columns OrderID, SKU, and ProductName
IF ISNULL({InvoiceShipments1.OrderID}) THEN
{InvoiceShipments2.OrderID}
ELSE
{InvoiceShipments1.OrderID}
Create a formula combining InvoiceShipments2.invoice# and SKU (SKU formula version)
Group by formula in previous step (If the invoice contains 2 finished products, it will create 2 lines for one invoice.
On the GF put InvoiceShipments2.invoice#, OrderID (formula version), SKU (formula version), ProductNmae (formula version), InvoiceShipments2.quantity, Summerize(InvoiceShipments2.price), Summerize(InvoiceShipments2.cost)
Hide GH
Hope it works!