Getting rows in Microsoft Access to refer to other rows - mysql

I have a Microsoft Access table of data with 3 fields: "part_number", "date_of_price_change" and "new_price", but I need to convert the "new_price" field to show the "price_change", rather than the full "new_price" of each part on each date.
This will obviously involve some process that looks at each unique part number on each date and looks up the price of the record with the same part number with the next earliest date and deduct the prices to get the price change.
Problem is, I have no idea how to do this in Access and there are too many records for Excel. Can anyone assist with how to do this in Access? (Note that date changes can happen any time and are not periodic).
Many thanks in advance.
Ana

Add the new column price_change as a Money data type, then run a query something like below. Make sure you backup the table first with an APPEND table to a new table, just in case. Since it is a new column i may not matter.
UPDATE
T1
SET
T1.price_change = T1.new_price - Nz((SELECT top 1 T2.new_price from MyTable T2 WHERE T2.part_number = T1.Part_Number ORDER BY date_of_price_change DESC),0)
FROM
MyTable T1

Related

How should I store another table's row in order to have statistics data in the frontend?

I have a table full of businesses each with a scannable QR Code, and another table that stores the scans the users make. Right now, the scan table schema looks like this:
id | user_id | business_id | scanned_date
If I want to create charts and analytics in the front-end of my Application for statistics about business scans I'd just get the business_id and get the business info with it, but the problem is that if a business' data is ever changed then the statistical data will also change, and it shouldn't be this way.
The first thing that came to my mind in order to have static data was to store the whole business row as a JSON String in a new column in the scan table, but it doesn't sound like a good practice. (Although storing JSON String is not advised against if the data won't be tampered with, which won't since it's supposed to be static).
Another thing that I thought of was to make a clone table out of the business table's schema, but that'd mean to work twice whenever I want to make changes to the original one since I must also change the cloned one.
You need a way to represent the history of the businesses' data in your database.
You didn't mention what attributes you store in each business's row, so I will guess. Let's say you have these columns
business_id
name
category
qr_code
website
Your problem is this: if you change any attribute of the business, the old value vanishes.
Here's a solution to that problem. Add start and end columns to the table. They should probably have TIMESTAMP data types.
Then, never DELETE rows from the table. When you UPDATE them, only change the value of the end column. Instead add new rows. Let me explain.
For a row to be active at the time NOW(), it must pass these WHERE criteria:
start_date >= NOW()
AND (end_date IS NULL OR end_date < NOW())
Let's say you start with two businesses in the table.
business_id start end name category qr_code website
1 2019-05-01 NULL Joe's tavern lkjhg12 joes.example.com
2 2019-05-01 NULL Acme rockets sdlfj48 acme.example.com
Good: You can count QR code scans day by day with this query
SELECT COUNT(*), DATE(s.scanned_date) day, b.name
FROM business b
JOIN scan s ON b.business_id = s.business_id
AND b.start >= s.scanned_date
AND (b.end IS NULL OR b.end < s.scanned_date)
GROUP BY DATE(s.scanned_date), b.name
Now, suppose Joe sells his tavern and its name changes. To represent that change you must UPDATE the existing row for Joe's to set the end date, and then INSERT a new row with the new data. Afterward, your table looks like this
business_id start end name category qr_code website
(updated) 1 2019-05-01 2019-05-24 Joe's tavern lkjhg12 joes.example.com
(inserted) 1 2019-05-24 NULL Fancy tavern lkjhg12 fancy.example.com
(unchanged) 2 2019-05-01 NULL Acme rockets sdlfj48 acme.example.com
The query above still works, because it takes into account the start and end dates of the changes.
This approach works best when you have many more scans than changes to businesses. That seems likely in this case.
Your business table needs a composite primary key (business_id, start).
Prof. Richard Snodgrass wrote a book on this subject, Developing Time-Oriented Database Applications in SQL, and generously made a pdf available.
I hope I got your question.
You could try having duplicates in the business table. Instead of editing the business, try adding a new one with a new id. When you are editing your business, instead of updating the existing one, you can INSERT a new one. The stats will use the old id and will not get affected by the changes. When you are trying to get the last business info, try sorting them according to their ids to get the last one. That way you won't need a second table for business data.
Edit: If the business id needs to be specific to a business, instead of using the business id, you can add a column that represents the insertion of data to the table. Again, you can use sorting limiting the query to get the last one.
Edit 2:
Removing entities that were inserted a certain amount of time ago
If you don't need the stats from a month ago, you could remove them from businesses to save up space. You can use the new time column you created to get the time difference and check if it is greater than the range you want.

MS Access: Calculate difference when two criteria meet

