Randomly select records to create limited record - ms-access

In a database of Microsoft Access containing 500 employees of different categories I want only certain number of employees in each category. e.g., 2 employees of Category A, 5 employees of category B, 8 employees of category C.
Thus I want to create 10 separate groups wherein each person should be found in one list only, i.e. there should be no duplicate record. Each report should contain randomly selected unique record. One employee in one list should be found in another list.
Please help by clarifying how to achieve? I tried by creating union query. But, I got the result of duplicate records only. I also tried random limit expression but of no avail. Preferably the grouping should be based on the centre allotted.
The database looks as follows:-
Employee Name Category Duty As Centre allotted
1. XXXXX A I 1
2. XXXXX A I 1
3. XXXXX B II 1
4. XXXXX B II 1
5. XXXXX B II 1
6. XXXXX C III 1
7. XXXXX C III 1
8. XXXXX C III 1
9. XXXXX C III 1
How do I do this please?

Would something like this suit?
SELECT p.ID, p.EmpName, p.Category
FROM Persons P
WHERE p.ID In (
SELECT Top 2 ID
FROM Persons
WHERE Category = "A"
ORDER BY Rnd(ID)+ID)
OR p.ID In (
SELECT Top 5 ID
FROM Persons
WHERE Category = "B"
ORDER BY Rnd(ID)+ID)
OR p.ID In (
SELECT Top 8 ID
FROM Persons
WHERE Category = "C"
ORDER BY Rnd(ID)+ID)
ORDER BY p.Category

One approach to do this would be to add a field to the employees table called flag with a yes/no data type. Then create a form with the following controls on it:
Command button with a caption of reset flag to no for all records
A combo box that lists all the different categories
A text box to store the number of records to select
Another command button with a caption of flag records
Then the on the click event VBA code would look something like the following:
Private Sub cmdFlagRecords_Click()
Dim lngRandomNumber As Long
Dim k As Long
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
strSQLText = "Select * From Employees Where Category='" & Me.cboCategory & "'"
Set rs = db.OpenRecordset(strSQLText, dbOpenSnapshot)
k = 0
Do Until k = CLng(Me.txtRecordsToSelect)
' generate a random number between one and the number of rows available
lngRandomNumber = CLng(Rnd(1) * rs.RecordCount)
'move to that record
rs.AbsolutePosition = lngRandomNumber
If Not rs![flag] Then
' set the flag to yes or true and increment the k variable
db.Execute "Update Employees Set=True Where ID=" & rs![ID]
k = k + 1
End If
Loop
rs.Close
End Sub
You can then click the button as many times as necessary to build up your selection.

Related

Delete from one table with lookup on another table

As part of a pruning process, I am trying to delete data from a table which is not used anymore. There are search jobs (table Search) which have results (table Res), and people receive the search results (table Abo) via email. For every Abonnement, the last result sent via email is saved in the column "last_result".
What I want to do: For every search job, I want to delete all results which have been sent to the users.
This is a simplified variant of the structure:
http://sqlfiddle.com/#!9/5ef8a3
Abo
---
user search last_result
A 1 100
B 1 200
C 2 50
D 3 100
Res
---
id search
50 1 <---- this should be deleted
300 1
51 2
Search
------
1
2
3
What I tried to do is something like this:
DELETE r
FROM Res r
JOIN Abo a ON r.search = a.search
WHERE
r.id < min(a.last_res)
For every "search" value, I want to delete all results ("Res") which are below the "last_res" field in the "Abo" table.
You need to group MIN(last_res) by search, so the way to do this is to write a subquery that calculates this, then join with that subquery.
DELETE r
FROM Res AS r
JOIN (SELECT search, MIN(last_res) AS min_res
FROM Abo
GROUP BY search) AS a
ON r.search = a.search AND r.id < a.min_res

Dynamic label caption in a report using vba

