MS Access: Calculate difference when two criteria meet - ms-access

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.

Related

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

Getting rows in Microsoft Access to refer to other rows

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

MYSQL checking if a record exists with the specified child-records

Okay, let's say I have a table called rooms:
It only has one column: ID
I also have another table called items_in_rooms with columns:
roomId, itemName, itemColor
Whenever a room-record is inserted a bunch of records is also inserted into items_in_rooms linked to the row-record, specifying what items are in that room.
The problem is that when a room-record along with its items, I need to first verify if a room with those exact items don't already exist.
How can this be done?
One way of course would be to first fetch all room-records along with all their items then look through them until it has been verified there isn't already an exact copy in the database and then do insertion if it's unique.
But this sounds a bit ineffective to me, especially as the tables grows very large so I was hoping there's a way to have MYSQL do the checking.
One way I came up with was to do something like this:
SELECT roomId FROM(
SELECT rooms.id roomId, GROUP_CONCAT(
CONCAT_WS(',',itemName,itemColor) ORDER BY itemName,itemColor SEPARATOR '/'
) roomContents
FROM items_in_rooms
JOIN rooms ON roomId=rooms.id
WHERE snapshotDate='$dateString'
GROUP BY roomId
) concatenatedRoomContents
WHERE roomContents='bed,white/carpet,red/chair,brown'
Essentially this will make MYSQL concatenate each room into a string, then compare them to the "input-string" in the WHERE-clause. Obviously the input-string would have to be ordered the same way as how MYSQL orders the rows before concatenating (itemName,itemColor).
While this worked for be it felt very dirty. Also, it initially caused some problems when I had added a decimal-field as MYSQL always includes every decimal-digit when stringifying so 1 for instance could be "1.000"
while PHP which I'm using by default stringifies it to "1". I solved this using number_format() making it include the right amount of decimal-digits.
Now I've noticed I've got some duplicates in the table again so there's some other gotcha I need to find, but I was just wondering if there's maybe a more clever way?
This is how it can be done. The following query returns the id of the room if such a room exists(it has exactly those items, no more, no less).
SELECT roomId FROM (
SELECT roomId,count(*) numMatchedItems
FROM items_in_rooms WHERE (itemName,itemColor)
IN (('bed','white'),('carpet','red'),('chair','brown'))
GROUP BY roomId
) matches
WHERE numMatchedItems=3
Thanks, CBroe.

Using Delete, Update, Insert in MySQL

Good day!
First of all, I am new at MySQL, and I've got some problems with altering tables with query's.
Secondly, sorry for bad English, unfortunately, it's not my native language.
So yeah, I have some questions, and I will be very thankful if you will be able to help me.
I have 2 tables: Screenshot
Foreign key is 'manufact' from table Registred
So, I have few Query tasks I wanted to do, but can't figure out how to do them.
Here goes first task I did, I just want you guys to check, If I did it right.
Calculate fields from January and February where Car Manufacturer is VW.
SET Total = January + February WHERE Manufact = 3;
And here comes Query's I can't do:
Delete all information about car manufacturer, that had smallest amount of cars registred in January.
Here is what I came up with.
DELETE FROM Registered Order by January Limit 1;
But it didn't delete information from table 'manufacturer'.
What can I do there?
Here is hardest one so far:
Calculate all cars registered in January and February and save it in additional field. (Should be displayed as Int, without floating point.)
Code:
ALTER TABLE Registered Add Column alltotal Int;
UPDATE Registered
Set alltotal = Select SUM(February + January) From Registered;
What I wanted to do is, Create only 1 field, where Sum of all February and January fields will be calculated.
Any suggestions so far?
P.S If I will be able to do these, I will be able to complete other tasks myself :)
P.S.2 I am new here, so please sorry for bad Question editing. I am doing as in tutorial I found but it's hellish for me. I tried my best :)
Let's break this down problem by problem. The first one is:
Delete all information about car manufacturer, that had smallest amount of cars registered in January.
The first thing we need to do is write a subquery that determines which manufacturer that is. We can do so by selecting the id of the row in registracija with the minimum value for January. We can do that using ORDER BY, which you caught on to:
SELECT vieglas
FROM registracija
ORDER BY january
LIMIT 1;
Now that we have that id, we can delete from that table using the WHERE clause:
DELETE FROM registracija
WHERE vieglas = (SELECT vieglas FROM (SELECT * FROM registracija) t ORDER BY january LIMIT 1);
For information on why I included the SELECT * FROM registracija, see this answer.
To see an SQL Fiddle of that in action, check this: http://sqlfiddle.com/#!9/c81d5/1
For the second part:
Calculate all cars registred in January and February and save it in additional field. (Should be displayed as Int, without floating point.)
We can use the addition operator along with an update command to put this total inside the Total column like this:
UPDATE registracija
SET total = (january + february);
For the SQL Fiddle of the update, see this: http://sqlfiddle.com/#!9/f5b28/1
for deleting all record which has had smallest amount of cars registred in January delete from 'Registracija' where 'January' =select min('January') from Registracija
Try following:
1) Total Count For January & February
SELECT (January+February) AS TOTAL from Registrant where Vieglas = 3
2) Delete Query
DELETE FROM Registrant INNER JOIN Vieglas Order By Registrant.January Limit 1

