MS Access Small Equivalent - sql

I have this working in Excel however it really needs moved into Access as that's where the rest of the database resides.
Its simply one table that contains Unique_ID, Seller and Fruit...
1 Chris Orange
2 Chris Apple
3 Chris Apple
4 Sarah Kiwi
5 Chris Pear
6 Sarah Orange
The end results should be displayed by Seller and then a list of each fruit sold (in the following example Robert has not sold any fruit, I do have a list of all sellers name however this could be ignored in this example as that I believe that will be easy to integrate.) They will only sell a maximum of 20 fruit.
Seller 1st 2nd 3rd 4th
Chris Orange Apple Apple Pear
Sarah Kiwi Orange
Robert
At the moment Excel uses Index, Match and Small to return results. Small is simply used on the Unique_ID to find the 1st, 2nd, 3rd, ect...smallest entries and is matched to each sellers name to build the above results.
As Access doesn't have a Small function I am at a loss! In reality there are over 100,000 records (minimum) with over 4000 sellers....they are also not fruit :)

TRANSFORM First(Sales.Fruit) AS FirstOfFruit
SELECT Sales.Seller
FROM Sales
GROUP BY Sales.Seller
PIVOT DCount([id],"sales","seller='" & [seller] & "' and id<=" & [id]);
Where the table name is "Sales" and the columns are "ID", "Seller" and "Fruit"

To understand DCount better, use it is a SELECT query instead of a crosstab:
SELECT Sales.ID, Sales.Seller, Sales.Fruit, DCount([id],"sales","seller='" & [seller] & "' and id<=" & [id]) AS N
FROM Sales;
On each row, the last column is the DCount result. The syntax is DCount (field, source, expression) so what it does is count the IDs (field) in the Sales table (source) that match the expression - in other words, has the same seller as that row's record and an ID <= the current row's ID. So for Chris's sales, it numbers them 1 through 4, even though Sarah had a sale in the middle.
From this result, it's easy to take a Crosstab query that makes a table with seller in the row and N in the column - putting the sales in order for each seller the way you wanted to see them. The "First" function finds the first fruit for the combination of seller and N for each row and column of the result. You could just as easily use "Max" or "Min" here - any text function. Of course, there is only one record matching the seller row and the N column, but Crosstab queries require a function to evaluate and cannot use "Group by" for the field selected as a Value.
My 1st answer combines these steps - the select and the crosstab queries - in one query.
Hope this helps.

Related

Custom Sort Order in CAML Query

How would one go about telling a CAML query to sort the results in a thoroughly custom order?
.
For instance, for a given field:
-- when equal to 'Chestnut' at the top,
-- then equal to 'Zebra' next,
-- then equaling 'House'?
Finally, within those groupings, sort on a second condition (such as 'Name'), normally ascending.
So this
ID Owns Name
————————————————————
1 Zebra Sue
2 House Jim
3 Chestnut Sid
4 House Ken
5 Zebra Bob
6 Chestnut Lou
becomes
ID Owns Name
————————————————————
6 Chestnut Lou
3 Chestnut Sid
5 Zebra Bob
1 Zebra Sue
2 House Jim
4 House Ken
In SQL, this can be done with Case/When. But in CAML? Not so much!
CAML does not have such a sort operator by my knowledge. The workaround might be that you add a calculated column to the list with a number datatype and formula
=IF(Owns="Chestnut",0,IF(Owns="Zebra",1,IF(Owns="House",3,999))).
Now it is possible to order on the calculated column, which translates the custom sort order to numbers. Another solution is that you create a second list with the items to own, and a second column which contains their sort order. You can link these two lists and order by the item list sort order. The benefit is that a change in the sort order is as easy as editing the respective listitems.

using MS Access 2010, editing a form, 3 tables, one table is "one to many" and want to have query across one row

