How to associate 2 fields in the same table / data structure? - database

On my website you can purchase a trip after choosing the departure date (among the available departure dates), knowing that each departure date has a specific price attached to it.
How should I define the [departure date / price] couples from an algorithmic point of view? I suppose they can't simply be 2 fields of the Trip table / data structure, among other fields, because these 2 fields are actually a couple. What then? Should they be contained in a separate table / data structure altogether ?
Just in case I'm working with WordPress on this project.

In my opinion should be table DEPARTURE_TERMS, table PRICES and DEPARTURE_PRICES_MAPPER where You have key ID and pair ID_DEPARTURE_TERMS , ID_PRICES. Now You define all your departures terms with prices and get as
SELECT dpm.id, dt.date, pr.price FROM DEPARTURE_PRICES_MAPPER dpm
JOIN DEPARTURE_TERMS dt ON (dpm.ID_DEPARTURE_TERMS = dt.ID)
JOIN PRICES pr ON (pr.ID = dpm.id.PRICES)
WHERE dt.date >= '2014-04-12' AND dt.date <= '2014-05-11'

Related

Store all dates in one table

I have many tables in my database and each one has one or two fields which is DATE field. This is increasing my database size so I am thinking to store all DATE fields in one table and add relationship to all tables. Is it possible and a good idea or not?
My database, example:
Old design
tblCustomer = > CustomerID, Surname, Name, DateFirstVisit, DateStopped
tblOrder = > OrderID, CustomerID, DateOrder, Order, DateShiped
tblPayment = > PaymentID, CustomerID, DatePayment, Price, DateCheck
New design
tblCustomer = > CustomerID, Surname, Name, DateInID, DateOutID
tblOrder = > OrderID, CustomerID, DateInID, Order, DateOutID
tblPayment = > PaymentID, CustomerID, DateInID, Price, DateOutID
tblDateIn = > DateInID, DateIn
tblDateOut = > DateOutID, DateOut
Can I combine tblDateIn and tblDateOut?
Thank you...
Technically, yes, you can further normalize your database this way. You could go so far as to have a Dates table that just has every date in it and use those dates by reference to a DateID, but this is over-normalization.
In addition to making simple queries more complicated because you will have to join to the dates table every time, I think you'll find that you don't save that much space and might possibly use more space. I don't know for certain what Access uses, but dates are typically stored internally as decimal values or an integer representing a count of seconds since a starting date. In any case, the space you would save in your tables by having an integer key versus Access' internal date value would be tiny and likely offset by having additional tables and indexes involved in foreign keys.

Creating a function to add a calculated column to a table in SQL Server based on a query

