Counting value from various columns - sql-server-2008

I have a table
school code school_name subcode1 subcode2 subcode3
001 xyz 56 55 54
002 abc 55 56 54
003 xyz 54 55 56
Suppose 56=english or 55=hindi and I want to check that school xyz is have how many English subject or how many Hindi subject etc.
I have used count(*) function on where condition like:
select count(*)
from schooltable
where (subcode1 = '55' or subcode2 = '55' or subcode3 = 55)
and school_name='abc'
But it give only the one result I want get all records about all schools and want to insert it like this
scode schoolname sub sub sub
eng hindi history
001 abc 3 2 3
Help required.

you could do a conditional sum, something like this
select sum(case when subcode1='55' or subcode2='55' or subcode3=55 then 1 else 0 end) as hindi,
sum(case when subcode1='56' or subcode2='56' or subcode3=56 then 1 else 0 end) as english
from schooltable
--where school_name='abc' (not sure if you really require this constraint, although you have it in your question)
you could add a GROUP BY clause if required, but this would depend on your exact requirements, database structure, primary keys, etc. But the above should at least get you started.

Try this,
select school_name,count(*) as TotalSub from schooltable
group by school_name, subcode1,subcode2,subcode3
having school_name = 'abc'

Related

MYSQL query - cross tab? Union? Join? Select? What should I be looking for?

Not sure what exactly it is I should be looking for, so I'm reaching out for help.
I have two tables that through queries I need to spit out one. the two tables are as follows:
Transactions:
TransactionID SiteID EmployeeName
520 2 Michael
521 3 Gene
TransactionResponse:
TransactionID PromptMessage Response PromptID
520 Enter Odometer 4500 14
520 Enter Vehicle ID 345 13
521 Enter Odometer 5427 14
521 Enter Vehicle ID 346 13
But what I need is the following, let's call it TransactionSummary:
TransactionID SiteID EmployeeName 'Odometer' 'VehicleID'
520 2 Michael 4500 345
521 3 Gene 5427 346
The "PromptID" column is the number version of "PromptMessage" so I could query off that if it's easier.
A good direction for what this query would be called is the least I'm hoping for. True extra credit for working examples or even using this provided example would be awesome!
For a predefined number of possible PromptID values you can use something like the following query:
SELECT t.TransactionID, t.SiteID, t.EmployeeName,
MAX(CASE WHEN PromptID = 13 THEN Response END) AS 'VehicleID',
MAX(CASE WHEN PromptID = 14 THEN Response END) AS 'Odometer'
FROM Transactions AS t
LEFT JOIN TransactionResponse AS tr
ON t.TransactionID = tr.TransactionID AND t.SiteID = tr.SiteID
GROUP BY t.TransactionID, t.SiteID, t.EmployeeName
The above query uses what is called conditional aggregation: a CASE expression is used within an aggregate function, so as to conditionally account for a subset of records within a group.

SQL - How to query for multiple WHERE values with AND operator

I'm a SQL newbie and have been searching for an answer to this but haven't found it yet. Say I want to query for all students that got a score of 80 from a table named students. How would I go about it? I have tried this so far, but it looks like the IN operator is similar to OR since it is giving me results of everyone that got an 80 on any of the tests.
SELECT * FROM students
WHERE test_name IN ('Quiz','Midterm','Final')
AND test_scores='80';
Thank you ahead of time for the assistance!
Sample data:
Test Name | Student ID | Student Name | Test Score
Quiz | 10 | Tom | 80
Midterm | 50 | Sally | 70
The results I would like to get back are all the columns of students who got 80 for all three tests. I apologize for the delay, but I guess I don't have the email notifications working properly. I did warn you I was new. I'm going to try the recommended steps to see how it goes. I'll report back.
One way is to negate the sense of the test, and then exclude those students:
SELECT *
FROM students
WHERE student_id NOT IN (
SELECT student_id
FROM students
WHERE test_name IN ('Quiz','Midterm','Final')
AND test_scores != '80';
)
AND test_name IN ('Quiz','Midterm','Final')
You can use aggregation with a having clause, assuming that you want a score of 80 on all three tests:
SELECT student_id
FROM students
WHERE test_name IN ('Quiz','Midterm','Final')
GROUP BY student_id
HAVING SUM(test_score = 80 and test_name = 'Quiz') > 0 AND
SUM(test_score = 80 and test_name = 'Midterm') > 0 AND
SUM(test_score = 80 and test_name = 'Final') > 0;

Compute the total number of accepted papers that are authored by at least two authors

It is a conference management SQL database
The task is to compute the total number of accepted papers that are authored by at least two authors.
I am just stuck with the sum up function after group by the paper ID
paperparticipant
RegNum PPNum
0001 001
0002 0
0003 0
0004 002
0005 0
0006 001
0007 0
0008 003
0009 003
0010 003
The above is the sample data and the table
What I want to output is just the number of 2
I can just code
Select Count(AuID) from paperauthorid group by PPNum having Count(AuID)>= 2
that it output something like
Count(AuID)
3
3
I just want to output that there are two papers (that have number of more than 2 authors)
You could just wrap the existing query in another aggregate query:
SELECT COUNT(*)
FROM (SELECT COUNT(AuID)
FROM paperauthorid
GROUP BY PPNum
HAVING COUNT(AuID)>= 2) t
Try the following code:
SELECT COUNT(1)
FROM paperauthorid
GROUP BY ppnum
HAVING COUNT(auid)>= 2
LIMIT 1;

