Fill a Number field with Auto Increment values in MS ACCESS - sql

I have a Access Table with following structure:
INO IDATE NAME ADDRESS CITY PHONE CONTACT & Other Fields.....
1430 01-Apr-15
1431 01-Apr-15
1432 01-Apr-15
1435 01-Apr-15
1436 01-Apr-15
1440 01-Apr-15
1441 01-Apr-15
1448 01-Apr-15
1450 01-Apr-15
1455 02-Apr-15
1456 02-Apr-15
1459 02-Apr-15
Field "INO" is set To Data type "NUMBER" Field Size: Double Indexed= Yes
This field is auto increment programmatically, but after deletion of some useless & cancelled records from database. INo. series is not in order. I want to re generate the numbers & fill the gap of deleted numbers.
i.e. INO 1435 should be 1433, 1436 to 1434, 1440 to 1435 & so on.
Select Statement i use to filter records from table:
SELECT *
FROM IDETAIL
WHERE TYPE=True AND INO>=1430 ORDER BY INO;
Till 1430 records are in order there is gap after 1430 & dated 01-Apr-15.
there are about 18,000 records in table so not easy to manually correct the records. How can i correct this with SQL or any other command.
P.S. : No related table or entry is effected. We just want to maintain the sequence of entries for accounting purpose.
Just like we use "Do While" function.
Starting entry INo is correct and known. All the entries got numbered in a loop starting with 1st record INo=1430, next record INO = 1430+1, next 1430+2 until last entry. How to implement same in UPDATE query alongwith "WHERE TYPE=True".

If no table is referenced from this table, You can use following query:-
UPDATE YourTable
SET INO = DCount('*', 'YourTable', 'INO <= ' & INO)
Hope this helps

If you insert a new autonumber field into the table, it should generate a new set of IDs for the rows. Then, if you want, you can update your existing field to the new ID value and delete the autonumber field.

Using and improving the great answer from #Ankit Bajpai here is maybe what you need:
UPDATE (SELECT * FROM IDETAIL WHERE TYPE=True AND INO>=1430 ORDER BY INO)
SET INO = DCount('*', 'IDETAIL ', 'INO <=' & INO & ' AND INO >= 1430 AND Type = True') + 1429
Be aware that if INO is indexed and without duplicates,
it may create errors in the recordsets Type=false

Related

SQL Select request by comparing one row with the next/previous one

I have such table (cars diesel supplies from a tank), coming from an Excel file:
Date
Odometer
Car
12-01-22
125000
CAR1
20-01-22
125800
CAR1
27-01-22
144000
CAR1
02-02-22
126500
CAR1
11-01-22
90500
CAR2
I'm working on Excel with VBA macros.
I can already extract the whole data with VBA code:
sql = "SELECT * FROM [Table1$] ORDER BY [CAR] ASC, [DATE] ASC;"
Set rs = cn.Execute(sql)
For each car, I need to exclude rows where Odometer (Km) data is wrong: higher than for the next refill date. In my table example, third row should not be selected.
Which SQL request (compatible with OLEDB) could do that?
Important: my recordset needs to be ordered with Date ASC.

MS Access Query to get entry time and exit time for each ID