SQL: Select table if a column has a given value

I am new to SQL and programming in general, this could be an easy question, or it may not be, I have not clue. I just know I have not been able to find a straightforward answer. I have an excel file with a bunch of different data sheets. Each data sheet has the same data, just for different occurances. I want to be able to associate certain readings with a given value of the subject. (i.e. I want to be able to return all paces recorded during a race if the person is under 24 years old) In this situation, the paces would be recorded every minutes during a 2 hour race. That would be in a column pace, age would be in another column age. There will be a data sheet for every subject. I ultimately would like to find the average pace of all people in different age ranges (24 and under etc.) I can combine the columns with the UNION command. I am working with SQL in R. What I have looks like this:
sqlQuery(Race, paste("SELECT [PACE] FROM [Bill] UNION [STEVE]"))
I understand the WHERE clause to return rows where the given value is present. My dilemma is I have enough data it would be very time consuming to input the age for every row so that I can query the rows.
Is it possible for me to create code that asks something like "return me all table where age is less than 24?"
I'd strongly advise against putting each data sheet into its own table - just add a column DATA_SHEET to your table to differentiate between occurences.
That said, I'd probably go one step further and use these tables (assuming one data sheet represents one race):
PERSON
------
PK
Name
Age (better: Date of birth, since age changes over time)
Gender
...
RACE
----
PK
Name
Start date
...
PACE
----
PERSON_FK -- foreign key to PERSON table
RACE_FK -- foreign key to race table
PACE
...
This way, to get all paces of people younger than 24 for a given race:
select race.name race_name, person.name person_name, pace.pace
from person, race, pace
where person.pk = pace.person_fk
and race.pk = pace.race_fk
and person.age < 24
sqlQuery(Race, paste("SELECT [PACE], AVG(PACE) FROM [Bill] UNION [STEVE] WHERE columnName["age"] < 24"))
I'm not a master in SQL-server/T-SQL and I have no experience developing R, but in SQL the syntax is not so different from this.
But you could separate the queries like this (I have no clue if the syntax is good):
sqlQuery(Race, paste("SELECT [PACE] FROM [Bill] UNION [STEVE] WHERE [PACE].age < 24"))
then:
sqlQuery(Race, paste("SELECT AVG([PACE].age) FROM [Bill] UNION [STEVE]"))
The question:
Blockquote "return me all table where age is less than 24?"
Implies that you would have more than one table with a column called age. If the age applies to the runner I would suggest reviewing your schema. You should have an entity named something like:
Person
or
Runner
or
Participant
That has a column age. The trick would then be to simply move all your data into that table. Then a simple
SELECT
*
FROM
Person
WHERE
age < 24
Would return all the data you're looking for.
I think where this is getting confusing is the concept of a datasheet in excel vs. a table in SQL. Your data sheets sound like they're instances of a participant with various additional data. Instead of creating a table for each data sheet you should create a schema that fits all of your data and then fill it with each instance from your data.
Take a look here for a reference to schema design:
How to design this RDBMS schema?
Try avg() function of sql server and with where condition where ageCol < 24