Example:
(using a comma, to show columns & "A_", "B_", "C_" to show tables)
I currently have...
A_John, A_Doe, B_MemStartDate, C_Date,
A_John, A_Doe, B_MemStartDate, C_Date,
A_John, A_Doe, B_MemStartDate, C_Date,
I would like Table "C" columns to be pulled by Course but shown as the "Date" column... in other words, example, where Course = 1, use Date... etc...
The table would have each member's course history.
MemberID, CourseID, Date
JohnDoe, Course1, 10-10-13
JohnDoe, Course2, 10-11-13
JohnDoe, Course3, 10-12-13
The table C is the one to many of course, with the goal to show the date that the course was taken as I would title the columns with the 3 different courses I want to show... (I want to pull only 3 different courses)
I would like to have them in a row...
A_John, A_Doe, B_Start Date, C_Course1Date, C_Course2Date, C_Course3Date
Sorry for the lack of experience in my question, but I usually get by with "copy/paste"...LOL
Keeping in mind I am using Access... can I do this?
Clarifying... sorry don't know how to do tables in basic html so have commas
Have this. Pulling from 3 different tables where the member# is unique and joined.
MEMBER, STARTDATE, STATUS, COURSE, COURSEDATE
JohnSmith, 08-01-2013, Active, Workshop1, 10-20-2013
JohnSmith, 08-01-2013, Active, Workshop2, 10-13-2013
JohnSmith, 08-01-2013, Active, Workshop3, 10-28-2013
LaraBentt, 12-01-2012, Inactive, Workshop1, 02-20-2012
LaraBentt, 12-01-2012, Inactive, Workshop2, 02-13-2012
LaraBentt, 12-01-2012, Inactive, Workshop3, 02-28-2012
Want this...
MEMBER, STARTDATE, STATUS, WORKSHOP1, WORKSHOP2, WORKSHOP3
JohnSmith, 08-01-2013, Active, 10-20-2013, 10-13-2013, 10-28-2013
LaraBentt, 12-01-2012, Inactive, 02-20-2012, 02-13-2012, 02-28-2012
Tables columns are basically like this...
Table 1 - tblMember (one - one)
MEMBER, STARTDATE
Table 2 - tblRegStatus (one - one)
MEMBER, STATUS
Table 3 - tblCourses (one to many)
MEMBER, COURSE, COURSEDATE
Hope this explains it better!
Your amendment to your question made it much more clear.
One of the problems you are going to encounter is if you have someone that has registered for the same course, twice. There has to be the understanding that you are only showing the most recent registration per person. Now that we understand that caveat - lets look at how you can build this.
The simplest way of building this is to change the query type from Select to Crosstab. This is done through the Access interface.
For each of the fields in the query, set the Total and Crosstab values to:
MemberName: Total = *Group By* Crosstab = *Row Heading*
StartDate: Total = *Group By* Crosstab = *Row Heading*
Status: Total = *Group By* Crosstab = *Row Heading*
CourseName: Total = *Group By* Crosstab = *Column Heading*
CourseDate: Total = *Max* Crosstab = *Value*
This will result in query results such as:
MemberName StartDate Status Biology English Math
---------- --------- ------ ------- ------- ----
John 10/1/2013 Active 11/14/2013 12/1/2013
Matthew 9/1/2013 Inactive 1/1/2013
Peter 8/7/2013 Active 1/1/2013 4/1/2013
Sam 1/14/2013 Inactive 11/14/2013
William 5/19/2013 Active 1/1/2013 4/1/2013
The advantage to the crosstab is that it will automatically add columns as there is data.
You have to construct your query (the joins) to give you the data that you want however. For example - do you want to show members that have no courses on the list? Do you want to show courses that have no enrollment?
Microsoft has a page on using crosstab queries:
http://office.microsoft.com/en-us/access-help/make-summary-data-easier-to-read-by-using-a-crosstab-query-HA010229577.aspx
If you want to hard code your three columns, you can also manually pivot the data. Again - keep in mind that we are using the Max aggregate, so only the latest courses will show. With a manual pivot you also need to remember that it will be limited to the data you are requesting.
Take your select query, right click and click "Totals" to show the Totals row. You can also click on the Totals icon in the ribbon under Query Tools / Design.
Set up your three columns:
MemberName: Total = *Group By*
StartDate: Total = *Group By*
Status: Total = *Group By*
Now add in a separate field for each course you wish to include. In the "Field" definition enter the following.
Science: IIf([CourseName]="Science",[CourseDate],Null)
Biology: IIf([CourseName]="Biology",[CourseDate],Null)
Math: IIf([CourseName]="Math",[CourseDate],Null)
English: IIf([CourseName]="English",[CourseDate],Null)
Set the "Total" definition value to "Max".
That should get you the results you are looking for.

Microsoft Access 2010 - Updating Multiple Rows with Different values in ONE query