I need help to with an attendance table in access, in my company we have a single card reader which provides access in/out of the facility.
I was able to extract from the software an excel sheet which I later imported to access, the column headers(fields) are in a temporary table as follows.
The problem is staff go in & out of the facility a lot during the course of the day, I need to get the first and last entry time for each day per CardID to add to another table.
*AttendanceDate* - *AttendanceTime* - *CardID*
10/09/2017 - 08:00:00 - 123
10/09/2017 - 09:20:00 - 123
10/09/2017 - 10:00:00 - 123
10/09/2017 - 15:00:00 - 123
10/09/2017 - 09:00:00 - 675
10/09/2017 - 12:00:00 - 675
11/09/2017 - 09:00:00 - 675
11/09/2017 - 16:00:00 - 675
I need to create a query that will get the for every cardID the first and last record of time per day and append it to another sheet to get the results like this.
*AttendanceDate* - *EntryTime* - *ExitTime* - *CardID*
10/09/2017 - 08:00:00 - 15:00:00 - 123
10/09/2017 - 09:00:00 - 12:00:00 - 675
11/09/2017 - 09:00:00 - 16:00:00 - 675
Is this even possible?
This is an aggregation query:
select AttendanceDate, min(AttendanceTime) as entrytime,
max(AttendanceTime) as exittime, CardId
from t
group by AttendanceDate, CardId;
To add this to another table, you would use either select into (to create the table) or insert (if the table is already created).
The insert would look like this:
insert into t2(AttendanceDate, entrytime, exittime, CardId)
select AttendanceDate, min(AttendanceTime) as entrytime,
max(AttendanceTime) as exittime, CardId
from t
group by AttendanceDate, CardId;
I don't believe MS Access supports "upsert", which would be a single operation to do both. So, create a unique index on the two columns:
create unique index unq_t_AttendanceDate_CardId on t(AttendanceDate, CardId);
Then attempt to do an insert. If that fails, then do an update. Here is a question on that topic.
Consider running two action queries back to back:
Append query with aggregation and NOT IN / NOT EXISTS / LEFT JOIN...NULL clause (still compliant in MS Access though an SQL Server link) where only new CardIDs and AttendanceDate pairs are appended.
Update query using domain aggregates, DMin and DMax (as aggregate query joins are not updateable queries) where existing CardIDs and AttendanceDate pairs are updated.
Append Query (appends only new CardIDs and AttendanceDate pairings, using NOT EXISTS)
INSERT INTO otherTable (CardID, AttendanceDate, EntryTime, ExitTime)
SELECT t.CardId, t.AttendanceDate, MIN(t.AttendanceTime), MAX(t.AttendanceTime)
FROM originTable t
WHERE NOT EXISTS
(SELECT 1 FROM otherTable sub
WHERE sub.CardID = t.CardID AND sub.AttendanceDate = t.AttendanceDate)
GROUP BY t.CardID, t.AttendanceDate;
Update Query (updates only existing CardIDs and AttendanceDate pairings, using domain aggregates)
UPDATE otherTable t1 INNER JOIN originTable t2
ON t1.CardID = t2.CardID AND t1.AttendanceDate = t2.AttendanceDate
SET t1.entrytime = DMin("AttendanceTime", "originTable", "CardID=" & t1.CardID &
" AND AttendanceDate=#" & t1.AttendanceDate & "#"),
t1.exittime = DMax("AttendanceTime", "originTable", "CardID=" & t1.CardID &
" AND AttendanceDate=#" & t1.AttendanceDate & "#")
An "upsert" is certainly possible, if the tables have a unique key.
This old tip from Smart Access is one of my favourites:
Update and Append Records with One Query
By Alan Biggs
Did you know that you can use an update query in Access to both update
and add records at the same time? This is useful if you have two
versions of a table, tblOld and tblNew, and you want to integrate the
changes from tblNew into tblOld.
Follow these steps:
Create an update query and add the two tables. Join the two tables by
dragging the key field of tblNew onto the matching field of tblOld.
Double-click on the relationship and choose the join option that includes all records from tblNew and only those that match from
tblOld.
Select all the fields from tblOld and drag them onto the QBE grid.
For each field, in the Update To cell type in tblNew.FieldName, where FieldName matches the field name of tblOld.
Select Query Properties from the View menu and change Unique Records to False. (This switches off the DISTINCTROW option in the SQL
view. If you leave this on you'll get only one blank record in your
results, but you want one blank record for each new record to be added
to tblOld.)
Run the query and you'll see the changes to tblNew are now in tblOld.
This will only add records to tblOld that have been added to tblNew.
Records in tblOld that aren't present in tblNew will still remain in
tblOld.

Select items where count in another field matches (not updatable)