I am trying to design an indididual report card for the students of my college. I have a table called "tbl_student" where their marks are stored. I have 6 columns for 6 different subjects. A student can choose only 5 subjects i.e 4 being required and Computer and Maths are optional subjects where a student can choose either one.
Now, if a std chooses Comp. then marks in the maths column is 0, likewise for maths.
I am trying to print an individual report cards for 10 students. But one of the label for the optional should display Computer or Mathematics based on the value of the column.
Here is the code i tried
'declare the variables
Dim d As Database
Dim r As Recordset
Dim comp As Field, maths As Field
'the data from the table
Set d = CurrentDb()
Set r = d.OpenRecordset("tbl_student")
Set id = r.Fields("Student ID")
Set comp = r.Fields("Computer")
Set maths = r.Fields("Mathematics")
'check for the column value
While Not r.EOF
If (comp = 0) Then
Me.labelOptional.Caption = "Mathematics"
ElseIf (maths = 0) Then
Me.labelOptional.Caption = "Computer"
Else
Me.labelOptional.Caption = "none"
End If
The result is it captions all the labels the same for all students.
If you want to display different values for different rows in report/form, you should use bound text boxes. Labels and unbound text boxes will be the same for all rows in details section. Add new calculated column for optional label in base query and use it instead of label.

how to extract particular cell to my SQL in EXCEL

Here is a example table in Excel:
ID Name Account
1 Jon 001
2 Snow 002
3 Alive 003
I want to create a SQL according to account. It looks like,
SELECT * FROM CUSTOMER_TABLE WHERE ACCOUNT=' ';
Is it possible to make system could fulfill ACCOUNT=' '? Like system could input each value automatically.
It should like WHERE ACCOUNT='C1', ACCOUNT='C2', ACCOUNT='C3'...
I assume you copied your accounts into a range like Range("E1:E10").
Then you can use a for loop to change accounts for every turn.
Change your Query as,
SQL_Query = "Select * From Customer_Table Where Account ="
then try a For Loop.
Dim Query as String
For i = 1 to 10
Query = SQL_Query & Cells(i,4).value
'Do your query here.
'Be careful about that your results should be copied under the last row.
'Otherwise only the last one will be shown.
Next

Query multiple records between "Weeks" where no record in child table

I am trying to determine the best method for how to handle this query using Access 2013. I have a clients table that contains the following:
clientID fName lName admissionDate dischargeDate
1 John Doe 05/06/2014 06/27/2014
2 Jane Doe 04/24/2014 05/15/2014
3 Steven Smith 05/15/2014 NULL/Empty
4 Chris Davis 06/12/2014 NULL/Empty
Then there is a WeeklyProgressNotes table that is there for the person that is responsible for auditing the clients charts. It does not contain the actual weeklyprogressnotes, it only contains a Yes/No field and a date field for the date the weeklyprogressnote was completed. Like below:
noteID completed dateCompleted clientID
1 yes 05/08/2014 1
2 yes 05/14/2014 1
3 yes 04/25/2014 2
I am creating a form that the auditor can open to determine what weeks she needs to check for each client to see if they have their weeklyprogressnotes completed that week. The weeks run Mon - Sun and there will be no record in the WeeklyProgressNotes table if she has not yet checked and confirmed for that week. So the form would basically look like this:
fName lName week completed date clientID(hidden)
John Doe 5/19/14-5/25/14 Checkbox Null 1
John Doe 5/26/14-6/1/14 Checkbox Null 1
John Doe 6/2/14-6/8/14 Checkbox Null 1
John Doe 6/9/14-6/15/14 Checkbox Null 1
John Doe 6/16/14-6/22/14 Checkbox Null 1
John Doe 6/23/14-6/29/14 Checkbox Null 1
Jane Doe 4/28/14-5/4/14 Checkbox Null 2
and so on.......
I have thought about creating an SQL statement to select all of the clients and then creating a function that determines their admission date within the specific week and their discharge date withing the specific week and then create a loop with another SQL statement with a BETWEEN clause for all the weeks and determine if there is an entry in the WeeklyProgressNotes table or not. If not then I would display out the above info. I'm not sure if there is an easier, less search intensive way of doing it. Maybe an SQL query that can cut done on some of the looping.
The way I would address this problem, is to create a new table. Since you want to split up date time between addmission and discharge date into multiple rows, I think it would be best to split the client in multiple records in a table.
The following code creates a recordset based on your basic clients table. Afterwards it creates your temporary table (Here populated by only 2 fields due to a lack of time). When you loop through the recordset of your original table, you hold on each row and split the time between the addmission and dischargedate in blocks of one week.
Afterwards, once you have populated the table, it is easy to create a simple query based on this table and the table with the weeklyprogressnotes.
I hope my explanation was sufficient and please note that I have not tested the code yet. It will most likely require some tweaking on your behalf. Perhaps I can look at it later on if I've got some more time on my hands.
Sub showrecords()
Dim gvweek As String
Dim rs As Recordset
Dim rstemp As Recordset
Dim tdfNew As TableDef
gvweek = ""
Set tdfNew = CurrentDb.CreateTableDef("Tbl_Temporary")
With tdfNew
.Fields.Append .CreateField("fName", dbText)
.Fields.Append .CreateField("week", dbText)
End With
Set rs = CurrentDb.OpenRecordset("Clients")
With rs
Do Until .EOF
.MoveFirst
Do Until DateAdd("dd", 7, ![admissionDate]) > ![dischargeDate]
gvweek = ![admissionDate] & " - " & DateAdd("dd", 7, ![admissionDate])
Set rstemp = CurrentDb.OpenRecordset("Tbl_Temporary")
With rstemp
.AddNew
![fName] = rs![fName]
![week] = gvweek
.Update
End With
rstemp.Close
Set rstemp = Nothing
Loop
gvweek = ""
.MoveNext
Loop
End With
rs.Close
Set rs = Nothing
DoCmd.DeleteObject acTable, "Tbl_Temporary"
End Sub