Robust SQL query on demographics data set

I have a rather complex SQL Server query (at least to me) to write on a demographics data set. I need to figure out how many respondents in the system mathc a specific demographic.
I have 2 main tables. I will list the relevant columns. Assume there are unique ID's on each row.
Table Respondents:
[RespondentID] [SystemEntryDate]
Table RespondentProfiles:
[QuestionID] [AnswerID]
The respondent ID on Respondents links to RespondentProfiles. For each question answered, a row is created. The question id corresponds to a specific question (say gender, ethnicity, state, and car ownership) and the answer id means something different depending on the question. Like 1 is male and 2 is female, or 1 might be white, 2 hispanic, 3 pacific islander, and so on.
I also have a table called Conditions. The conditions table looks like this:
[ConditionSetID] [QuestionID] [AnswerID]
The condition set id links to the conditions together into a collection of conditions. So i can pass a condition set id to the query, and it will return a count of how many respondents meet that criteria, as well as the min and max dates from that set.
My query will look something like this:
create procedure query
#ConditionSetID int
as
select count(distinct r.ID) as Respondents,
min(r.SystemEntryDate) as EarliestDate,
max(r.SystemEntryDate) as LatestDate
from Respondents r
join RespondentProfiles rp
on r.ID = rp.RespondentID
join Conditions c
on c.ConditionSetID = #ConditionSetID
and c.QuestionID = rp.QuestionID
where rp.QuestionID = c.QuestionID
and rp.Condition = c.AnswerID
As an example, I might have a respondent profiles table like this
[RespondentID] [QuestionID] [AnswerID]
10001 1 (gender) 1 (male)
10001 2 (ethnicity) 1 (white)
10001 3 (car) 23 (lexus)
10002 1 (gender) 2 (female)
10002 2 (ethnicity) 2 (black)
10002 3 (car) 24 (buick)
10003 1 (gender) 2 (female)
10003 2 (ethnicity) 1 (white)
10003 3 (car) 5 (honda)
10004 1 (gender) 1 (male)
10004 2 (ethnicity) 2 (black)
10004 3 (car) 24 (buick)
And if I pick a specific condition set, the rows id have might be like:
[QuestionID] [AnswerID]
1 (gender) 2 (female)
2 (ethnicity) 2 (black)
3 (car) 24 (buick)
This would be asking for all the black females who own a buick, which should give em a count of 1.
Or I could have:
[QuestionID] [AnswerID]
3 (car) 23 (lexus)
3 (car) 24 (buick)
This is asking for everyone who owns a buick or lexus, which would be 3 people.
And then as a final example:
[QuestionID] [AnswerID]
2 (ethnicity) 2 (black)
3 (car) 23 (lexus)
3 (car) 24 (buick)
This is asking for everyone who is black and owns a lexus or everyone who is black and owns a buick, which would be 2 people.
I know this isn't horribly complicated, but it is the most complex thing I've attempted yet, and any help would be greatly appreciated. I'm having a lot of trouble figuring out how to set up the where clause, and even general direction would be appreciated. There are also about 800,000 records in the respondentprofiles table, so it must be efficient.
The where clause I have set up isn't quite correct, because it will only get the records as if the different questions are being or'd together as opposed to and'ed. So it will return a row for that respondent even if only one answer matches, which is wrong. A particular respondent must meet all the conditions in the condition set to be selected.
Perhaps I need to select into a temp table question at a time or something? Or use some sort of grouping? I am just really confused on where to go with this. I hope I have provided enough information to adequately demonstrate my dilemma.
The examples below show how to get the respondent IDs of respondents who answered:
To question A, Yes
To question B, No
TO question C, Yes
Assuming you are actually using SQL server (you tagged both mysql and sql server in your question), you can use:
select id
from RespondentProfiles
where QuestionID = 'a'
and AnswerID = 'yes'
intersect
select id
from RespondentProfiles
where QuestionID = 'b'
and AnswerID = 'no'
intersect
select id
from RespondentProfiles
where QuestionID = 'c'
and AnswerID = 'yes'
Or if you are using MySQL you can use:
select id
from RespondentProfiles x
where QuestionID = 'a'
and AnswerID = 'yes'
join (select id
from RespondentProfiles
where QuestionID = 'b'
and AnswerID = 'no') y
on x.id = y.id
join (select id
from RespondentProfiles
where QuestionID = 'c'
and AnswerID = 'yes') z
on y.id = z.id
Just to add to my answer what I put in the comments - there is no need for your conditions table. You do not need to have such a table in order to query for respondents who answers 2+ questions a certain way. You can use inline views and/or subqueries to accomplish that. (or in the case of sql server, the intersect set operator)

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.