I have a this Table in MS Access:
Table1
ID EMP ROLE ASSESS
1 JOE Weld 4
2 TOM Weld 4
3 JIM Ship 4
4 PAT Ship 3
5 JAY Weld 4
6 TIM Ship 4
"ROLE" is short text and "ASSESS" is a number field. "ASSESS" is assessing employees' roles on a scale of 1-4. I want to collect and total assessments that are "4" for each role.
Returning something like:
ROLE TOTAL
Weld 3
Ship 2
I however have around 100 different roles that I am needing to do this with. Is there a way with SQL or a combination of query and macro to make this work? I am at a loss.
Thank you.
You could use a where clause to filter just the the assesses that are 4 and a group by clause to aggregate them:
SELECT role, COUNT(*)
FROM table
WHERE assess = 4
GROUP BY role
Related
I'm building a e-Commerce platform (PHP + MySQL) and I want to add a attribute (feature) to products, the ability to specify (enable/disable) the selling status for specific city.
Here are simplified tables:
cities
id name
==========
1 Roma
2 Berlin
3 Paris
4 London
products
id name cities
==================
1 TV 1,2,4
2 Phone 1,3,4
3 Book 1,2,3,4
4 Guitar 3
In this simple example is easy to query (using FIND_IN_SET or LIKE) to check the availability of product for specific city.
This is OK for 4 city in this example or even 100 cities but will be practical for a large number of cities and for very large number of products?
For better "performance" or better database design should I add another table to table to JOIN in query (productid, cityid, status) ?
availability
id productid cityid status
=============================
1 1 1 1
2 1 2 1
3 1 4 1
4 2 1 1
5 2 3 1
6 2 4 1
7 3 1 1
8 3 2 1
9 3 3 1
10 3 4 1
11 4 3 1
For better "performance" or better database design should I add
another table
YES definitely you should create another table to hold that information likewise you posted rather storing in , separated list which is against Normalization concept. Also, there is no way you can gain better performance when you try to JOIN and find out the details pf products available in which cities.
At any point in time if you want to get back a comma separated list like 1,2,4 of values then you can do a GROUP BY productid and use GROUP_CONCAT(cityid) to get the same.
I've been making an award system in ms access but trying to use the if statement for 2 distinct parameters, i.e. in one class top 3 students get a different amount from what the top 3 students of another class might get. All the data of all classes is in one table.
See:
Student ID Class ID Average Rank Awards
1111 Form4 77.79166667 2
1189 Form4 105 1
1222 Form4 73.41666667 3
1234 Form4 69.95833333 4
1235 Form 3 77.16666667 3
1236 Form 3 72.875 4
1258 Form 3 82.54166667 1
1333 Form 3 77.25 2
1367 Form 2 56.54545455 4
1445 Form 2 75.66666667 2
1447 Form 2 75.72727273 1
1465 Form 2 74.18181818 3
1523 Form 1 76.18181818 3
1542 Form 1 75.51515152 4
1552 Form 1 79.03030303 2
1555 Form 1 79.63636364 1
at the awards column when creating a query the build formula I use i.e. IIf([Rank]=1,1100) gives all student IDs ranked 1 an award of 1100 but I want only form 1 student IDs to get 1100 and the others ranked 1st with different award values please assist.
I think you want something like:
IIF([ClassID] <> "Form 1", IIf([Rank]=1,500), IIf([Rank]=1,1100))
Obviously, you will have to edit the award amount since you didn't specify what you were giving, but the logic should hold true.
If this gets a bit more complicated, you can write a function in VBA (in any code module in the 'modules' section), and use it in the query:
ExpressionName: evaluateAward(ClassID, Rank)
In the function, you can then use nested select case statements. This may be much better for readability.
My question about SEARCH query performance.
I've flattened out data into a read-only Person table (MySQL) that exists purely for search. The table has about 20 columns of data (mostly limited text values, dates and booleans and a few columns containing unlimited text).
Person
=============================================================
id First Last DOB etc (20+ columns)...
1 John Doe 05/02/1969
2 Sara Jones 04/02/1982
3 Dave Moore 10/11/1984
Another two tables support the relationship between Person and Activity.
Activity
===================================
id activity
1 hiking
2 skiing
3 snowboarding
4 bird watching
5 etc...
PersonActivity
===================================
id PersonId ActivityId
1 2 1
2 2 3
3 2 10
4 2 16
5 2 34
6 2 37
7 2 38
8 etc…
Search considerations:
Person table has potentially 200-300k+ rows
Each person potentially has 50+ activities
Search may include Activity filter (e.g., select persons with one and/or more activities)
Returned results are displayed with person details and activities as bulleted list
If the Person table is used only for search, I'm wondering if I should add the activities as comma separated values to the Person table instead of joining to the Activity and PersonActivity tables:
Person
===========================================================================
id First Last DOB Activity
2 Sara Jones 04/02/1982 hiking, snowboarding, golf, etc.
Given the search considerations above, would this help or hurt search performance?
Thanks for the input.
Horrible idea. You will lose the ability to use indexes in querying. Do not under any circumstances store data in a comma delimited list if you ever want to search on that column. Realtional database are designed to have good performance with tables joined together. Your database is relatively small and should have no performance issues at all if you index properly.
You may still want to display the results in a comma delimted fashion. I think MYSQL has a function called GROUP_CONCAT for that.
I have 2 tables in Access with these fields
Student:
ID(PK) Name Family Tel
Lesson:
ID StudentRef(FK(Student)) Name Score
Imagine we have these records
Student :
1 Tom Allen 09370045230
2 Jim leman 09378031380
Lesson:
1 1 Math 18
2 1 Geography 20
3 2 Economic 15
4 2 Math 12
How can I write a query that result will be this (2 fields)?
Tom Math : 18 , Geography 20
Jim Economic :15 , Math :12
SELECT s.Name, l.Name, l.Score
INNER JOIN tbl_lessons as l ON s.student_id = l.student_id
FROM tbl_students as s
That won't give you your formatting, but it'll get you the data.
The most tricky part of your problem is how to aggregate strings in your sub-query. MS Access does not have any aggregation function that is applicable to strings (except for Count()) and there is no way to define your own function. This means you can't just get the desired "subject:score , subject:score" concanetation. As long as you can go without you can easily take the solution provided in the answer by Corith Malin.
Supoose I have the following:
tbl_options
===========
id name
1 experience
2 languages
3 hourly_rate
tbl_option_attributes
=====================
id option_id name value
1 1 beginner 1
2 1 advanced 2
3 2 english 1
4 2 french 2
5 2 spanish 3
6 3 £10 p/h 10
7 3 £20 p/h 20
tbl_user_options
================
user_id option_id value
1 1 2
1 2 1
1 2 2
1 2 3
1 3 20
In the above example tbl_user_options stores option data for the user. We can store multiple entries for some options.
Now I wish to extend this, i.e. for "languages" I want the user to be able to specify their proficiency in a language (basic/intermediate/advanced). There will also be other fields that will have extended attributes.
So my question is, can these extended attributes be stored in the same table (tbl_user_options) or do I need to create more tables? Obviously if I put in a field "language_proficiency" it won't apply to the other fields. But this way I only have one user options table to manage. What do you think?
EDIT: This is what I propose
tbl_user_options
================
user_id option_id value lang_prof
1 1 2 null
1 2 1 2
1 2 2 3
1 2 3 3
1 3 20 null
My gut instinct would be to split the User/Language/Proficiency relationship out into its own tables. Even if you kept it in the same table with your other options, you'd need to write special code to handle the language case, so you might as well use a new table structure.
Unless your data model is in constant flux, I would rather have tbl_languages and tabl_user_languages tables to store those types of data:
tbl_languages
================
lang_id name
1 English
2 French
3 Spanish
tbl_user_languages
================
user_id lang_id proficiency hourly_rate
1 1 1 20
1 2 2 10
2 2 1 15
2 2 3 20
3 3 2 10
Designing a system that is "too generic" is a Turing tarpit trap for a relational SQL database. A document-based database is better suited to arbitrary key-value stores.
Excepting certain optimisations, your database model should match your domain model as closely as possible to minimise the object-relational impedance mismatch.
This design lets you display a sensible table of user language proficiencies and hourly rates with only two inner joins:
SELECT
ul.user_id,
u.name,
l.name,
ul.proficiency,
ul.hourly_rate
FROM tbl_user_languages ul
INNER JOIN tbl_languages l
ON l.lang_id = ul.lang_id
INNER JOIN tbl_users u
ON u.user_id = ul.user_id
ORDER BY
l.name, u.hour
Optionally you can split out a list of language proficiencies into a tbl_profiencies table, where 1 == Beginner, 2 == Advanced, 3 == Expert and join it onto tbl_user_languages.
i'm thinking it's a mistake to put "languages" as an option. while reading your text it seems to me that english is an option, and it might have an attribute from option_attributes.