I have 2 database tables called Spend, and VendorSpend. The columns used in the Spend table are called VendorID, VendorName, RecordDate, and Charges. The VendorSpend table contains VendorID and VendorName but with distinct data (one record for each unique VendorID). I need a simple way to add a column to the VendorSpend table called Aug2015, this column will contain the SUM of each Vendor's charges within that month time period. It will be calculated based on this query:
Select Sum(Charges)
from Spend
where RecordDate >= '2015-08-01' and RecordDate <= '2015-08-31'
Keep in mind this will need to be called whenever new data is inserted into the Spend table and the VendorSpend table will need to update based on the new data. This will happen every month so actually a new column will need to be added and the data be calculated every month.
Any assistance is greatly appreciated.
Create a user-defined function that you pass a VendorID and Date to and which does your SELECT:
Select Sum(Charges)
from Spend
where VendorID=#VendorID
AND DATEDIFF(month, RecordDate, #Date) = 0
Now personally, I would stop right there and use the function to select your data at query time, rather than adding a new column to your table.
But treating your question as academic, you can create a computed column called [Aug2015] in VendorSpend that passes [VendorID] and '08/01/2015' to this function and it will contain the desired result.

CakePHP - How to use calculations from associated data in query

I'm trying to figure out the best way to do something - basically I'm looking for advice before I do it the long/hard way!
I have the following model associations:
Seller hasMany Invoices
Invoice hasOne Supplier
Supplier belongsTo SupplierType
Each invoice is for a certain amount and is from a certain date. I want to be able to retrieve Sellers who have spent within a certain amount in the past 'full' month for which we have data. So, I need to get the date 1 month before the most recent invoice, find the total on all invoices for that Seller since that date, and then retrieve only those where the total lies between, say, £10000 and £27000 (or whatever range the user has set).
Secondly, I want to be able to do the same thing, but with the SupplierType included. So, the user may say that they want Sellers who have spent between £1000 & £5000 from Equipment Suppliers, and between £1000 & £7000 from Meat Suppliers.
My plan here is to do an inital search for the appropriate supplier type id, and then I can filter the invoices based on whether each one is from a supplier of an appropriate type.
I'm mainly not sure whether there is a way to work out the monthly total and then filter on it in one step. Or am I going to have to do it in several steps? I looked at Virtual Fields, but I don't think they do what I need - they seem to be mainly used to combine fields from the same record - is that correct?
(Posted on behalf of the question author).
I'm posting the eventual solution here in case it helps anyone else:
SELECT seller_id FROM
(SELECT i.seller_id, SUM(price_paid) AS totalamount FROM invoices i
JOIN
(SELECT seller_id, MAX(invoice_date) AS maxdate FROM invoices) sm
ON i.seller_id = sm.seller_id
WHERE i.invoice_date > (sm.maxdate - 30) GROUP BY seller_id) t
WHERE t.totalamount BETWEEN 0 AND 1000
This can be done in a single query that will look something like:
select * from (
select seller, sum(amount) as totalamount
from invoices i join
(select seller, max(invoicedate) as maxdate from invoices group by seller) sm
on i.seller=sm.seller
and i.invoicedate>(sm.maxdate-30)
group by seller
) t where t.totalamount between 1000 and 50000

MSSQL Finding Total of a column and carry other data with it

I have the following table to work with, which I can not change. I have to work with what I have.
Id (int auto int)
CustomerName (varchar)
CustomerNumber (int)
Date (date)
WeeklyAmount (int)
What I would like to do is grab all the data per customer and add all the weekly amounts for a specific year. Eventually I will want to compare two years together, but right now I am working on the data to sum up the weekly totals per CustomerNumber.
I am using:
Select
CustomerNumber, SUM (WeeklyAmount) as Total from
Customers.RECORDS GROUP BY CustomerNumber;
This works fine, however, I want to return the CustomerName as well. Eventually I will have to place in the SQL for getting specific years and compare them. However, I have to tackle this part first.
Assuming there is a 1-to-1 relationship between CustomerName and CustomerNumber:
Select
CustomerNumber, CustomerName, SUM (WeeklyAmount) as Total from
Customers.RECORDS GROUP BY CustomerNumber, CustomerName;
If the relationship is not 1-to-1, then I suppose you'd need to define what exactly represents a customer in the phrase grab all the data per customer.

Best structure for inventory database

I want to create a small database for my inventory but I have some problems on picking a structure. The inventory will be updated daily at the end of the day.
The problem I am facing is the following.
I have a table for my products, having an
id, name, price, quantity.
Now I have another table for my sales, but there is my problem. What kind of fields do I need to have. At the end of the day I want to store a record like this:
20 product_x $ 5,00 $ 100,-
20 product_y $ 5,00 $ 100,-
20 product_z $ 5,00 $ 100,-
20 product_a $ 5,00 $ 100,-
-------------------------------------------------
$ 400,-
So how do I model this in a sales record. Do I just create a concatenated record with the product id's comma separated.
Or is there another way do model this the right way.
This is a model which supports many aspects,
Supports Sites, Locations and Warehouses etc.
Supports Categorization and Grouping
Support Generic Product (Ex. "Table Clock" and specific product "Citizen C123 Multi Alarm Clock" )
Also support Brand Variants (by various manufacturers)
Has CSM (color / size / model support) Ex. Bata Sandles (Color 45 Inch Blue color)
Product Instances with serials (such as TVs , Refrigerators etc.)
Lot control / Batch control with serial numbers.
Pack Size / UOM and UOM Conversion
Manufacturer and Brands as well as Suppliers
Also included example transaction table (Purchase order)
There are many other transaction types such as Issues, Transfers, Adjustments etc.
Hope this would help. Please let me know if you need further information on each table.
Cheers...!!!
Wajira Weerasinghe.
Sites
id
site_code
Site_name
Warehouse
id
site_id
warehouse_code
warehouse_name
Item Category
id
category_code
category_name
Item Group
id
group_code
group_name
Generic Product
id
generic_name
Product
id
product_code
category_id
group_id
brand_id
generic_id
model_id/part_id
product_name
product_description
product_price (current rate)
has_instances(y/n)
has_lots (y/n)
has_attributes
default_uom
pack_size
average_cost
single_unit_product_code (for packs)
dimension_group (pointing to dimensions)
lot_information
warranty_terms (general not specific)
is_active
deleted
product attribute type (color/size etc.)
id
attribute_name
product_attribute
id
product_id
attribute_id
product attribute value (this product -> red)
id
product_attribute_id
value
product_instance
id
product_id
instance_name (as given by manufacturer)
serial_number
brand_id (is this brand)
stock_id (stock record pointing qih, location etc.)
lot_information (lot_id)
warranty_terms
product attribute value id (if applicable)
product lot
id
lot_code/batch_code
date_manufactured
date_expiry
product attribute value id (if applicable)
Brand
id
manufacturer_id
brand_code
brand_name
Brand Manufacturer
id
manufacturer_name
Stock
id
product_id
warehouse_id, zone_id, level_id, rack_id etc.
quantity in hand
product attribute value id (if applicable) [we have 4 red color items etc.]
Product Price Records
product_id
from_date
product_price
Purchase Order Header
id
supplier_id
purchase_date
total_amount
Purchase Order Line
id
po_id
product_id
unit_price
quantity
Supplier
id
supplier_code
supplier_name
supplier_type
product_uom
id
uom_name
product_uom_conversion
id
from_uom_id
to_uom_id
conversion_rule
I'd have a table with a row per item per day - store the date, the item ID, the quantity sold, and the price sold at (store this even though it's also in the product table - if that changes, you want the value you actually sold at preserved). You can compute totals per item-day and totals per day in queries.
Tables:
create table product (
id integer primary key,
name varchar(100) not null,
price decimal(6,2) not null,
inventory integer not null
);
create table sale (
saledate date not null,
product_id integer not null references product,
quantity integer not null,
price decimal(6,2) not null,
primary key (saledate, product_id)
);
Reporting on a day:
select s.product_id, p.name, s.quantity, s.price, (s.quantity * s.price) as total
from product p, sale s
where p.id = s.product_id
and s.saledate = date '2010-12-5';
Reporting on all days:
select saledate, sum(quantity * price) as total
from sale
group by saledate
order by saledate;
A nice master report over all days, with a summary line:
select *
from (
(select s.saledate, s.product_id, p.name, s.quantity, s.price, (s.quantity * s.price) as total
from product p, sale s
where p.id = s.product_id)
union
(select saledate, NULL, 'TOTAL', sum(quantity), NULL, sum(quantity * price) as total
from sale group by saledate)
) as summedsales
order by saledate, product_id;
Try modelling your sales as a transaction - with a "header", i.e. who sold to, when sold, invoice # (if applicable), etc. and "line items", i.e. 20 * product_x # $5 = $100. The safest approach is to avoid relying upon prices etc. from the products table - as these will presumably change over time, and instead copy much of the product information (if not all) into your line item - so even when prices, item descriptions etc. change, the transaction information remains as was at the time the transaction was made.
Inventory can get quite complex to model. First you need to understand that you need to be able to tell the value of the inventory onhand based on what you paid for it. This means you cannot rely on a product table that is updated to the current price. While you might want such a table to help you figure out what to sell it for, there are tax reasons why you need to know the actual vlaue you paid for each item in the warehouse.
So first you need the product table (you might want to make sure you have an updated date column in this, it can be handy to know if your prices seem out of date).
Then you need a table that stores the actual warehouse location of each part and the price at purchase. If the items are large enough, you need a way to individually mark each item, so that you know what was taken out. Usually people use barcodes for that. This table needs to be updated to record that the part is no longer there when you sell it. I prefer to make the record inactive and have a link to my sales data to that record, so I know exactly what I paid for and what I sold each part for.
Sales should have at least two tables. One for the general information about the sale, the customername (there should also be a customer table most of the time to get this data from), the date, where it was shipped to etc.
Then a sales detail table that includes a record for each line item in the order. Include all the data you need about the part, color, size, quantity, price. This is not denormalizing, this is storing historical data. The one thing you do not want to do is rely on the prices in the product table for anything except the inital entry to this table. You do not want to do a sales report and have the numbers come out wrong becasue the product prices changed the day before.
Do not design an inventory database without consulting with an accountant or specialist in taxes. You also should do some reading on internal controls. It is easy to steal from a company undetected that has not done their work on internal controls in the database.
I think you need a table with fields showing the transaction properties per customer
OR
a table with fields - date, product(foreign), quantity - this way you'll have no problem with new products
Try multiple tables with links
table_products
id
name
table_product_sales
id
product_id
quantity
price_per
transaction_time AS DATETIME
SELECT table_product_sales.*, table_product.name
FROM table_product
JOIN table_product_sales
ON table_product_sales.product_id = table_product.id
GROUP BY DATE(transaction_time)
Haven't tried it but will something like that work? That allows you to keep each transactions separate so you can query things like average number sold per sale, total sold per date, total sales each day, etc.

Resources