Is Not Null works - Is Null does not - ms-access

I am making a grade entering system in Access, and I am running into some issues with a query.
One of my queries gets the class roster of a class. It takes in the students information, and then it also displays a grade next to their name. For the grade entry system, I only want to have students that do not have a grade already entered to appear.
To do this, in my Grade field, I have tried to set the Criteria to Is Null.
This is not working as it just does not display any student at all. The weird thing is, whenever I set it to Is Not Null, it shows me all of the students that have grades entered, and ignores all the students without a grade like I would expect.
So, since the students without grades are left out when the Criteria is set to Is Not Null, that leads me to believe that a student without a grade is null
So, I am very confused why setting the Criteria to Is Null, just leaves me with no results.
I am very new to Access, so if there is some important information I need to provide for adequate help, please let me know!

Very likely your join is a standard join. That means ONLY those with a parent record (student will ONLY show). If the child record that contains the grade does not exist, then they don't appear in your query. Fire up the query builder, and double click on the join line - change it to a left join (the option that says to include all students).
Now, when you run the query, records with a grade row will show, and those without will result in the grade column being null. Now, both of your conditions can and should work. It not the condition that is failing but your query not showing any students without a grade regardless of your condition that is the problem.

Related

joining two tables in my sql desn't return a result set

Hi I have run in to a problem when retrieving a particular data set using 3 tables in a MySql database.Tables are as follows
Student
SID | Name | Age | Telephone
Term
TID | Start | End
Payment
PID | TID | SID | Value
SID is primary key of Student table. TID is primary key of Term table. PID is primary key of Payment table. TID and SID in Payment table are foreign key references.
Student table contains data of students. Term table contain data of term start and end dates. Payment table contain data about student payment. Records in Payment table may either contain TID or not. When it is a registration payment there will be no TID. Otherwise it is a term fee and there will be TID. What I want is a list of students that hasn't paid this terms fees until today. Asuume this TID is in a variable. How can I obtain the list of students ? IT SEEMS SUPER EASY. BUT I COULDNT FIND AN ANSWER THIS WHOLE DAY 😣
You want a list of just those students who do not have a TID-populated record whose start and end dates are either side of today, in Payment
SELECT * FROM
student
LEFT OUTER JOIN
(select * from payment where TID is not null and NOW() BETWEEN start and end) this_term_payments
on student.id = this_term_payments.sid
WHERE
this_term_payments.ID is null
There are many ways to skin this cat. Here is one. We filter the payments table down to just a list of this term's payments (that's the inner query). And left join that to students. Left join means we get all students, matched with this_term_payments if the this_term_payments row exists, or NULL in every this_term_payments column if the term payment doesn't exist. The where clause then filters the whole results set down to "just those who don't have a term payment" by looking for those nulls that the left join creates
FWIW, your question attracted close votes because it didn't include example data/demonstrate the level of your effort we like to see on SQL questions. If you'd included sample data for all your tables and an example result set you wanted to see out, it means we can write an exact query that meets your requirements.
This is a bit of a double edged sword for me; we can deliver exactly what you ask for even if you later realise it's not what you want (asking in English is far more vague than giving an example result set) but at the same time we basically become some free outsourced homework contractor or similar, doing your work for you and removing learning opportunities along the way. Hopefully you'll take this query (it's likely it doesn't output everything you want, or outputs stuff you don't want) and craft what you want out of it now that the technique has been explained.. :)
For an SQL question that was relatively well received (by the time i'd finished editing it following up on the comments), and attracted some great answers take a look here:
Fill in gaps in data, using a value proportional to the gap distance to data from the surrounding rows?
That's more how you need to be asking SQL questions - say what you want, give example data, give scripts to help people create your same data so they can have a play with their idea without the boring bits of creating the data first. I picked on that one because I didn't even have any SQL attempts to show at the time; it was just a thought exercise. Having nothing working isn't necessarily a barrier to asking a good question
Try this:
select s.name, p.value from Student s, Term t, Payment p where t.TID = p.TID and s.SID=p.SID and p.TID is null;

SSRS report - add extra table and chart to show occurence of character string in one of the main report's columns

I have an SSRS report based on stored procedure dataset. The report shows employees and their performance rating and uses bunch of parameters to filter the data.
Now I would like to add a table below that would dynamicaly count and show occurence of given mark in the main report. The table data should update according to what is visible in the main report after filtering it.
I wanted also to add a chart that would visualize this.
It would be feasible to do if the extra table and chart could run from the same dataset as the main report. This however seems impossible as this dataset does not always contain all the possible marks. It can happen that some marks are missing (when filtered or missing at all), and I would like to show the mark with zero value (and zero value bar in the chart) instead of just skipping it.
So far I was able to produce the table by hardcoding the headers and using SUM(IIF...) expressions under each header
Here is the expression for the "C" column.
=Sum(IIf(Fields!current_performance_rating.Value = "C", 1, 0))
It shows correctly the number of "C" marks appearing in the main report.
Now I am stuck with creating a chart that would show this.
I am not able to hardcode expressions similar to the ones in the table
and can't make the chart run from the main dataset, because the categories
would be missing after filtering the report (and not showing zero).
I tried linking datasets with Lookup function, but that did not work.
Which way should I go now? What is the best practice in such case?
Thank you for any hints!
Thanks trubs.
I have right joined a view that contains
all the marks and that solves the issue
of missing categories.
The join is on something like
tb.current_performance_rating = vw.performance_rating_code
I can now add the value series that counts
the occurence of current_performance_rating
per category. This works all fine.
However there is another table joined
(on employee_id) that stores last year's rating.
This rating obviously may differ to the current one.
On the same chart I would like to add another
series that counts last year's rating per category.
The category is there already, joined to the current
rating.
So you can have row like:
curren rating | last year's rating | category
C | H | C
So I am stuck, because when SSRS groups per category
it counts last year's H rating and displays
i the C category, while it should display it in H.
Sorry I can't post any pictures, seems like I
need more reputation points.
Hope you can understand what I mean.
Regards!
You're likely better off changing your query to return results for marks where there are no values.
So instead of inner joining to your Performance Rating table, use a Right Join or Full Outer Join, so that all the data is always available.
eg: Instead of...
SELECT p.PersonId, PersonName, g.Grade
FROM Person p
INNER JOIN PersonGrades pg ON p.PersonId = pg.PersonId
INNER JOIN Grades g ON pg.GradeId = pg.GradeId
Use
SELECT p.PersonId, PersonName, g.Grade
FROM Grades g
LEFT JOIN PersonGrades pg ON pg.GradeId = g.GradeId
LEFT JOIN Person p ON p.PersonId = pg.PersonId
If that's not clear, post your query and we could help get the data in the right format.
The way to go was to simplify the dataset that the main report was based on.
Then I took the query from that dataset, used COUNT and GROUB BY to count number of occurence of each current year mark in the main report. Then I right joined (thx trubs!) with the view that contains all the possible marks (so that my extra table headers/chart categories would not disappear if they do not exist). As a result I got the number of occurence in current year per mark (table A).
Then I did almost exactly the same for the last year's rating, just used last year's mark. I got the number of occurence of last year's mark per mark (table B).
I inner joined table A and B on common column (the mark, which will always appear thanks to the RIGHT joins). This gave me a table (dataset eventualy) where I had:
mark | current year mark count | last year mark count.
Making a table and chart basing on this was really easy then.
There was some more fun of adding all the parameters from the main report to both the count queries, so that the counts would change when report is filtered. I also needed to make sure that count works not only when my filter criteria (in WHERE stetement) equal the parameter provided from the report, but also when they are NULLs (so I added OR column_i_filter_on IS NULL).
This works smoothly - the table content and chart changes when filtering changes (although runs slowly, as parameters are passed to two big dataset, one of which uses them twice).
Thanks for all the help!!
psh

Specific MYSQL view with null values

I'm having trouble creating a view for one of my MYSQL assignments. I understand how to create a view technically, as in, the commands to do so. (I have already done a few other different views for this assignment) My problem is with how to design this particular view... I don't know how to with the knowledge I have/The way I designed my tables.
So, I have 2 relevant tables(There are 2 others but I don't think they are needed for this problem): Attendance and Scholar. I need to create a view where all scholars are listed as well as the date where they were an invited speaker. However, if they were never an Invited Speaker, the date should have a null value shown. So I need to select First Name and LastName from Scholar and ADate from Attendance. Attendance has the column AttendanceType that can be either Invited Speaker or Chairman. Attendance also has the foreign key LName, relating to LastName, and ADate obviously. I can't conceptually think of have to do this, I thought that using a join, which I'm not that experienced with would be the right choice but it didn't work...
Here's what I attempted
CREATE VIEW InvitedScholars
AS SELECT FirstName,LastName,ADate
FROM Scholar LEFT JOIN Attendance ON AttendanceType='Invited Speaker'
WHERE Lname=LastName;
This only gave me Invited Speakers, not all Scholars... I don't know how to progress... any advice would be appreciated.
You need to do your left join on the Last Name (assuming this is your key on both tables). See the SQL below:
CREATE VIEW InvitedScholars
AS SELECT FirstName,LastName,ADate
FROM Scholar LEFT JOIN Attendance ON Scholar.LastName = Attendance.LName
AND Attendance.AttendanceType = 'Invited Speaker';
It appears you have your join and where clauses mixed up. You want to join the the two tables on the last name (which invites another issue if you have two speakers with the same last name) and filter by AttendanceType
FROM Scholar LEFT JOIN Attendance ON Lname=LastName
WHERE AttendanceType='Invited Speaker'

SQL Query to populate table based on PK of Main Table being joined

Here is my Database structure (basic relations):
I'm attempting to formulate a one-line query that will populate the clients_ID, Job_id, tech_id, & Part_id and return back all the work orders present. Nothing more nothing less.
Thus far I've struggled to generate this Query:
SELECT cli.client_name, tech.tech_name, job.Job_Name, w.wo_id, w.time_started, w.part_id, w.job_id, w.tech_id, w.clients_id, part.Part_name
FROM work_orders as w, technicians as tech, clients as cli, job_types as job, parts_list as part
LEFT JOIN technicians as techy ON tech_id = techy.tech_name
LEFT JOIN parts_list party ON part.part_id = party.Part_Name
LEFT JOIN job_types joby ON job_id = joby.Job_Name
LEFT JOIN clients cliy ON clients_id = cliy.client_name
Apparently, once all the joining happens it does not even populate the correct foreign key values according to their reference.
[some values came out as the actual foreign key id, not even
corresponding value.]
It just goes on about 20-30 times depending on largest row of a table that I have (one of the above).
I only have two work orders created, So ideally it should return just TWO Records, and columns, and fields with correct information. What could I be doing wrong? Haven't been with MySQL too long but am learning as much as I can.
Your join conditions are wrong. Join on tech_id = tech_id, not tech_id = tech_name. Looks like you do this for all your joins, so they all need to be fixed.
I really don't follow the text of your question, so I am basing my answer solely on your query.
Edit
Replying to your comment here. You said you want to "load up" the tech name column. I assume you mean you want tech name to be part of your result set.
The SELECT part of the query is what determines the columns that are in the result set. As long as the table where the column lives is referenced in the FROM/JOIN clauses, you can SELECT any column from that table.
Think of a JOIN statement as a way to "look up" a value in one table based on a value in another table. This is a very simplified definition, but it's a good way to start thinking about it. You want tech name in your result set, so you look it up in the Technicians table, which is where it lives. However, you want to look it up by a value that you have in the Work Orders table. The key (which is actually called a foreign key) that you have in the Work Orders table that relates it to the Technicians table is the tech_id. You use the tech_id to look up the related row in the Technicians table, and by doing so can include any column in that table in your result set.

MySQL sub-query AND 'NOT IN'

sorry if this has been answered before; I'm a little unsure how best to describe this problem never mind search for it. But here goes...
Basically I have a 'projects' table, which holds and 'id' and a 'title'. I also have a 'projects_history' table which holds information when (IF) the project is set to archived (a boolean value). It has a 'pid' key that references the project - there can be more than one record for each project as it is updated (in order to track who sets the value to what).
There's also a 'project_enquiries' table that holds information on enquiries that have been raised for the project, so there is a 'pid' key that references 'projects'. Similarly, there's a 'project_enquiry_history' table that records when (IF) the enquiry is set to closed (a boolean value). It has a 'eid' key that references the project_enquiry - there can be more than one record for each enquiry as it is updated (in order to track who sets the value to what).
My query aims to pull out the projects that haven't been archived (so either there is no record in 'project_history' or the most recent record for the project has 'archived' = 0), which have enquiries that are still open (so either there is no record in 'project_enquiry_history' or the most recent record for the enquiry has 'open' = 1).
I'm really struggling on where to start with the query.
The first thing is that if there is no record in project_history, then you will need to do a left join of your projects table on the project_history table using your project id to discover this. You will have entries in the results that are null in the columns for project_history where there is no corresponding entry. You can then chain that process, using the result to do another left join on the 'project_enquiry_history' to find the items that have no entries.
You can also use these results as normal, to do selects of the data.
It will look something like:
SELECT * from project p LEFT OUTER JOIN project_history ph ON P.ID=ph.pid
LEFT OUTER JOIN project_enquiry_history peh ON peh.ID=ph.pid
WHERE (archived is NULL OR archived=0)
AND (open is NULL OR open=1)
You may have to tweak this to find the most recent if you are using timestamps and such.