Database normalization : where does unit price stands? - database-normalization

I'm having confusion whether i should put unit price of item in Item table or Order table?
Given table:
SalesOrderNo, Date, CustomerNo, CustomerName, CustomerAdd, ClerkNo, ClerkName, ItemNo, Description, Qty, UnitPrice
I did this solution:
SalesOrderDetail: SalesOrderNo, CustomerNo, Qty, ClerkNO
Customers: CustomerNo, CustomerName, CustomerAdd
Clerks: ClerkNo, ClerkName
Items: ItemNo, UnitPrice, Description
But MAM gave following solution:
Customers: CustomerNo, CustomerName, CustomerAdd
Clerks: ClerkNo, ClerkName
Inventory Items: ItemNo, Description
Sales Orders: SalesOrderNo, Date, CustomerNo, ClerkNo
SalesOrderDetail: SalesOrderNo, ItemNo, Qty, UnitPrice
Which one is right?
And specifically unit price, shouldn't it depend on item rather then order?

Think about all the scenarios where this data will be used. I would actually say that the UnitPrice in fact goes on both tables.
When looking at a catalog or inventory report, users may wish to see what the current asking price for each Item is, and that price is dependent only on the Item. However, when an order is placed, there may be a reason to alter the price for that order, without changing the normal price of the item. Perhaps the salesman had to give a little discount in order to make the sale. Perhaps the item was part of an incentive program. Maybe next week the asking price of the item will go up because of supply chain issues, but any orders already processed need to retain the price at the time they were made (otherwise, the invoices won't balance).

Related

How to create MS Access data entry form with rolling 12 months for each row

I'm creating a data entry form in Access where sales people can select a product, then enter a quantity for that product in each of 12 columns representing the next twelve months. For a given project, there may be up to ten products, so each product will be on a separate row.
Tables:
Project - fields ProjectID, ProjectName, City, SalespersonID, StartDate
ProjectDetail - fields ProjectDetailID, ProjectID, ProductID, Date, Quantity
Product - fields ProductID, ProductName
Salesman - fields SalespersonID, SalespersonName
Currently I have the Project form with the simple project header information, and I want the ProjectDetail information to be a subform, of course. But - when I used a query to give me "buckets" of Quantity for Month0 (the current month), Month1, Month2, etc., I found that I can't enter data into the form because the fields are based on an expression.
What's the best way to handle this? Thanks in advance!
If each ProjectDetail entry will have multiple sets of Date and Quantity, it might be wise to pull those out into a separate table with a one-to-many relationship to ProjectDetailID, especially if you anticipate the number of date/quantity pairs could change from twelve. So, a ProjectDetailQuantity table would have fields ProjectDetailQuantityID, ProjectDetailID, Date, Quantity. On your form, you would have the Project main form, with a sub form to ProjectDetail and another subform to ProjectDetailQuantity.

How do I add multiple subtotals in tableau?

My report has the following structure
ID , Currency, Subdepartment, Unit , Revenue, Salary
I wanted to print the subtotals of Revenue and Salary for the following combinations
(ID, Currency, Subdepartment)
(ID, Currency, )
The row has discrete dimensions hence the default grandtotal/subtotal option is not working .
is thr an alternate to calculate the subtotals and display beneath each grouping.?
If you're hoping to see this in a single worksheet, it sounds like a job for LOD (level-of-detail) functions. I'm not sure how you want to visualize it, but here's how you could simply make a table.
Create some calculated fields:
Revenue Total (ID, Currency)
{ FIXED [Id], [Currency] : SUM([Revenue]) }
Salary Total (ID, Currency)
{ FIXED [Id], [Currency] : SUM([Salary]) }
We can then create a table (for example) with the subtotals and totals by placing the following pills in the Rows shelf, in this order:
[ID]
[Currency]
SUM([Revenue Total (ID, Currency)]) (Make it discrete)
SUM([Salary Total (ID, Currency)]) (Make it discrete)
[Subdepartment]
SUM([Revenue]) (Make it discrete)
SUM([Salary]) (Make it discrete)
The resulting table will look something like this:
ID Currency Total Revenue Total Salary Subdepartment Revenue Salary
----------------------------------------------------------------------------------
A Dollars $200 $100 R $140 $30
S $60 $70
Manat ₼4000 ₼8000 R ₼1000 ₼7000
S ₼3000 ₼1000
Yen ¥500 ¥1000 R ¥100 ¥300
S ¥200 ¥500
T ¥200 ¥200
B Dollars $300 $700 R $200 $600
S $100 $100
Manat ₼7000 ₼3000 R ₼2000 ₼1000
S ₼3000 ₼1000
T ₼2000 ₼1000
Yen ¥900 ¥400 R ¥150 ¥100
S ¥250 ¥100
T ¥300 ¥200
All that said, FirebladeDan makes a great point in the comments of your question. Tableau is NOT Excel – it's a visualization tool, and a smokin' one at that. If you want to show aggregations of measures at different levels of detail, your best option (both in terms of what Tableau can easily do and the clearest way to visualize it) is usually going to be to create a dashboard with multiple worksheets at different levels of detail and to take advantage of filter actions and other controls to see how it all relates.

Comparing Records In Crystal Reports

So I want to compare some records in Crystal Reports to take care of a problem a bug in our system has caused.
So every once in a while our system charges someone twice. I want to find all those orders/shipments. An order can have multiple shipments (if we have one item on backorder we ship out the rest of the order in one shipment and then ship out the backordered item in another shipment). The shipment also has a charge_date field that's a date time stamp when we charged the customer. So if we grouped it in Crystal reports it would look like this:
Order Id: 234587
Shipment Id: 121 charge_date: 8/29/2012 11:43:21
Shipment Id: 524 charge_date: 9/1/2012 15:37:39
Shipments are created in numerical order. So if we send out one shipment, say shipment number: 345, then the next shipment we send out, regardless of what order it's a part of, will be shipment number: 346.
So, when someone is a victim of our bug then their shipments are right after one another and their charge_date are exactly the same. Like so:
Order Id: 69875
Shipment Id: 594 charge_date: 9/2/2012 14:32:15
Shipment Id: 595 charge_date: 9/2/2012 14:32:15
I can create a list of just shipments and their charge date (without grouping on Order Id) and sorting them in ascending order. But what I want to do is iterate through the list of shipments and compare each shipment to the previous shipment and see if the charge_date's are equal and if they are then select them or mark them or something so that I can group them by a formula and take care of them.
Is this possible in Crystal? Should I use a different program? I realize this might not be the best way to do this so I'm open to suggestions. Thanks in advance!
Can you create groups for the orderID and chargeDate, then suppress all shipment details unless the count(shipmentID) > 1?
You'd display the shipment details in the chargeDate group footer.
Use the Previous function:
// {#Is Error}
If Previous({table.chargeDate})={table.chargeDate}) Then
true
Else
false
Insert a group in this formula.
I'm not able to test this, as I'm not at my work computer.