I have a question about updating multiple rows with different values in MS Access 2010.
Table 1: Food
ID | Favourite Food
1 | Apple
2 | Orange
3 | Pear
Table 2: New
ID | Favourite Food
1 | Watermelon
3 | Cherries
Right now, it looks deceptively simple to execute them separately (because this is just an example). But how would I execute a whole lot of them at the same time if I had, say, 500 rows to update out of 1000 records.
So what I want to do is to update the "Food" table based on the new values from the "New" table.
Would appreciate if anyone could give me some direction / syntax so that I can test it out on MS Access 2010. If this requires VBA, do provide some samples of how I should carry this out programmatically, not manually statement-by-statement.
Thank you!
ADDENDUM (REAL DATA)
Table: Competitors
Columns: CompetitorNo (PK), FirstName, LastName, Score, Ranking
query: FinalScore
Columns: CompetitorNo, Score, Ranking
Note - this query is a query of another query, which in turn, is a query of another query (could there be a potential problem here? There are at least 4 queries before this FinalScore query is derived. Should I post them?)
In the competitors table, all the columns except "Score" and "Ranking" are filled. We would need to take the values from the FinalScore query and insert them into the relevant competitor columns.
Addendum (Brief Explanation of Query)
Table: Competitors
Columns: CompetitorNo (PK), FirstName, LastName, Score, Ranking
Sample Data: AX1234, Simpson, Danny, <blank initially>, <blank initially>
Table: CompetitionRecord
Columns: EventNo (PK composite), CompetitorNo (PK composite), Timing, Bonus
Sample Data1: E01, AX1234, 14.4, 1
Sample Data2: E01, AB1938, 12.5, 0
Sample Data3: E01, BB1919, 13.0, 2
Event No specifies unique event ID
Timing measures the time taken to run 200 metres. The lesser, the better.
Bonus can be given in 3 values (0 - Disqualified, 1 - Normal, 2 - Exceptional). Competitors with Exceptional are given bonus points (5% off their timing).
Query: FinalScore
Columns: CompetitorNo (PK), Score, Ranking
Score is calculated by wins. For example, in the above event (E01), there are three competitors. The winner of the event is BB1919. Winners get 1 point. Losers don't get any points. Those that are disqualified do not receive any points as well.
This query lists the competitors and their cumulative scores (from a list of many events - E01, E02, E03 etc.) and calculates their ranking in the ranking column everytime the query is executed. (For example, a person who wins the most 200m events would be at the top of this list).
Now, I am required to update the Competitors table with this information. The query is rather complex - with all the grouping, summations, rankings and whatnots. Thus, I had to create multiple queries to achieve the end result.
How about:
UPDATE Food
INNER JOIN [New]
ON Food.ID=New.ID
SET Food.[Favourite Food] = New.[Favourite Food]

SELECT datafields with multiple groups and sums

I cant seem to group by multiple data fields and sum a particular grouped column.
I want to group Person to customer and then group customer to price and then sum price. The person with the highest combined sum(price) should be listed in ascending order.
Example:
table customer
-----------
customer | common_id
green 2
blue 2
orange 1
table invoice
----------
person | price | common_id
bob 2330 1
greg 360 2
greg 170 2
SELECT DISTINCT
min(person) As person,min(customer) AS customer, sum(price) as price
FROM invoice a LEFT JOIN customer b ON a.common_id = b.common_id
GROUP BY customer,price
ORDER BY person
The results I desire are:
**BOB:**
Orange, $2230
**GREG:**
green, $360
blue,$170
The colors are the customer, that GREG and Bob handle. Each color has a price.
There are two issues that I can see. One is a bit picky, and one is quite fundamental.
Presentation of data in SQL
SQL returns tabular data sets. It's not able to return sub-sets with headings, looking something a Pivot Table.
The means that this is not possible...
**BOB:**
Orange, $2230
**GREG:**
green, $360
blue, $170
But that this is possible...
Bob, Orange, $2230
Greg, Green, $360
Greg, Blue, $170
Relating data
I can visually see how you relate the data together...
table customer table invoice
-------------- -------------
customer | common_id person | price |common_id
green 2 greg 360 2
blue 2 greg 170 2
orange 1 bob 2330 1
But SQL doesn't have any implied ordering. Things can only be related if an expression can state that they are related. For example, the following is equally possible...
table customer table invoice
-------------- -------------
customer | common_id person | price |common_id
green 2 greg 170 2 \ These two have
blue 2 greg 360 2 / been swapped
orange 1 bob 2330 1
This means that you need rules (and likely additional fields) that explicitly state which customer record matches which invoice record, especially when there are multiples in both with the same common_id.
An example of a rule could be, the lowest price always matches with the first customer alphabetically. But then, what happens if you have three records in customer for common_id = 2, but only two records in invoice for common_id = 2? Or do the number of records always match, and do you enforce that?
Most likely you need an extra piece (or pieces) of information to know which records relate to each other.
you should group by using all your selected fields except sum then maybe the function group_concat (mysql) can help you in concatenating resulting rows of the group clause
Im not sure how you could possibly do this. Greg has 2 colors, AND 2 prices, how do you determine which goes with which?
Greg Blue 170 or Greg Blue 360 ???? or attaching the Green to either price?
I think the colors need to have unique identofiers, seperate from the person unique identofiers.
Just a thought.

Rows to Dynamic columns in Access

I need a setup in Access where some rows in a table are converted to columns...for example, lets say I have this table:
Team Employee DaysWorked
Sales John 23
Sales Mark 3
Sales James 5
And then through the use of a query/form/something else, I would like the following display:
Team John Mark James
Sales 23 3 5
This conversion of rows to columns would have to be dynamic as a team could have any number of Employees and the Employees could change etc. Could anyone please guide me on the best way to achieve this?
You want to create a CrossTab query. Here's the SQL that you can use.
TRANSFORM SUM(YourTable.DaysWorked) AS DaysWorked
SELECT YourTable.Team
FROM YourTable
GROUP BY YourTable.Team
PIVOT YourTable.Employee
Of course the output is slightly different in that the columns are in alphabetical order.
Team James John Mark
Sales 5 23 3
For more detail see Make summary data easier to read by using a crosstab query at office.microsoft.com