Hello Stack Overflowers,
I'm redesigning a system for an ordering group.
We have a hundred or so companies (ordering accounts) that order from us.
And maybe 40 of those companies also have online stores (admin accounts) with us.
An online store has a customer list of users that belong to their store, and the admin account lets them create and manage customers and customer orders.
So the customer shops, and when finished the order goes to the company.
The company verifies the order (combines orders to save shipping if they want) and then send it(/part of it) to us or fill it(/part of it) from their inventory.
We pack their order at our warehouse and ship it to the address on the order.
And we invoice the company.
The company then settles payment with their customer. (we never bill a customer directly)
Hopefully that wasn't too convoluted...
So again, we never bill a 'customer' directly. But in our current system, we store all accounts (ordering, admin, AND customers) in the same way.
While considering the redesign, I've questioned if this is the most logical approach. And I was thinking of storing our billable accounts (ordering and admin) in an accounts table and customers in a separate customers table.
The way I was thinking of setting this up was, our accounts have an accountID XXXXX, while users have a similar userID YYYYY, but are identified by a composite key of the two (XXXXX-YYYYY)
So company A's first customer is AAAAA-000001 and company B's BBBBB-00001. This seems fine when I think about things like customer orders being billed to their parent company, and displaying all of a companies customers, etc.
But is it a bad idea to have a customer table where customers non-unique customerIDs, even if that isn't the Primary Key?
I know I could make it work, but is it suboptimal when doing something like a customer_address table that relates a customerID and an addressID? Wouldn't it then need to use an accountID + customerID right?
Originally I was thinking they would all be accounts, and the account number would just be structured that way AAAAA-00000 being the admin account, AAAAA-00001 being customer 1, and so one.
But that brings me back to, should our accounts table treat our clients/billable accounts and their customers the same?
Sorry if this question is kind of all over the place. I think that demonstrates how unsure I am of how it should all be structured...
Any input would be greatly appreciated.
Related
If a user can have multiple addresses and phone numbers, is it possible to design the database in such a way that I can enforce integrity between data?
For example:
users(id,name)
addresses(id, description, user_id -FK to users)
phones(id, description, user_id -FK to users)
orders(id,address_id -FK addresses,phone_id - FK to phones)
How can I be sure that in the orders table I won't accidentally insert a record with user1 address and user2 phone number?
I'm sorry if this was asked before but I don't know how to search for this situation.
Where is the Orders table? It will have columns user_id, address_id, and phone_id.
For data entry, if a known user calls in an order, then the UI brings up the existing addresses and phones for that user. The order-taker can quickly click on them. Or the user can say to use a different address. Then the UI assists in adding a new address for that user.
I'm a beginner in SQL and Database management, I have an idea that I don't know how to model into database tables.
I have these tables : users, orders, bills, lessons, tickets, coaches.
Lessons are posted by coaches.
The users are able to order lessons.
A bill is registered after the order.
The users are also able to order tickets.
A ticket gives access to a lesson.
When users buy a ticket, the coache benefit or half or the ticket price.
So when a user buy a ticket that costs 6$ for a specific lesson, the coache who owns the lesson will get 3$.
Do I need another bills table for the coaches? or I can use the same bills table to register their gains from the purchased lessons?
I really have no idea how to achive my List of ideas above, sorry.
For now I've just managed to do this, I don't know how to complete the rest of the DB.
|bills|<--|orders| *<------ |users|
|
v
*
|order_lesson|
*
/\
|
|lessons| *<----- |coaches|
I can't ask you for a complete answer, but I really need some explication or guidance.
From what I can tell the ticket is no different then a regular order and can be placed with the orders as the only difference is the money the coach gets. So maybe just a column in the orders table would signify the type of order.
|bills|<--|orders|<----|users|
/ \
|
|lessons|<---|coaches|
I have a schema design question for my application, hope I can get advices from teachers. This is very alike of Role Based Access Controll, but a bit different in detail.
Spec:
For one company, there are 4 roles: Company (Boss) / Department (Manager) / Team (Leader) / Member (Sales), and there are about 1 million Customers records. Each customer record can be owned by someone, and he could be Boss or Manager or Leader or Sales. If the record's owner is some Sales, then his upper grade (say: his leader / manager / boss) can see this record as well (but others: say the same level of his workmates, cannot see, unless his upper grade manager share the customer to his workmates), but if the record's owner is boss, none except the boss himself can see it.
My Design is like this (I want to improve it to make it more simple and clear):
Table:
departments:
id (P.K. deparment id)
d_name (department name)
p_id (parent department id)
employees
id (P.K. employee id)
e_name (employee name)
employee_roles
id (P.K.)
e_id (employee id)
d_id (department id)
customers
id (P.K. customer id)
c_name (customer name)
c_phone (customer phone)
permissions
id (P.K.)
c_id (customer id)
e_id (owner employee id)
d_id (this customer belongs to which deparment)
share_to (this customer share to other's id)
P.S.: each employee can have multi roles, for example, employee A can be the manager of department_I and meanwhile he can also be one sales of deparment_II >> Team_X.
So, when an employee login to application, by querying from employee_roles table, we can get all of the department ids and sub department ids, and save them into an array.
Then I can use this array to query from permissions table and join it with customers table to get all the customers this employee should see. The SQL might look like this:
SELECT * FROM customers AS a INNER JOIN permissions AS b ON a.id =
b.c_id AND (b.d_id IN ${DEP_ARRAY} OR e_id = ${LOGIN_EMPLOYEE_ID} OR
share_to = ${LOGIN_EMPLOYEE_ID})
I don't really like the above SQL, especially the "IN" clause, since I am afraid it will slow down the query, since there are about 1 million records or even more in the customer table; and, there will be as many records as the customers table in the permissions table, the INNER JOIN might be very slow too. (So what I care about is the performance like everyone :))
To my best knowledge, this is the best design I can work out, could you teachers please help to give me some advice on this question? If you need anything more info, please let me know.
Any advice would be appreciated!
Thanks a million in advance!!
Do not use an array, use a table, ie the value of a select statement. And stop worrying about performance until you know more basics about thinking in terms of tables and queries.
The point of the relational model is that if you structure your data as tables then you can looplessly describe the output table and the DBMS figures out how to calculate it. See this. Do not think about "joining"; think about describing the result. Whatever the DBMS ends up doing is its business not yours. Only after you become knowledgeable about variations in descriptions and options for descriptions will you have basic knowledge to learn about performance.
I am designing a schema for E-Commerce app, in which I would have 3 tables i.e Orders, Products, Customers.
So Should we store customer_id and product_id in Orders table straightaway.
The limitation to this is when a product or customer updates their attributes( i.e product price or customer name ), the orders table doesn't reflect them.
For Ex: A Customer bought a product at $10, but later on the product price gets updated to $20.So now when we are referring to this order by product id we would get the result as it was bought at $20 instead of $10.
SOLUTION 1:
One solution would be to insert a new row into products table whenever an updates occur and perform a soft delete to that product so that it can be referenced from orders table.
SOLUTION 2:
Store most of the details in product and customer details in orders table.
SOLUTION 3:
Create a temporary table of customers and products whenever there is an update to these tables.
I am very much open to any other suggestions.
One thing that you seem to be missing is a orderLineItem table for anything other than the most simple solution, where there is one product/order.
Now, that being said, you can do the products table in several ways.
Assuming that price is your only variable in the products table that you want to change, you can have a separate pricePoints table, that would store the price for any item at any given time. You would then use the ID from this table in your orders table and use that to get to the productID from the products table. A slightly more inefficient way to store this (but faster for retrieval) would be to store both the productId and the pricePointId in the orders table.
You could also do this by simply storing the price paid amount in the orders table. This gives you a little more flexibility to add discounts and pricing rules. You do need to be concerned about auditing the price though if you do it this way. Why was this price charged for this line at this time is going to be a common question.
You need to know how much the customer paid for the product at any time. It's not so important to know how much the customer would have paid for the order if they bought it today.
Customers are a slightly different issue. Some of the information in a customer table is transient. Some of it has to be fixed for the order. Lets say that the customer has a name, address, billing address and shipping address. At the time of the order, the shipping and billing addresses have to be absolutely fixed. You don't want to go back in three weeks and discover that the shipping address was changed. But, by the same token, you might like the name to be updated if a customer changes their maiden name, for example.
Now, all that being said, we aren't going to design your schema for you. There are a lot of good resources out there for how to design a simple e-commerce database.
Having two database tables:
orders (id, client_id, ...) - stores orders of customers
addresses (id, client_id, ...) - stores delivery addresses of customers
Relationship between that tables is many-to-many so I have table
addresses_orders (id, order_id, address_id) which maps where order goes
But I'd like to enforce one thing - in table
addresses_orders can only be paired together orders and addresses of the same customer.
What is the best way to do this?
I have web application based on MVC, which stores data in MySQL database.
Every customer gets only his orders and addresses to choose from, but form can be tampered and malicious user can change address_id to random guess, so it will produce described insonsitency.
For safety I have to validate against this scenario - probably in Model or directly in database.
I prefer second solution, but how to do this? Maybe some triggers?
If there are no overlap in addresses ( only one client per address ), Then your DB structure makes no sense.
Clients Addresses Orders
--- ------- -------
client_id PK address_id PK order_id PK
name client_id FK address_id FK
phone_number full_address data
Then to get all details from an order
SELECT
Clients.name
Addresses.full_address
Orders.data
FROM Orders
LEFT JOIN Addresses USING(address_id)
LEFT JOIN Clients USING(client_id)
WHERE
client_id = 42
This would give you all orders from client with ID 42.
each order has one address
each address has one client
each client has multiple addresses
each address has multiple orders
Is the address_id hidden or visible form field and you are worried that users are capable or willing to mess with it?
I'm guessing your customers are logged in. You could take advantage of session information and user_id (or something). Retrieve the customers address_id in the process file and use that address_id, not the id sent by form (you could of course check if they match). If something goes wrong the problem is probably somewhere in session/application security, but not in the spoofed form.
We tend to use the following approach:
a) Store the customerid in the session
b) When selecting the orders or addresses use one of the following showing the user names while saving the ids:
- A pregenerated list using a select control where only one can be selected
- A pre-generated list from which specific items can be selected using checkboxes