I am using the following query to retrieve the number of events per state from 2 tables that are linked by a userID.
SELECT state,COUNT(*) AS num
FROM tableUserInfo
WHERE userID IN (SELECT userID
FROM tableEvents
WHERE conditionOne = 1
AND conditionTwo = 2)
GROUP BY state
This query works correctly. My problem is that not all states have user entries, and I need the query to return 0 for those. I was wondering if there was a method such as joining or using an in clause, that would included a set of all states, making the query return 0 for any that didn't have entries in tableEvents?
Do you have a list of states? If not then this would give a list of all the states your database knows about:
SELECT DISTINCT state FROM tableUserInfo
....and enclosing this in brackets it can be dropped in place in the query below:
SELECT s.state, IFNULL(cnt, 0) AS num
FROM list_of_states s
LEFT JOIN (
SELECT state,COUNT(*) AS cnt
FROM tableUserInfo ui
INNER JOIN tableEvents te
ON ui.userId=te.userId
WHERE conditionOne = 1
AND conditionTwo = 2
GROUP BY state
) u
ON s.state=u.state;
Although in the absence of "list_of_states" it would be more efficient to do this:
SELECT ui.state, SUM(IF(te.userId IS NULL, 0, 1)) AS cnt
FROM tableUserInfo ui
LEFT JOIN tableEvents te
ON ui.userId=te.userId
AND te.conditionOne = 1
AND te.conditionTwo = 2
GROUP BY state;
As #raymond-nijland suggested you can use Left Join to include all states.
SELECT tableUserInfo.state,COUNT(tableUserInfo.*) AS num
FROM tableUserInfo Left Join tableEvents on tableUserInfo.userID = tableEvents.userID
WHERE tableEvents.conditionOne = 1 AND tableEvents.conditionTwo = 2
GROUP BY state
Related
I've the following SQL Query which runs perfectly fine but now i want to calculate the count based on the following scenario:
SELECT d.vseverity, v.vulnstatus, v.vtitleid, d.vtitle
FROM vulnsummary v
JOIN project p ON v.projid = p.projid
AND v.stagename = p.currentstage
JOIN datasets d ON v.vtitleid = d.datasetid
The current Output is:
Now i want to show the count like this way:
High (Open) - 2
High (Closed) - 0
Medium (Open) - 1
Medium (Closed) - 0
Low (Open) - 3
Low (Closed) - 1
Please help me to solve this query, Thank You
You need to CROSS JOIN the distinct sets of severity and status values and then LEFT JOIN that to your table to allow you to count the values of each severity/status combination. Without sample data it's hard to be certain but something like this should work:
SELECT sv.vseverity, st.vulnstatus, COUNT(v.vseverity) AS count
FROM (
SELECT DISTINCT vseverity
FROM datasets
) sv
CROSS JOIN (
SELECT DISTINCT vulnstatus
FROM vulnsummary
) st
LEFT JOIN (
SELECT d.vseverity, v.vulnstatus
FROM vulnsummary v
JOIN project p ON v.projid = p.projid
AND v.stagename = p.currentstage
JOIN datasets d ON v.vtitleid = d.datasetid
) v ON v.vseverity = sv.vseverity AND v.vulnstatus = st.vulnstatus
GROUP BY sv.vseverity, st.vulnstatus
I don't have your full dataset, however, a RIGHT OUTER JOIN to a master volnstatus table will enable (the volnstatus table showing all options i.e. 'Open', 'Closed'). A rough draft example, with only the volnstatus table populated:
SELECT COUNT(s.vulnstatus) CountOf, t.vtype
FROM dbo.vusummary s
RIGHT OUTER JOIN
vusummarytype t
ON s.vulnstatus = t.vtype
GROUP BY t.vtype
in barcodes table i have two column witch they are enter, exit like with student attendance record,
in this table when student entered to class, i add new row in table and enter value is 1 and exit is 0 like with login
after exiting from classroom i check latest row of this student and if enter is 1 then i add new row in table with 1 value for exit like with logout
now i want to calculate counting all students witch enter column is 1 and exit value is 0 to get all present students in class
SAMPLE DATA:
in this DB-FIDDLE i have sample data and into that i have 2 present student that session_id of them is 1, they are 123451,123452 students, but my sql command as second part is incorrect and that return one present student:
(
select count(*)
from barcodes b
where b.session_id = s.id
group by session_id, barcode
having sum(exit) = 0
) as present
for example:
select s.id, s.session_name, s.session_type, s.date_time,
(
select count(*)
from barcodes b where b.session_id = s.id
) as barcode_count ,
(
select count(*)
from barcodes b
where b.session_id = s.id
group by session_id, barcode
having sum(exit) = 0
) as present
from sessions s;
If I get what you want to do right, you can add another, outer aggregation.
...
(SELECT sum(x.count)
FROM (SELECT count(*) count
FROM barcodes b
WHERE b.session_id = s.id
GROUP BY b.session_id,
b.barcode
HAVING sum(b.enter) <> 0
AND sum(b.exit) = 0) x) present
...
But I think there's a much simpler way to get what you want by just taking the sum of enter minus exit for the session. Since any row with exit = 1 also comes with enter = 1, we need to double the exit before subtraction though.
...
(SELECT sum(b.enter - 2 * b.exit)
FROM barcodes b
WHERE b.session_id = s.id) present
...
If you can trust the data, something like this could work:
select
s.id,
s.session_name,
s.session_type,
s.date_time,
count(*) as barcode_count,
sum(exit = 0) - sum(exit = 1) as present
from sessions s
left join barcodes b on b.session_id = s.id
group by s.id, s.session_name, s.session_type, s.date_time
db-fiddle
You can read sum(exit = 0) - sum(exit = 1) as (number of entries) - (number of exits). If 4 students entered a class and 2 left the class, I would expect 2 students (4 - 2) to be still in the class.
i am trying to write the Query for three things .My table structure is like that
You can see Schema at http://sqlfiddle.com/#!2/56c2d/1
I am trying to write the query in MYSQL
user:- table
user_id
user_fname
This is User tabke which will save User Information
group:- "group" and "subgroup" is maintain in same table using column "group_parent_group_id"
group_id
group_title
group_parent_group_id(INT)
This is group table which will save Group and Subgroups
user_group: table
user_group_id
user_group_user_id
user_group_group_id
This ill store both User and Group relation using their Id
I am trying to write the Query for three things. Fetching Users Groups, Subgroups
1) Query to fetch list of All Groups for User Register. Query is gelow and is giving error
Query:
select user.id, user.user_fname, group.group_id, group.group_title
from `user`
inner join user_group on user_group.user_group_user_id = user.user_id
inner join group on group.group_id = user_group.user_group_group_id
where user_group.user_group_user_id = 1 and user_group.group_parent_group_id = 0
2) I am Looking the query to fetch all subgroups(For Whom user is already Register) for Group Id 1,2 or 1
3) I am Looking the query to fetch all subgroups(For Whom user is Not Register yet) for Group Id 1,2 or 1. Ideal is for giving him randomly suggest a subgroup to add
Please Help. I am a newbie in DB :(
Your query is probably failing as you have a table called group, which is a reserved word. You can use back tics to delimit the name to get away with this (as follows) but it would be a better idea to change the table name.
SELECT user.id, user.user_fname, `group`.group_id, `group`.group_title
FROM `user`
INNER JOIN user_group ON user_group.user_group_user_id = user.user_id
INNER JOIN `group` ON `group`.group_id = user_group.user_group_group_id
WHERE user_group.user_group_user_id = 1
AND user_group.group_parent_group_id = 0
EDIT updated for queries I think the OP requires.
First query will get a list of all the groups (ones that have no parent group id) that a user (in this case id 28) is a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
INNER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id
INNER JOIN y2m_group ON y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id = 0
This query will get a list of all the sub groups (ones where the parent group id is greater than 0) that a user (in this case id 28) is a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
INNER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id
INNER JOIN y2m_group ON y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id > 0
This query will get a list of all the sub groups (ones where the parent group id is greater than 0) that a user (in this case id 28) is NOT a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
CROSS JOIN y2m_group
LEFT OUTER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id AND y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id > 0
AND y2m_user_group.user_group_id IS NULL
Please excuse any typos as not tested (with your test data there are no sub groups).
I have this query, where I am trying to get max age of a retail store seller(There's multiple towns), and show multiple if there's multiple people with the same (max)age. I am using Microsoft Access 2010. Here is the query:
SELECT Linnad.Linn, Myyjad.Nimi, Max(Myyjad.Vanus) As Vanus
FROM Linnad INNER JOIN Myyjad ON Linnad.LinnID = Myyjad.LinnID
GROUP BY Linnad.Linn, Myyjad.Nimi
ORDER BY Linnad.Linn;
The problem is, it seems to ignore the MAX, and just shows all of the values, and I can't remove the group by Myyjad.Nimi, because it gives me an error that aggregate function not included for Myyjad.Nimi.
And the output should be:
Town - Name - Max(Age)
Also, Linn = Town, Nimi = Name and the Vanus = Age.
I think this may be what your looking for:
SELECT L.Linn, M.Nimi, M.Vanus
FROM Linnad As L,
(
SELECT M2.LinnID, M2.Nimi, M2.Vanus
FROM Myyjad As M2
WHERE M2.Vanus = (SELECT Max(Z.Vanus) FROM Myyjad As Z WHERE Z.LinnID = M2.LinnID)
) As M
WHERE M.LinnID = L.LinnID
This performs a sub-select to get a list of the Linn ID's with all Nimi's showing the maximum Vanus, then we link this sub-select back to the Linnad table via the LinnID.
I think you want:
SELECT Linnad.Linn, Myyjad.Nimi, Myyjad.Vanus
FROM Linnad INNER JOIN Myyjad ON Linnad.LinnID = Myyjad.LinnID
WHERE DateValue(Myyjad.Vanus)
= (SELECT Max(DateValue(Myyjad.Vanus)) FROM Myyjad)
ORDER BY Linnad.Linn
Top N per group:
SELECT Linnad.Linn, Myyjad.Nimi, Myyjad.Vanus
FROM FROM Linnad INNER JOIN Myyjad ON Linnad.LinnID = Myyjad.LinnID
WHERE Myyjad.ID In (
SELECT Top 1 m.ID
FROM Myyjad m
WHERE m.LinnID=Linnad.ID
ORDER BY m.Vanus Desc, m.ID)
Grouping by Linn (town) and Nimi (name) tells the db engine to give you one row for each combination of town and name, and show you the maximum Vanus (age) for each of those combinations. And logically, that's not what you want. You want the name of each person whose age is the same as the maximum age in that town.
First verify you can retrieve the max age for each LinnID.
SELECT
LinnID,
Max(Vanus) As MaxOfVanus
FROM
Myyjad
GROUP BY LinnID;
If that works, you can save it as "qryTownAge", then use it in another query where you join it (on LinnID) with Linnad. That will allow you to retrieve the matching Linn.
SELECT l.LinnID, l.Linn, q.MaxOfVanus
FROM
Linnad AS l
INNER JOIN qryTownAge AS q
ON l.LinnID = q.LinnID
ORDER BY l.Linn;
If that works, save it as qryTownAge2. Then try this query.
SELECT q.Linn, q.MaxOfVanus, m.Nimi
FROM
qryTownAge2 AS q
INNER JOIN Myyjad AS m
ON (
m.LinnID = q.LinnID
AND m.Vanus = q.MaxOfVanus
)
ORDER BY q.Linn;
If that all works, you could create a single query which does it all. However, doing it step by step should help us pinpoint errors.
To begin with I have 4 tables I am dealing with.
I have a classes table that is a 1->N relationship with a sections table which also has a 1->N relationship with a lessons table.
So to put it in perpective:
Classes
Sections
Lessons
The last table is an activityLog, when the student accesses a lesson this is recorded using the following:
ActivityLog Row -> actorID (user ID), classID, sectionID, lessonID
I want to pull out the last 5 unique lessons the student has visited. I tried using both DISTINCT and GROUP BY without success.
The same records are being returned each time, not the latest classes that they have visited.
Using GROUP BY
SELECT activityLog.actorID, activityLog.activityDate,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
GROUP BY activityLog.lessonID
ORDER BY activityLog.activityDate DESC
LIMIT 5
Using DISTINCT
SELECT DISTINCT activityLog.actorID,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
ORDER BY activityLog.activityDate DESC
LIMIT 5
I cannot figure out why the latest records are not being displayed.
Based on your change, how does this suit you?
SELECT activityLog.actorID, activityLog.activityDate,
strClasses.classID, strClasses.className,
strSections.sectionID, strSections.sectionName,
strLessons.lessonID, strLessons.lessonName
FROM activityLog
LEFT JOIN strClasses ON strClasses.classID = activityLog.classID
LEFT JOIN strSections ON strSections.sectionID = activityLog.sectionID
LEFT JOIN strLessons ON strLessons.lessonID = activityLog.lessonID
WHERE activityLog.activityTypeID = 6 AND activityLog.actorID = 3
AND activityLog.activityDate = (SELECT MAX(activityDate) FROM activityLog AS lookup WHERE lessonID = activityLog.lessonID)
ORDER BY activityLog.activityDate DESC
LIMIT 5
Based on your description, I'm not sure why you're using LEFT JOIN, but I've left it in just in case.
Try group by like below
GROUP BY activityLog.classID,activityLog.sectionID,activityLog.lessonID
I think it will work, or just sent me create scripts for these I will create that query
Well, there's got to be a datetime in the ActivityLog I hope... so Try this:
Select s.Name, c.ClassName
From Students s
left Join On Classes c
On c.ClassId In
(Select Distinct ClassId From Classes
Where (Select Count(Distinct ClassId) From Classes ic
Join ActivityLog l On l.UserId = s.UserId
And l.ClassId = c.ClassId
Where classId = c.ClassId
And activityDateTime > l.activityDateTime)
< 5)