Select values from table where value in comma delimited string - ms-access

this is my first post...
I'm busy writing up a piece of software in Access 2010. My SQL's not too bad, but I'm a little stumped here.
I have a table with the following layout
ID = AutoNumber,
Category = Text,
SubCategory = Text,
Grades = Text.
And the following data
ID Category SubCategory Grades
2 Behaviour Good RRR,RR,R,1,2,3,4,5,6,7,8,9,10,11,12
3 Behaviour Not so Good RRR,RR,R,1,2,3,4,5,6,7,8,9,10,11,12
4 Health Doctor Note RRR,RR,R,1,2,3,4,5,6,7,8,9,10,11,12
5 Social Peer Pressure
6 Academics General Academic Knowledge 1,2,3
7 Academics Additional Academic Knowledge 1,2,3
8 Gross Motor Skills Kicks a ball that is moving towards him or her.
9 Gross Motor Skills Hops and jumps while in motion R
10 Gross Motor Skills Skips RR
11 Gross Motor Skills Gallops RR
12 Gross Motor Skills Jumps forward 10 times RR
13 Gross Motor Skills Catches a small bounced ball RR
14 Gross Motor Skills Turns somersault RR
15 Gross Motor Skills Alternates feet walking up or down stairs RR`
I'm trying to create a query where I select for eg
SELECT SubCategory from CATEGORY WHERE GRADES LIKE R
and it should return
Good
Not so Good
Doctors Note
Peer Pressure
Hops jumps and Skips
and obviously if I require Grades RRR or 1 or 2 or 5 it should select as needed
please can anyone assist.
Thanks
Warren

You can do it with the operator LIKE this way:
SELECT SubCategory
FROM CATEGORY
WHERE ',' + GRADES + ',' LIKE '*,R,*'
or if you want the queried value 'R' separately as a parameter:
SELECT SubCategory
FROM CATEGORY
WHERE ',' + GRADES + ',' LIKE '*,' + 'R' + ',*'

Related

MS Access - create and populate column containing concatenated text separated by commas with no repeating values

I have two tables in MS Access, one with foods and associated companies:
FoodID
Food
Company
1
Apple
Vino Farms
2
Orange
Citrus Co.
3
Banana
Vino Farms
and one with information about whether someone ate the food
ClientID
ClientName
Apple
Orange
Banana
1
Bob
Yes
No
Yes
2
Tyler
Yes
Yes
Yes
3
Joe
No
No
No
I'd like to write a query that creates a column populated by the company that makes the foods someone reported eating, separated by commas. If someone reports eating a more than one food made by the same company, I only want the company's name listed once:
ClientID
ClientName
AssociatedCompanies
1
Bob
Vino Farms
2
Tyler
Vino Farms, Citrus Co.
3
Joe
Any help would be greatly appreciated!
As indicated by Gustav, start by normalizing your "ate food" Table. It should look like:
1 Bob Apple
1 Bob Banana
2 Tyler Apple
2 Tyler Orange
2 Tyler Banana
You then get what you want with the following Query:
-- Group companies into one field, sepparated with commas
SELECT ClientID, ClientName, RemoveCommas(Company1 & ", " & Company2 & ", " ... & CompanyN)
FROM
( -- Convert rows (records) into columns (fields)
SELECT ClientID, ClientName
, Max(Iif(Company="Vino Farms", "Vino Farms", Null)) AS Company1
, Max(Iif(Company="Citrus Co.", "Citrus Co.", Null)) AS Company2
, ...
, Max(Iif(Company="Last_company", "Last_company", Null)) AS CompanyN
FROM
(-- Replace food by its manufacturing company
SELECT DISTINCT ClientID, ClientName, Company
FROM
Table_ate_food_normalized AS Ate
INNER JOIN
Table_food AS Comp
ON Ate.Food = Comp.Food
)
GROUP BY ClientID, ClientName
)
Notice the following relevant points:
This will only work, as you notice, for a fixed number of companies with names hardcoded in the Query. This is a very severe limitation. If these restrictions are not satisfied, I suggest that you use a TRANSFORM Query, but, you would not get the companies as a single text field with values sepparated by commas, and you would rather get them as a variable number of fields, each field having a Yes/No value (similar to your current "ate food" table).
I am assuming that the values of "food" and "Company" are each a candidate key in its Table. Otherwise, use the corresponding ID fields, and get the actual values using an inner join.
If you want to understand better the part of converting rows into columns, you may check the Query "K_rows_into_columns_1" from the database of examples dowloadable from LightningGuide.net.
You have to code the user defined VBA function "RemoveCommas()" to remove unncessary commas from the string containing the listing of companies. If unncessesary commas do not bother you, then you can do the Query without coding this functions.
If you want to code the TRANSFORM alternative that I suggested above, you may check the Query "K_rows_into_columns_2" from the database of examples dowloadable from LightningGuide.net.

Data warehouse logical model

I have drawn a logical model for a hotel room booking OLTP system Logical model
I'm facing a problem querying it.
the question is: For each Country and quarter, produce the cumulative income of 3-star-rooms
Noted that RoomBand contain how many starts for each room
I have tried this
SELECT Quarter, Country
FROM DT_Date, Country, RoomBand
where RoomBand = 3
the output was this
CountyName Quarter
USA 2
Uk 1
USA 2
UK 1
as it has shown it repeated USA and UK
why is that happening
Thanks for the support all
Try the DISTINCT operator with your query. For example: SELECT DISTINCT column1, column2, .... You can read more about it here.

Is mysql database logic suitable for query?

I am designing a database, and I would like to know;
Can I answer this question with queries, how much skill employees earned from this trainings?
Is this a good structure to do it?
how much money spent per department
how much skill earned per employee
how much skill earned per department
id session_name Skill impact sugg dept function training_value training no
1 PHP Software 3 Sales 2 100usd 1
2 PHP Software 3 Finance 2 100usd 1
3 PHP communication 2 Sales 2 100usd 1
4 PHP communication 2 Finance 2 100usd 1
5 ASP Software 4 Sales 2 200usd 2
6 ASP Software 4 Finance 2 200usd 2
7 ASP database 1 Sales 2 200usd 2
8 ASP database 1 Finance 2 200usd 2
attended training table
id student_id training_no
1 1 1
1 1 2
student table
id name department
1 John 1
2 Mary 2
department table
id name
1 sales
2 finance
In the end I need to find skills for each student
john
software 7
communication 2
database 1
total spent
john 300 usd
total spent by department
sales 300 usd
Your schema looks OK to me.
You should, however, think about entities and relationships.
Your entities seem to be trainings, people, and departments.
You have a many:many relationship for people:trainings. That's good.
You have a one:many relationship for departments:people. That's also good.
It looks like you want some kind of relationship for trainings:departments. I'm guessing here, but you have a sugg dept column in your trainings table. Is that supposed to have a direct relationship to your departments table?
Do you actually need an extra entity called "attendance" rather than just a many-to-many relationship people:trainings. Do you want to record when a person did a training? Do you want to record how much that particular attendance cost? How about what marks they received if there was a quiz?
In that case, you'll want relationships where each person has zero or more attendances, each attendance has exactly one training, and each training has zero or more attendances.
My point: do the hard work of thinking through your entities and relationships, and the result will be a good design for your tables.
If I may put it another way: What part of the real world are you trying to capture in your data base? What's valuable in the real world that you want your data base to hold? In your application ...
Students are people. They are, umm, inherently valuable and persistent entities.
Trainings represent the labor and cost of creating them and presenting them.
Attendances represent the effort of students.
Departments probably pay the bill for attendances. They certainly represent power centers in your application.
What other items of value exist in this corner of the real world? Teachers? Managers? Venues (classrooms)? Equipment? Customers?
My point is, figure out your entities -- the items of value -- and the relationships between them. Then write your table definitions.

Getting data from multiple tables into single row while concatenating some values

I'm trying to retrieve data from tables and combine multiple rows into a single column, without repeating any information.
I have the following tables: profile, qualification, projects.
Profile
pro_id surname firstname
------ ------- ----------
1 John James
2 King Fred
3 Luxury-Yachts Raymond
Qualification
pro_id Degree School Year
------ ------ ------ -----
1 MBA Wharton university 2002
1 LLB Yale University 2001
2 BSc Covington University 1998
2 BEd Kellog University 1995
Projects
pro_id Title Year
------ ------ ------
1 Social Networking 2003
1 Excavation of aquatic debris 2007
2 Design of solar radios 1992
2 Development of expert systems 2011
I want to retrieve the all of the information for each person, with each person appearing only once in the result. The info on qualifications and projects should each be in their own column (one column for qualifications, another for projects), separated by commas. For example, the results for the above sample data should be:
1 John James MBA Wharton university 2002, LLB Yale University 2001 Social Networking 2003, Excavation of aquatic debris 2007, Design of Solar panels 2008
2 King Fred BSc Covington University 1998, BEd Kellog University 1995, Msc MIT 2011 Design of solar radios 1992, Development of expert systems 2011
3 Raymond Luxury-Yachts
Currently, I have the query:
SELECT pro_id,
surname,
firstname,
group_concat(degree,school,year) AS qual,
concat(Title,year) AS work
FROM profile,
LEFT JOIN qualification
ON qualification.pro_id = profile.pro_id
JOIN projects
ON projects.pro_id = profile.pro_id
GROUP BY pro_id
For the sample data, this query results in:
1 John James MBA Wharton university 2002, Social Networking 2003
1 John James LLB Yale University 2001, Excavation of aquatic debris 2007
1 John James MBA Wharton university 2002, Social Networking 2003, Excavation of aquatic debris 2007
etc
Note: Raymond Luxury-Yachts isn't present in the current result.
I don't want duplicate result records. Also if the surname does not have any entry in the qualification and projects table, I want the query to return the name and display an empty field in the qualification and projects table instead of omitting them altogether.
Replace LEFT JOIN with JOIN
Select pro_id, surname, firstname, group_concat(degree,school,year) as qual,concat(Title,year) as work
from profile
join qualification on qualification.pro_id = profile.pro_id
join projects on projects.pro_id = profile.pro_id group by pro_id
What is the difference between "INNER JOIN" and "OUTER JOIN"?
Using Join will fix the issue with displaying values even if there are no records in the projects table.
For the first question, you can try making a stored function and calling it from the select statement. This function will take pro_id as parameter, create the concatenated string and return it. That's the only solution for MySQL that I can think of at the moment.
I think you are close on your thoughts of group_concat. However, with possible No values (thus leaving nulls), can cause problems. I would have each secondary table pre-concatinated by person's ID and join to THAT result. Eliminates the problem of nulls
SELECT
p.pro_id,
p.surname,
p.firstname,
PreQConcat.UserQual,
PrePJConcat.UserWork
FROM
profile p
LEFT JOIN
( select q.pro_id,
group_concat( q.degree, q.school, q.year) AS UserQual
from
qualification q
group by
q.pro_id ) PreQConcat
ON p.Pro_ID = PreQConcat.pro_id
LEFT JOIN
( select pj.pro_id,
concat(pj.Title, pj.year) AS UserWork
from
projects pj
group by
pj.pro_id ) PrePJConcat
ON p.Pro_ID = PrePJConcat.pro_id
You are going through all people anyhow, and want all their respective elements (when they exist) grouped, so why group on a possibility it doesn't exist. Let the JOINED queries run once each, complete with a single result grouped by only those people it had data for, then join back to the original profile person.

Subquery in Access

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.