Access 2003 - Running an update query based on select query results

I currently have a subform that displays a select query. I want to update all the records of Table B that are showing in the subform with information from the form. The subform is not necessary. I was just using it to make sure my select query was displaying correctly.
Table A has 3 columns (OID, Project_Number, Landowner)
Table B has 4 columns (OID, PhoneNum, Address, Year)
These tables have a one to many relationship. One OID in Table A relates to many in Table B
Table A
1 A10 Bill
2 B10 Sally
3 A10 Bill
Table B
1 555 123 blah st 2012
1 2013
2 111 456 aaa st 2012
3 2012
The form allows the user to enter information that populates Table B.
The subform displays a list of records where Project_Number, Landowner, and Year are equal to the record showing on the form
For example. If the form is showing
1 A10 Bill
the subform is showing
1 A10 Bill 2012
3 A10 Bill 2012
When I click a save command button I would like it to run the update query but I'm having issues with the SQL command.
My Select query is as follows:
SELECT B.Project_Number, A.LANDOWNER, B.Year
FROM A INNER JOIN B ON A.OBJECTID = A.OBJECTID;
The subform is setup
Link Child Fields: Project_Number; Year; Landowner
Link Master Fields: B.Project_Number; Year; A.Landowner
I would like:
UPDATE B.PhoneNum, B.Address, B.Year
WHERE items found in my subform
WITH information from my form
Is it easier to forget the subform and do it all through a single update query?
UPDATE B SET B.phonenum = [New_Info]![PhoneNumCtrl], B.Address = [New_Info]![AddressCtrl]
WHERE [A]![Landowner] = The same landowner as the OID selected, [A]![Project_Number] = The same project number as the OID selected, [New_Info]![Year] = [B]![Year]
Thanks in advance for any help!
Everything is working now. I wanted to add to djphatic's answer.
When doing this make sure to add [Forms]![formname]![controlname]
Depending on where the controls are on your form you may need to change the control reference.
Use the query builder GUI to create a select query which has the columns you wish to update and filter the records using the controls on your form. Once you have this you can change the query to an update query and set the values the controls on your form.
UPDATE B
SET B.phonenum = [formname]![controlname], ...
FROM B JOIN A ON B.OID = A.OID
WHERE A.PROJECTID = [formname]![controlname]
AND B.YEAR = [formname]![controlname]