I have an MS Access related question. I have a table that looks like this:
Table1
What I need to do is this:
1. Find deadline 29.01.2017 (first month of the year),
2. look at the corresponding AccountNumber and SubAccountNumber,
3. find deadline 28.02.2017 (so the next month) that matches with the AccountNumber and SubAccountNumber of the previous month,
4. subtract the Amounts,
5. and display the result.
In this example (Table 1): The first deadline of 29.01.2017 has the AccountNumber 1 and SubAccountNumber 23 as well as the Amount 400€. Looking for the next month that matches AccountNumber and SubAccountNumber, we find the value 300€. I would now have to subtract 300€ from 400€ and put this in the field that I have added (see also Table 2).
What I have done so far is concatenate the two attributes AccountNumber and SubAccountNumber, so my table now looks like this:
Table2
I thought it would be easier this way, because now I can look for the first month/deadline (29.01.2017), get the corresponding CONCAT, look for the next month/deadline that has the same CONCAT, and subtract the amounts.
Seeing as I am new to Access though, I am clueless as to how to go about this. Any hint would be greatly appreciated. If you think that my approach using a concatenation is not target-aimed or if I haven't made the problem clear enough, let me know.
PS I read online that Access offers an if-else statement - would that be an idea?
That should get you there or very close:
SELECT T1.ACCOUNTNUMBER, T1.SUBACCOUNTNUMBER, T1.AMOUNT-T2.AMOUNT AS AMOUNTDIFF
FROM Table1 T1
INNER JOIN Table1 T2
ON T1.ACCOUNTNUMBER=T2.ACCOUNTNUMBER
AND T1.SUBACCOUNTNUMBER=T2.SUBACCOUNTNUMBER
AND DateDiff('m',DateAdd('d',1,T1.DEADLINE), DateAdd('d',1,T2.DEADLINE))=1
WHERE T1.DEADLINE=#29.01.2017#
Make sure whatever date format you use with WHERE is a valid date format for your locale. Obviously substitute Table1 with the actual name of your table.
I do not have an easy way of testing this so there may be typos.

Access Find, Match and Replace

I have an MS-Access query that I am trying to design with little luck. I have 2 columns...one of check numbers and one of invoice numbers. For every check number there has to be an invoice number. The columns look like this...
Check# Invoice#
012564
012564 PC0935
012564 PC0935
012564
I need to fill in the Invoice# wherever it is missing on the check.
I can get it to work as an index/match with a vlooup in Excel but I need to be able to do this in Access.
I have tried dlookups with replace but no luck. I am not looking for the absolute answer but some ideas in the general direction would be most appreciated!
I have no knowledge of VBA and very limited SQL.
Based on my comment that you want the table updated so that each Check# entry has a corresponding Invoice# entry and there will always be at least one entry in that table that does have the 'Check# ~ Invoice#` pairing so use that pairing to complete the empty records.
e.g. Check 012564 has Invoice# PC0935, and 012565 has PC0939 in at least one record. We just need to complete the blanks for those Check numbers.
All records will have a Check #.
This SQL should do it:
UPDATE Table1 T1 INNER JOIN Table1 T2 ON T1.Check = T2.Check
SET T1.Invoice = T2.Invoice
WHERE T1.Invoice IS NULL AND NOT T2.Invoice Is Null

Updating several table columns based off a Select Query

So this is my Select Query called qryHoursSUM.
SELECT DAL.Project
, DAL.Unit
, DAL.Activity
, Sum(([EndTime]-[StartTime])*24) AS Hours
FROM DAL INNER JOIN UnitTbl
ON (DAL.Project=UnitTbl.Project) AND (UnitTbl.Unit=DAL.Unit)
GROUP BY DAL.Project, DAL.Unit, DAL.Activity;
I'm trying to get it to update to the corresponding *** Actual field and matching row in my Table called UnitTbl, which has the Project and Unit fields as a composite primary key. I cant seem to get it to work. I've first tried running a update query based on the select query but received an "Operation must use an updateable query", and found out that its not possible. I've made a make table query call qrySumHoursTbl to turn the qryHoursSUM into a table
SELECT qryHoursSUM.* INTO SumHoursTbl
FROM qryHoursSUM;
Then created an update query called qryUpdateUnitTbl to just update the 002 Actual field
UPDATE SumHoursTbl INNER JOIN UnitTbl
ON (SumHoursTbl.Unit = UnitTbl.Unit)
AND (SumHoursTbl.Project = UnitTbl.Project)
SET UnitTbl.[002 Actual] = [Hours]
WHERE (([Activity]="002 Drafting Submittals"));
Is it possible to have an update query to update multiple fields at once or would I have to make a update for each field i want to update?
Also, for some reason it only update the UnitTbl with whole numbers only, I need to have it show up to 2 decimal places. After working with so many copies, I completely forgot to change the field size to double. After changing that, its showing up to 2 decimal places
My end goal is to be able to let a user click on a button that shows a variance report of hours for each units Budgeted hours and Actual hours (which would be [*** Budget] - [*** Actual]) Any tips for things to consider along the way to get there is appreciated, I've trying to figure this out for a week now.

Creating a complicated MySQL Update Query

I am trying to create an UPDATE query that will replace the NameID field on a table called TimeStamps with the user's id field value from another table called Names. Here is some sample data.
Names Table
id:1
name:John
password:1234
TimeStamps Table
id:1
name:**John**
timestamp:01/01/2000 12:00:00
I want to replace the Name field in the TimeStamps table with the corresponding id value from the Names table. I'm not entirely sure on how to write the query but I know it starts with something like this.
UPDATE TimeStamps
SET NameID=(NamesTableReference)
WHERE NameID=(TimeStampsTableReference);
This way I can start to run queries against the user's id and not the user's Name. We have more than one user with the same name and it doesn't pull the right data because it is pulling multiple users. I can update the data manually but there are several hundred thousand rows in the table and that would take entirely too much time. Can anyone shed some light on what I need to add/change in the query below? Thanks!
I think you just want a join:
update timestamps t join
names n
on t.id = n.id
set t.name = n.name;
However, the update shouldn't be necessary. You have an id connecting the two tables. Just use it when you are using timestamps. That is, use a join to look up the name rather than storing it in both places -- and running the risk that the names associated with an id somehow end up different in the two tables.
It looks like this query did the trick.
UPDATE TimeStamps t, Names n
SET t.NameID = n.id
WHERE t.NameID = n.Name
Thanks everyone for your input and your help! Hope this can help someone else in the future!