Here I am trying to get the record for my products where the # swab location in Main table matches the count of swab locations in swab Table and Users can checked off the Y/N to verify that the description of the locations are correct.
Here is the example of my 2 tables.
tblMainEquipment
Asset_ID EquipmentName Num_SwapLocations Verified
234 Saijimon 2 N
235 Pasquale 3 N
tblMainSwapLocations
Asset_ID Swap_location
234 Particle Cannon
234 RailGun
235 Particle Cannon
I use the following query to count the number of records, i avoided using a having query to combine both tables since it is not updatable.
qryMainSwapLocationCount
SELECT MSL.Asset_ID, Count(Asset_ID) AS [Count]
FROM tblMainSwapLocation AS MSL
GROUP BY MSL.Asset_ID;
This will give me the result of
qryMainSwapLocationCount
Asset_ID count
234 2
234 1
I used the following as a record source for my form to allow users to verify the inputs.
SELECT MEQ.Asset_ID, MEQ.Equipment_Name,MEQ.Num_swapLocations MEQ.Verified
FROM tblMainEquipment AS MEQ, qryMainSwapLocationCount AS MSLC
WHERE (((MEQ.Asset_ID)=[MSLC].[Asset_ID]) AND ((MEQ.Num_SwapLocations)=[MSLC].[Count]);
This result would be
tblMainEquipment
Asset_ID EquipmentName Num_SwapLocations Verified
234 Saijimon 2 N
However this record set is not editable. Is there any reasons for this?
I think you should put your table tblMainEquipment as your recordsource and bring all the fields from that on to your form:
Then insert an unbound textbox (perhaps close to your Num_SwapLocations field for easy comparison):
Then in this new textbox, put the following in the ControlSource:
=DCount("ASSET_ID","tblMainSwapLocations","ASSET_ID=" & [Asset_ID])
Then open your form and it should count the number of records in table tblMainSwapLocations that have the same Asset_ID as the record currently showing:
You'll then be able to update the Verified field in your tblMainEquipment table.

New entries are on top When bound DGV is filled

When I fill my DGV from a bound Access Table, it orders by Primary ID to a point - I say that because I have 1200 records and the DGV is filled in the following order, assuming we are just looking at the Prim. ID column -
1200
1199
1198
1197
1196
1
2
3
4
.....
1195
using the code below -
Me.ClientListTableAdapter.Fill(Me.ReportGenieDatabaseDataSet2.ClientList)
Sorry if this is vague but it's all I got. I hope to be able to order by descending ID - just like the Access table shows.
Also when I look up the .Last value it reads the "1195"
There is no order in a table. You can often find from one query to the next, records will be returned in different orders. You MUST thus use a SQL statement to set the order of the data returned. It is likely now you are using some SQL statement to retrieve this data – simply all a ORDER BY clause to that sql.

Split delimited field into Different rows

So each day I'm given an Excel worksheet with orders, they look something like this:
Date Vendor OrderID/Quantity Total
12/28/2013 Nike 1111111-8;2222222-12 20
12/29/2013 Adidas 3333333-5;4444444-10 15
12/30/2013 Wrangler 5555555-3 3
It's usable to most people I work with but not to me, as I want to identify each OrderID separate from the quantity. The "-" between the 7 digit number is to separate the ID from how many units are associated to it. But essentially when I import this table into access I want to create another table that splits these values.
Date Vendor OrderID Quantity
12/28/2013 Nike 1111111 8
12/28/2013 Nike 2222222 12
12/29/2013 Adidas 3333333 5
12/29/2013 Adidas 4444444 10
12/30/2013 Wrangler 5555555 3
This is much more useful to me but has been a daunting task to produce with two delimiters("-" and ";"). I am ok with VBA but I am struggling to find a solution to my conflict. So how would I go about doing this?
The most straightforward way I can think of is the VBA Split function. Please note that I set up the tblStaging staging table with all the fields as Text type for the import from Excel, but I set the tblOrders table up with (what I assume are) the correct types: Date as Date, Vendor as Text, OrderID as Number and Quantity as Number. See the comments in the code for details.
Public Sub SplitOrders()
Dim rsStaging As Recordset
Dim rsOrder As Recordset
Dim arrOrders() As String
Dim arrOrderDetails() As String
'Rename these for whatever your tables are called'
Set rsStaging = CurrentDb.OpenRecordset("tblStaging")
Set rsOrder = CurrentDb.OpenRecordset("tblOrders")
rsStaging.MoveFirst
While Not rsStaging.EOF
'Split into an array of Orders'
arrOrders = Split(rsStaging.Fields("OrderID/Quantity"), ";")
For i = 0 To UBound(arrOrders)
'Split the OrderID and Quantity for each Order'
arrOrderDetails = Split(arrOrders(i), "-")
'Create the new record in tblOrders'
With rsOrder
.AddNew
!Date = CDate(rsStaging!Date)
!Vendor = rsStaging!Vendor
!OrderID = CLng(arrOrderDetails(0)) 'If the OrderID can contain letters, symbols or leading zeros, omit the CLng( ... ) call'
!Quantity = CLng(arrOrderDetails(1))
.Update
End With
Next
rsStaging.MoveNext
Wend
End Sub
I'd look to break this down into different pieces rather than trying to parse the data all at once. For example, step 1 might be to import the file to a staging table (that looks like the first data example from your question). Step 2 would be to query the table to detect any rows that contain ';' (perhaps using the InStr function or a wildcard search like '*;*'. Take these records and parse them into two or more records. Third, identify any records that do not contain ';' and parse those into single records. All of the resulting (clean) records can go into your destination table for further analysis.