Sql GroupBy with one more field in the result set as in the group by clause

I have a table with different offers which are bound to a specific date. depended on the date the price changes. i want to get the cheapest deal for each date.
my problem is i use a group by like:
select price, date from deals group by date, price
to display the offer, i need more records which are not in the group by clause. the best field would be my autoid, so if a customer selects a offer with a specific price i can display this offer with all its fields using a second select.
i hope this makes it simpler to answer my question. i tried to keep it generic as possible but i have the feeling it was not described clear enough :-)
Just add the Id column into the GROUP BY list
SELECT id, date, price
FROM products
GROUP BY id, date, price
Otherwise Sql Server was not able identify which id is to return for grouped by price and date rows, for instance consider two following rows:
1 | 10-10-2010 | 100 |
2 | 10-10-2010 | 100 |
Which Id value should be selected for row which is grouped by date and price?
??? | 10-10-2010 | 100 |
You either need to specify an aggregate function on ID or add it to your group by clause like #sll suggested. Aggregate example:
SELECT MAX(id), date, price
FROM products
GROUP BY date, price
If you remove the id from Select clause, you will have a list of all distinct couples of date and price.
If you add the id to the Group By clause, since it is an identity, you will obtain a row per every record in your table, so that your Group By clause won't be useful.
The third way is to use an aggregate function on id in the Select clause to obtain one value for every single group (the first, the min, the max, etc.).
Hi Group by is useful when you are doing count etc.
SELECT [Display Billing Provider], [Display Insurance Category]
, SUM([TOTAL RVUs]) AS RVUs_08
, SUM([Units]) AS Units_08
, SUM(Payments) AS Payments_08
FROM dbo.ProductivityAnal_2008
GROUP BY [Display Billing Provider],[Display Insurance Category]
ORDER BY [Display Billing Provider],[Display Insurance Category]
Thanks Abe

Faster CROSS JOIN alternative - PostgreSQL

I am trying to CROSS JOIN two tables, customers and items, so I can then create a sales by customer by item report. I have 2000 customer and 2000 items.
SELECT customer_name FROM customers; --Takes 100ms
SELECT item_number FROM items; --Takes 50ms
SELECT customer_name, item_number FROM customers CROSS JOIN items; Takes 200000ms
I know this is 4 million rows, but is it possible to get this to run any faster? I want to eventually join this with a sales table like this:
SELECT customer_name, item_number, sales_total FROM customers CROSS JOIN items LEFT JOIN sales ON (customer.customer_name = sales.customer_name, item.item_number=sales.item_number);
The sales table will obviously not have all customers or all items, so the goal here is to have a report that shows all customers and all items along with what was sold and not sold.
I'm using PostgreSQL 8.4
To answer your question: No, you can't do a cross join faster than that - if you could then that would be how CROSS JOIN would be implemented.
But really you don't want a cross join. You probably want two separate queries, one which lists all customers, and another which lists all items and whether or not they were sold.
This really needs to be multiple reports. I can think of several off the top of my head that will yield more efficient packaging of information:
Report: count of all purchases by customer/item (obvious).
Report: list of all items not purchased, by customer.
Report: Summary of Report #2 (count of items) in order to prioritize which customers to focus on.
Report: list of all customer that have not bought an item by item.
Report: Summary of Report #3 (count of customers) in order to identify both the most popular and unpopular items for further action.
Report: List of all customers who purchased an item in the past, but did not purchase it his reporting period. This report is only relevant when the sales table has a date and the customers are expected to be regular buyers (i.e. disposable widgets). Won't work as well for things like service contracts.
The point here is that one should not insist that the tool process every possible outcome at once and generate more data and anyone could possibly digest manually. One should engage the end-users and consumers of the data as to what their needs are and tailor the output to meet those needs. It will make both sides' lives much easier in the long run.
If you wish to see all items for a given client (even if the cient has no items), i would rather try
SELECT c.customer_name, i.item_number, s.sales_total
FROM customers c LEFT JOIN
sales s ON c.customer_name = s.customer_name LEFT OIN
items i on i.item_number=s.item_number
This should give you a list of all clients, and all items joined by sales.
Perhaps you want something like this?
select c.customer_name, i.item_number, count( s.customer_name ) as total_sales
from customers c full join sales s on s.customer_name = c.customer_name
full join items i on i.item_number = s.item_number
group by c.customer_name, i.item_number