Merging two different tables to form one but keeping related data - sql

Im a little new to Acess and am trying to understand how to merge tables.
My problem is basically this...
I have 2 reports that can be ran and exported to excel. I want to be able to take both reports, combine them, and import the combined result to a table.
In one report.. call it location detail... has the following fields:
ID (PK, and autonumber)
Day (Date call was done)
CallID (Resets every day to 1, and increases by 1 for every new call)
Lat (Lattitude of call)
Long (Longitude of call)
Cost
In the other report.. call it location summary.. has the following fields:
ID (PK, and autonumber)
Location
City
Lat (Lattitude of call)
Long (Longitude of call)
# of Occurences (Number of times there was a call at that location)
The problem is when you have a call in the same location, even though it was on two seperate days, it automatically groups it into the number of occurances. So I tried to run 2 seperate queries from the same range of dates, one matching lat, other matching long, it shows up with duplicates.. my guess is because the ones that do not have a matching lat (because it already used the field once, even though there were 4 occurences) are showing null value and are added to the query as a duplicate.
I want to add the City Column that matches the long/lat data, to the location details report, and then make that into a new table/ and then be able to run the same reports, and add them to the new table, but somehow ensure there arent any duplicates.
My biggest problem is there isnt any real primary key since the Call ID is Dependent on the Date.... I am not sure how to really accomplish this.
Any help would be much appreciated... I am Stumped.
EDIT:
The first Query is to join lattitudes:
SELECT
[Location Detail Report_142].Day, [Location Detail Report_142].[Call ID],
[Location Detail Report_142].Lat, [Location Detail Report_142].Long
FROM [Location Detail Report_142]
LEFT JOIN [Location Summary Report_14]
ON [Location Detail Report_142].Lat = [Location Summary Report_14].Lat;
The second one matches call id:
SELECT qryRelationshipToLat.Day, qryRelationshipToLat.[Call ID],
[Location Summary Report_14].City
FROM [Location Summary Report_14]
INNER JOIN qryRelationshipToLat
ON [Location Summary Report_14].Long = qryRelationshipToLat.Long
ORDER BY qryRelationshipToLat.Day, [Location Summary Report_14].City;
I was thinking maybe it could be possible to make some sort of if-then statement stating that if call id shows duplicate THEN match Call ID... It has to match both, when the original Location Summary report is uploaded, it has 283 reccords, but it shows duplicate locations grouped into anouther field (#_of_Occurances), so the total amount of calls would be the total amount in the Location Detail report, witch in this case is 288. so when I run the first qry - 305 results, and the second qry turns the 305 to 337. So I end up with a lot of just duplicates I guess, or null value ones.
But the two reports both don't include Call ID or Call Numbers. The only information that they share is the LONG and LAT Coordinates. So I would have to match those first, then assign call ID, date, and city to the corresponding coordinates.

I think that you need to learn how to use a GROUP BY statement to aggregate your table. These links may help:
http://www.sqlteam.com/article/how-to-use-group-by-in-sql-server
http://beginner-sql-tutorial.com/sql-group-by-clause.htm
It's possible also that your table designs have to be revised, and presumably your approach for adding to the call record as well.
I'm sorry to just throw some links at you, but I'm not quite up to analyzing what you have got in order to construct a complete answer, and in any case I think you will have to tackle these areas of learning.

Related

Calculated Field in subreport

TL:DR I want a whole column of SQL equivalent of excel's COUNTIFS() Function.
I'm still quite new to MS Access, but I'm quite proficient with Excel. I've inherited an Access Database that tracks reasons for delays in a large logistics group, and am trying to build a report showing which reasons come up most.
So, I can output an SQL report showing all the reasons (they're in a table called 'Reasons', so that bit's easy). What I want is a calculated field next to that column, showing how many times each reason has been cited on the [Master Data] Table (field called 'Lateness Reason') in a given date range. And for double extra bonus points, the percentage they come up would be extremely handy.
I've looked online and found COUNTIFS equivalents for a single set of criteria, but in this case I want it calculating on each row of a report. I've also tried a few things myself, but the closest I could figure was:
SELECT Reasons.Reason, Count([Master Data].[ID]) AS Num
FROM Reasons INNER JOIN [Master Data] ON Reasons.[ID] = [Master Data].[Lateness Reason]
WHERE ((([Master Data].[Lateness Reason])=[Reasons].[Reason]));
which has incorrect syntax and possibly a few other problems (that WHERE clause has to apply equally to all lines, doesn't it?). My only other option might be to do a separate calculation for each line and 'union' them together, but that is likely to cause other problems in the future if more reasons get added (and there are quite a lot already).
Firstly, Is it Possible?
Secondly, If so, How??
Many Thanks in advance
EDIT: In response to comments, table structure is as follows;
Table "Reasons" has two columns; "Reason" and "ID"
Table "Master Data" has many columns, the ones I'd be bothered about are "Date", "ID" and "Lateness Reason" (Lateness reason is equivalent to an ID from table 'Reasons')
Table Reasons
ID Reason
___________________
1 | Stock Shortage
2 | Courier Problems
etc | etc
Master Data
ID Date Reason
__________________
1 | 01/01/1980 | 2
2 | 03/05/2020 | 2
etc
This is how I think your query should look like based on the information you provided.
SELECT Reasons.Reason, Count([Master Data].ID) AS Num
FROM Reasons INNER JOIN [Master Data] ON Reasons.ID = [Master Data].[Lateness Reason]
WHERE ((([Master Data].Date) Between [BeginDate] And [EndDate]))
GROUP BY Reasons.Reason;
Replace [BeginDate] and [EndDate] if you're using form control references.
As for the percentages based on the total, you can use text boxes as #June7 has suggested:
Use a total count in the header or footer of the report =Count(*) and then in the detail add a text box with the following control source: =[Num]/Count(*), where Num is the name of the textbox in your report which holds the counted values per reason. In this case, the control source for Num will be Num based on the query given.
Just a side note, naming your field Date is not advised since it's a reserved keyword in MS Access. It can cause unintended issues along the road.

Create and define functions to apply to different segments/filters that exist (Instead of doing one very long SQL query)

I am trying to come up with some arithmetic calculations for some survey data. I want to do these calculations for a number of segments and want to figure out how to do it without writing numerous SELECT statements.
This is what I have so far:
FACT table. This tables holds survey data at a respondent level - for example, if a survey had 10 questions, this table will have 11 columns: a column to identify the respondent_ID and 10 other columns to identify the responses to those questions.
DIMENSION table. This table segments we want to view the survey data by at a respondent level - for example, if we want to view survey responses by membership_status and age_bracket, this table will have 3 columns: a column to identify the respondent_ID, and two columns to identify membership_status and age_bracket.
OUTPUT.
I want to get aggregate calculations to summarizes the responses to the survey overall and to each question. I also want to be able to get this information for all possible segments that exist in the DIMENSIONS table.
I can do the query below, however I'll need to do this for every segment:
SELECT
COUNT(DISTINCT(CASE WHEN f.QUESTION_1 IN ('8', '9', '10') THEN f.RESPONDENT_ID END))*1.0 / COUNT(DISTINCT(CASE WHEN f.QUESTION_1 IS NOT NULL THEN f.RESPONDENT_ID END))*1.0 AS CSAT_1
FROM FACT f
JOIN DIMENSION d ON f.RESPONDENT_ID = d.RESPONDENT_ID
WHERE d.MEMBERSHIP_STATUS = 'ACTIVE'
The calculation above gives us something called a top 3 box. That is just one calculation, I will need to do many of them. Additionally, ever calculation will need to be done for each segment. In order to get a calculation for nonactive members, I would need to run another query and set d.MEMBERSHIP_STATUS = 'INACTIVE' and I would need to run another query with no filter, to get the overall calculation.
Is there a way I could store all my arithmetic calculations needed in my output as a function (maybe in a temp table or something) - my thought is that it'll be better to set the functions somewhere, and then when I need to calculate the output, I would some how call the function to do all the calculations I need, and give me all the calculations for every segment I have?
I can't fully envision how to get there, or if this is even a good solution, so guidance and detailed SQL code would be extremely helpful.Examples please!

Access 2013 SQL to perform linear interpolation where necessary

I have a database in which there are 13 different products, sold in 6 different countries.
Prices increase once a year.
Prices need to be calculated using a linear interpolation method.  I have 21 different price and quantity increments for each product for each country for each year.
The user needs to be able to see how much an order would cost for any given value (as you would expect).
What the database needs to do (in English!) is to:
If there is a matching quantity from TblOrderDetail in the TblPrices,
use the price for the current product, country and year
if there isn't a matching quantity but the quantity required is greater than 1000 for one product (GT) and greater than 100 for every other product:
Find the highest quantity for the product, country and year (so, 1000 or 100, depending on the product), and calculate a pro-rated price.  eg.  If someone wanted 1500 of product GT for the UK for 2015, we'd look at the price for 1000 GT in the UK for 2015 and multiply it by 1.5.  If 1800 were required, we'd multiply it by 1.8.  I haven't been able to get this working yet as I'm looking at it alongside the formula for the next possibility...
If there isn't a matching quantity and the quantity required is less than 1000 for the product GT but 100 for the other products (this is the norm)...
Find the quantity and price for the increment directly below the quantity required by the user for the required product, country and year (let's call these quantitybelow and pricebelow)
Find the quantity and price for the increment directly above the quantity required by the user for the required product, country and year (let's call these quantityabove and priceabove)
Calculate the price for the required number of products for an account holder in a particular country for a given year using this formula.
ActualPrice: PriceBelow + ((PriceAbove - PriceBelow) * (The quantity required in the order detail - QuantityBelow) / (QuantityAbove - QuantityBelow))
I have spent days on this and have sought advice about this before but I am still getting very stuck.
The tables I've been working with to try and make this work are as follows:
TblAccount (primary key is AccountID, it also has a Country field which joins to the TblCountry.Code (primary key)
TblOrders (primary key is Order ID) which joins to TblAccount via the AccountID field; TblOrderDetail via the OrderID.  This table also holds the OrderDate and Recipient ID which links to a person in TblContact - I don't need that here but will need it later to generate an invoice 
TblOrderDetail (primary key is DetailID) which joins to TblOrders via OrderID field; TblProducts via ProductID field, and holds the Quantity required as well as the product
TblProducts (primary key is ProductCode) which as well as joining to TblOrderDetail, also joins to TblPrice via the Product field
TblPrices links to the TblProducts (as you have just read).  I've also created an Alias for the TblCountry (CountryAliasForProductCode) so I can link it to the TblPrices to show the country link. I'm not sure if I needed to do this - it doesn't work if I do or I don't do it, so I seek guidance again here.
This is the code I've been trying to use (and failing) to get my price and quantity steps above and I hope to replicate it, making a couple of tweaks to get the steps below:
SELECT MIN(TblPrices.stepquantity) AS QuantityAbove, MIN(TblPrices.StepPrice) AS PriceAbove, TblOrders.OrderID, TblOrders.OldOrderID, TblOrders.AccountID, TblOrders.OrderDate, TblOrders.RecipientID, TblOrders.OrderStatus, TblOrderDetail.DetailID, TblOrderDetail.Product, TblOrderDetail.Quantity
FROM (TblCountry INNER JOIN ((TblAccount INNER JOIN TblOrders ON TblAccount.AccountID = TblOrders.AccountID) INNER JOIN (TblOrderDetail INNER JOIN TblProducts ON TblOrderDetail.Product = TblProducts.ProductCode) ON TblOrders.OrderID = TblOrderDetail.OrderID) ON TblCountry.Code = TblAccount.Country) INNER JOIN (TblCountry AS CountryAliasForProduct INNER JOIN TblPrices ON CountryAliasForProduct.Code = TblPrices.CountryCode) ON TblProducts.ProductCode = TblPrices.Product
WHERE (StepQuantity >= TblOrderDetails.Quantity)
AND (TblPrices.CountryCode = TblAccount.Country)
AND (TblOrderDetail.Product = TblPrices.Product)
AND (DATEPART('yyyy', TblPrices.DateEffective) = DATEPART('yyyy', TblOrders.OrderDate));
I've also tried...
I've even tried going back to basics and trying again to generate the steps below in 1 query, then try the steps above in another and finally, create the final calculation in another query.
This is what I have been trying to get my prices and quantities below:
SELECT Max(StepQuantity) AS quantity_below, Max(StepPrice) AS price_below, TblOrderDetails.Quantity, TblAccounts.Country
FROM 
(TblProducts INNER JOIN TblPrices ON TblProducts.ProductCode = TblPrices.Product)
(TblOrderDetail INNER JOIN TblProducts ON TblOrderDetail.Product = TblProducts.ProductCode)
(TblOrders INNER JOIN TblOrderDetail ON TblOrders.OrderID = TblOrderDetail.OrderID)
(TblAccount INNER JOIN TblOrders ON TblAccount.AccountID = TblOrders.AccountID),
WHERE (((TblPrices.StepQuantity)<=(TblOrderDetail.Quantity)) AND ((TblPrices.CountryCode)=([TblAccounts].[country])) AND ((TblPrices.Product)=([TblOrderDetail].[product])) AND ((DatePart('yyyy',[TblPrices].[DateApplicable]))=(DatePart('yyyy',[TblOrders].[OrderDate]))));
You may be able to see glaring errors in this but I'm afraid I can't.  I've tried re-jigging it and I'm getting nowhere.
I need to be able to tie the information in to the OrderDetail records as the price generated will need to be added to a financial transactions table as a debit amount and will show as an amount owing on statements.
I'm really not very good at SQL.  I've read and worked though several self-study books and I have asked part of this question before; but I really am struggling with it.  If anyone has any ideas on how to proceed, or even where I've gone wrong with my code, I'd be delighted, even if you tell me I shouldn't be using SQL. For the record, I originally posted this question on a different forum under Visual Basic. Responses from that forum brought me to SQL - however, anything that works would be good!
I've even tried, using Excel, concatenating the Year&Product&Country&Quantity to get a unique product code, interpolating the prices for every quantity between 1 and 1000 for each product, country and year and bringing them into a TblProductsAndPrices table. In Access, I created a query to concatenate the Year(of order date from tblOrders)&Product(of tblorderdetails)&Country(of tblAccount) in order to get the required product code for the order. Another query would find a price for me. However, any product code that doesn't appear on the list (such as where a quantity isn't listed in the tblProductsAndPrices as it is larger than the highest price increment) doesn't have a price.
If there was a workable solution to what I've just described that would generate a price for everything, then I'd be so pleased.
I'd really like to be able to generate an order for any quantity of any product for any account based in any country on any date and retrieve a price which will be used to "debit" a financial account in the database, who in a transaction history for an account and appear on statements. I'd also like to be able to do an ad-hoc price check on the spot.
Thank you very much for taking the time to read this.  I really appreciate it. If you could offer any help or words of encouragement, I'd be very grateful.
Many thanks
Karen
Maybe no one thinks on an easy solution to the problem, since not all minds work in database thinking.
Easy solution: Create one view that gives all calculated values, not only the final one you need, each one as a column. Then you can use such view in a relation view and use on some rows one of the values and on other rows other values, etc.
How to think is simple, think in reverse order, instead of thinking "if that then I need to calculate such else I need this other", think as "I need "such" and I need "this other", both are columns of an intermediate view, then think on top level "if" that would be another view, such view will select the correct value ignoring the rest.
Never ever try to solve all in one step, that can be a really big headache.
Pros: You can isolate calculated values (needed or not), sql is much more easy to write and maintain.
Cons: Resources use is bigger than minimal, but most of times that extra calculated values does not represent a really big impact.
In terms of tutorial out there: Instead of a Top-Down method, use a Down-Top method.
Sometimes it is better (with your example) to calculate all three values (you write sentences on bold) ignoring the if part, and have all three possible values for your order and after that discard the ones not wanted, than trying to only calculate one.
Trying to calculate only one is thinking as a procedural programming, when working with databases most times one must get rid of such thinking and think as reverse, first do the most internal part of such procedural programming to have all data collected, then do the external selection of the procedural programing.
Note: If one of the values can not be calculated, just generate a Null.
I know it is hard to think on First in, last out (Down-Top) model, but it is great for things as the one you want.
Step1 (on specific view, or a join from one view per calculation):
Calculate column 1 as price for the current product, country and
year
Calculate column 2 as calculate a pro-rated price as if 1000
Calculate column 3 as calculate a pro-rated price as if 100
Calculate column 4 as etc
Calculate column N as etc
Step 2 (Another view, the one you want):
Calculate the if part, so you can choose adequate column from previous view (you can use immediately if or a calculated auxiliary field).
Hope you can follow theese way of thinking, I have solved a lot of things like that one (and more complex) thinking in that way, but it is not easy to think as that, needs an extra effort.

Ms Access : Query to work out percentage

I have a database which currently records the amount of times someone does a certain procedure and they scores they have received. The scoring is done by select a value of either N, B or C.
I currently have written a query which will count the total number of times a procedure is done and the amount of times each score is received.
Here is the result of the query (original: http://www.flickr.com/photos/mattcripps/6673555339/)
and here is the code
TRANSFORM Count(ed.[Entry ID]) AS [CountOfEntry ID]
SELECT ap.AdultProcedureName, ap.Target, Count(ed.[Entry ID]) AS [Total Of Entry ID]
FROM tblAdultProcedures AS ap LEFT JOIN tblEntryData AS ed ON ap.AdultProcedureName = ed.[Adult Procedure]
GROUP BY ap.AdultProcedureName, ap.Target
PIVOT ed.Grade;
If a score of N or B is given that is deemed below standard and C is deemed at standard. Is there a way I can add something to my query which will show me in percentage how many of the procedures we at standard and how many below?
I really cant get my head round this so any help would be great.
Thanks in advance
UPDATE TabProd
SET PrecProd = (PrecProd * 1.1)
WHERE Código IN (1,2,3,4)
I did something very similar to this on a pretty large scale.
My issue was the need to be able to run queries over specific (but user variable) timeframes and output similar percentage of total results in a report.
I won't get into the date issue but my solution was to run the "sum" function on the total line on my specific reject criteria to get totals of the rejects then use a divide expression to create a new column element (defined expression) in the same query pulling from the joined table of "Total net production" - joined by a common reference - job ID.
For your case it sounds like you want to sum the two failure types - which you would simply add defined expressions dividing your total instances into your various failure modes and formatting in your output report as percents. To finish the data portion of your report you then need a third expression defining your "non-fail percent" - which would be 1.0 - N/total - B/total - both of which you will have previously defined in the query to determine the N and B failure rates.
Then its a matter of pulling that information into your report and formatting. It definitely CAN be done.
Hope this helps.

What is an unbounded query?

Is an unbounded query a query without a WHERE param = value statement?
Apologies for the simplicity of this one.
An unbounded query is one where the search criteria is not particularly specific, and is thus likely to return a very large result set. A query without a WHERE clause would certainly fall into this category, but let's consider for a moment some other possibilities. Let's say we have tables as follows:
CREATE TABLE SALES_DATA
(ID_SALES_DATA NUMBER PRIMARY KEY,
TRANSACTION_DATE DATE NOT NULL
LOCATION NUMBER NOT NULL,
TOTAL_SALE_AMOUNT NUMBER NOT NULL,
...etc...);
CREATE TABLE LOCATION
(LOCATION NUMBER PRIMARY KEY,
DISTRICT NUMBER NOT NULL,
...etc...);
Suppose that we want to pull in a specific transaction, and we know the ID of the sale:
SELECT * FROM SALES_DATA WHERE ID_SALES_DATA = <whatever>
In this case the query is bounded, and we can guarantee it's going to pull in either one or zero rows.
Another example of a bounded query, but with a large result set would be the one produced when the director of district 23 says "I want to see the total sales for each store in my district for every day last year", which would be something like
SELECT LOCATION, TRUNC(TRANSACTION_DATE), SUM(TOTAL_SALE_AMOUNT)
FROM SALES_DATA S,
LOCATION L
WHERE S.TRANSACTION_DATE BETWEEN '01-JAN-2009' AND '31-DEC-2009' AND
L.LOCATION = S.LOCATION AND
L.DISTRICT = 23
GROUP BY LOCATION,
TRUNC(TRANSACTION_DATE)
ORDER BY LOCATION,
TRUNC(TRANSACTION_DATE)
In this case the query should return 365 (or fewer, if stores are not open every day) rows for each store in district 23. If there's 25 stores in the district it'll return 9125 rows or fewer.
On the other hand, let's say our VP of Sales wants some data. He/she/it isn't quite certain what's wanted, but he/she/it is pretty sure that whatever it is happened in the first six months of the year...not quite sure about which year...and not sure about the location, either - probably in district 23 (he/she/it has had a running feud with the individual who runs district 23 for the past 6 years, ever since that golf tournament where...well, never mind...but if a problem can be hung on the door of district 23's director so be it!)...and of course he/she/it wants all the details, and have it on his/her/its desk toot sweet! And thus we get a query that looks something like
SELECT L.DISTRICT, S.LOCATION, S.TRANSACTION_DATE,
S.something, S.something_else, S.some_more_stuff
FROM SALES_DATA S,
LOCATIONS L
WHERE EXTRACT(MONTH FROM S.TRANSACTION_DATE) <= 6 AND
L.LOCATION = S.LOCATION
ORDER BY L.DISTRICT,
S.LOCATION
This is an example of an unbounded query. How many rows will it return? Good question - that depends on how business conditions were, how many location were open, how many days there were in February, etc.
Put more simply, if you can look at a query and have a pretty good idea of how many rows it's going to return (even though that number might be relatively large) the query is bounded. If you can't, it's unbounded.
Share and enjoy.
http://hibernatingrhinos.com/Products/EFProf/learn#UnboundedResultSet
An unbounded result set is where a query is performed and does not explicitly limit the number of returned results from a query. Usually, this means that the application assumes that a query will always return only a few records. That works well in development and in testing, but it is a time bomb waiting to explode in production.
The query may suddenly start returning thousands upon thousands of rows, and in some cases, it may return millions of rows. This leads to more load on the database server, the application server, and the network. In many cases, it can grind the entire system to a halt, usually ending with the application servers crashing with out of memory errors.
Here is one example of a query that will trigger the unbounded result set warning:
var query = from post in blogDataContext.Posts
where post.Category == "Performance"
select post;
If the performance category has many posts, we are going to load all of them, which is probably not what was intended. This can be fixed fairly easily by using pagination by utilizing the Take() method:
var query = (from post in blogDataContext.Posts
where post.Category == "Performance"
select post)
.Take(15);
Now we are assured that we only need to handle a predictable, small result set, and if we need to work with all of them, we can page through the records as needed. Paging is implemented using the Skip() method, which instructs Entity Framework to skip (at the database level) N number of records before taking the next page.
But there is another common occurrence of the unbounded result set problem from directly traversing the object graph, as in the following example:
var post = postRepository.Get(id);
foreach (var comment in post.Comments)
{
// do something interesting with the comment
}
Here, again, we are loading the entire set without regard for how big the result set may be. Entity Framework does not provide a good way of paging through a collection when traversing the object graph. It is recommended that you would issue a separate and explicit query for the contents of the collection, which will allow you to page through that collection without loading too much data into memory.