SQL - IIF clause outside of select statement? - mysql

I'm working in MS Access 2010 doing a series of UNIONs inside of a SELECT statement. After all of these UNIONs are complete, I need to add a couple of new columns using IIF statements (i.e., based on the value of a ch column). However, I can't seem to find out how or where to properly squeeze in this syntax so that the IIFs check against an entire column in the final 'unioned' table. Simply put, after the below syntax (which is trimmed and simplified for this question) runs, I want to then append a new variable column (e.g., 'asterisk') in this final table based on whether an existing column cell (e.g., 'grades') contains an asterisk. Help and patience is greatly appreciated -- I am just becoming familiar with the syntax principles of SQL.
SELECT * FROM(
SELECT class, teacher, student
grades2010 AS grades
WHERE NOT(grades2010 IS NULL OR grades2010="")
UNION
SELECT class, teacher, student
grades2011 AS grades
WHERE NOT(grades2011 IS NULL OR grades2011="")
UNION
SELECT class, teacher, student
grades2012 AS grades
WHERE NOT(grades2012 IS NULL OR grades2010="")
)
Here's an example of the type of IIF I'd want to run -- see if 'grades' contains an asterisk and create an indicator:
IIF(InStr([grades],"*")>0,"YES","NO") AS asterisk

So... You are on the right track. It would look something like:
SELECT
IIF(InStr([grades],"*")>0,"YES","NO") AS asterisk,
class,
teacher,
student
FROM(
SELECT class, teacher, student
grades2010 AS grades
WHERE NOT(grades2010 IS NULL OR grades2010="")
UNION
SELECT class, teacher, student
grades2011 AS grades
WHERE NOT(grades2011 IS NULL OR grades2011="")
UNION
SELECT class, teacher, student
grades2012 AS grades
WHERE NOT(grades2012 IS NULL OR grades2010="")
) as mysubquery
But... grades is not a column in your UNION subquery, so this won't work. You'll need to make sure that grade column is added to each SELECT statement in your subquery to do anything with it in your main SELECT.
Also worth mentioning is that your schema isn't the best. Instead of having a table for each year, you should really just have a single table with year as a column. This will get you out of having to do these nasty, and often times slow Union queries. You could fix that up pretty quick by making a table and using that UNION query there to do an INSERT from each of your year based tables.

Related

What is the new table name after joining two tables in sql?

I read the previous posts but I couldn't find one that answered my question.
What would be the name of the table that is made by joining two tables? The reason why I need the name is because I would like to change the column name of the new table using the ALTER TABLE (Table name) RENAME COLUMN (A) to (B). If there is no specified name, how can I name the new table?
ex
SELECT
client_id
,last_name
FROM INDIVIDUAL_CLIENT
UNION ALL
SELECT
client_id
,bus_name
FROM BUSINESS_CLIENT;
I would like to rename the column to last_name/bus_name instead of last_name
In the case of a query what temporal table a query might create internally is not relevant, because you a making a query and getting data back, it doesn't stay in the database as a table, there is no such table. Unless we make it.
if You want TSQL to change a column name it would affect your union query and I base my answer on Your
'I would like to rename the column to last_name/bus_name instead of last_name'
And think this is what you're looking for. Please correct me if it isn't.
In generic SQL what we're doing is putting a label on both projections that are to be displayed in the same column
SELECT
client_id
,last_name [last_name/ bus_name]
FROM INDIVIDUAL_CLIENT
UNION ALL
SELECT
client_id
,bus_name [last_name/ bus_name]
FROM BUSINESS_CLIENT;
update, in MySQL notation uses AS and quotes instead of angle brackets
SELECT
client_id
,last_name as "last_name/ bus_name"
FROM INDIVIDUAL_CLIENT
UNION ALL
SELECT
client_id
,bus_name as "last_name/ bus_name"
FROM BUSINESS_CLIENT;

Trying to understand the difference between IN and EXISTS

I'm currently taking a course and during one of the tests, I came across this question.
The math_students and english_students tables have the following columns:
student_id, grade, first_name, last_name
Using a subquery, find out what grade levels are represented in both the math and english classes.
The query I used was this.
select distinct grade
from math_students
where grade in (
select grade
from english_students
);
However, it was graded as incorrect and the correct answer was given as
SELECT grade
FROM math_students
WHERE EXISTS (
SELECT grade
FROM english_students
);
I would really appreciate it if someone could help me understand the difference in the two queries because the output was the same in both cases. Also, why doesn't the query contain distinct?
The version with EXISTS is incorrect. Period. It is answering the "question":
Return all grades for math students if there is at least one English student.
Not very useful. The correct EXISTS would be:
SELECT DISTINCT grade
FROM math_students ms
WHERE EXISTS (
SELECT 1
FROM english_students es
WHERE ms.grade = es.grade
);
If your database supports it, I would expect you to also be learning:
select grade
from math_students
intersect
select grade
from english_students;
The "In" clause checks if the value is a member of a provided list, this can either be a hard coded list or a query result.
In your example if the table english_students was defined as
id name grade
-- ---- -----
1 Joe 6
2 Bill 8
3 Sue 7
The query:
select distinct grade
from math_students
where grade in (
select grade
from english_students
);
Will evaluate to:
select distinct grade
from math_students
where grade in (
"6","8","7"
);
Order of operations executes the query in parens first, then executes the outer query
so since you are saying
select grade
from english_students
It would return "6","8","7" then execute the outer query.
Your second query:
SELECT grade
FROM math_students
WHERE EXISTS (
SELECT grade
FROM english_students
);
"Exists" checks for just that Existence of data (or objects), so you are saying select all data in math_students if data exists in english_students as Gordon pointed out.
To answer the question in the title. The big distinction between "In" and "Exists" is: "In" is evaluates to "Give me anything that matches one of these values" where "Exists" evaluates to "Give me anything that exists"
The reason the second does not require a distinct is probably data related.
As Gordon pointed out "intersect" will append multiple results to the same result set and return the distinct records.

Selecting specific records to run query on

I am trying to select a small number of records in a somewhat large database and run some queries on them.
I am incredibly new to programming so I am pretty well lost.
What I need to do is select all records where the Registraton# column equals a certain number, and then run the query on just those results.
I can put up what the db looks like and a more detailed explanation if needed, although I think it may be something simple that I am just missing.
Filtering records in a database is done with the WHERE clause.
Example, if you wanted to get all records from a Persons table, where the FirstName = 'David"
SELECT
FirstName,
LastName,
MiddleInitial,
BirthDate,
NumberOfChildren
FROM
Persons
WHERE
FirstName = 'David'
Your question indicates you've figured this much out, but are just missinbg the next piece.
If you need to query within the results of the above result set to only include people with more than two children, you'd just add to your WHERE clause using the AND keyword.
SELECT
FirstName,
LastName,
MiddleInitial,
BirthDate,
NumberOfChildren
FROM
Persons
WHERE
FirstName = 'David'
AND
NumberOfChildren > 3
Now, there ARE some situations where you really need to use a subquery. For example:
Assuming that each person has a PersonId and each person has a FatherId that corresponds to another person's PersonId...
PersonId FirstName LastName FatherId...
1 David Stratton 0
2 Matthew Stratton 1
Select FirstName,
LastName
FROM
Person
WHERE
FatherId IN (Select PersonId
From Person
WHERE FirstName = 'David')
Would return all of the children with a Father named David. (Using the sample data, Matthew would be returned.)
http://www.w3schools.com/sql/sql_where.asp
Would this be any use to you?
SELECT * from table_name WHERE Regestration# = number
I do not know what you have done up to now, but I imagine that you have a SQL query somewhere like
SELECT col1, col2, col3
FROM table
Append a where clause
SELECT col1, col2, col3
FROM table
WHERE "Registraton#" = number
See SO question SQL standard to escape column names?.
Try this:
SELECT *
FROM tableName
WHERE RegistrationNo = 'valueHere'
I am not certain about my solution. I would propose You to use view. You create view based on needed records. Then make needed queries and then you can delete the view.
View description: A view contains rows and columns, just like a real table. The fields in a view are fields from one or more real tables in the database.
Example:
CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
For more information: http://www.w3schools.com/sql/sql_view.asp

Access 2010 DLookUp

Working with MS Access for the first time and coming across a few problems if someone could please point me in the right direction.
So I'm doing a mock database (so it looks silly) just to learn the ins and outs and need some help with DLookUp at the moment.
My database has two tables, with the following fields:
C_ID the PK in Courses and FK in Student
tblCourse: C_ID, Title, Subject
tblStudent: S_ID, C_ID, Name, EnrollDATE
As I said this is just for testing/learning. So what I want is to have a filter that gives me a list of C_ID's based on which EnrollDates are NULL.
so filter is:
Expr1: DLookUp("[tblStudent]![C_ID]","tblStudent","isNull([tblStudent]![EnrollDATE])")
I have also tried with the criteria being
[tblStudent]![EnrollDATE] = Null
Currently I get just blank fields returned. Any help is greatly appreciated, and please ask me to elaborate if my explanation is off.
Thank You!
The correct syntax looks like this:
DLookup("C_ID", "tblStudent", "EnrollDate is null")
You don't need to include the table name when you specify the columns
In Access, you check for Null by using xxx is null or xxx is not null
Note that DLookup only returns one value (if the criteria matches more than one row, the value is taken from any row), so you can't use it to get a list of C_IDs back.
EDIT:
What you actually want to do is select data from one table, and filter that based on data from the other table, correct?
Like, selecting all courses where at least one student has an empty EnrollDATE?
If yes, you don't need the DLookup at all, there are two different ways how to do that:
1) With a sub-select:
select *
from tblCourse
where C_ID in
(
select C_ID
from tblStudents
where EnrollDATE is null
)
2) By joining the tables:
select tblCourse.*
from tblCourse
inner join tblStudent on tblCourse.C_ID = tblStudent.C_ID
where tblStudent.EnrollDATE is null
This is SQL, so you need to switch to SQL View in your query in Access.

How do I make the rows of a lookup table into the columns of a query?

I have three tables: students, interests, and interest_lookup.
Students has the cols student_id and name.
Interests has the cols interest_id and interest_name.
Interest_lookup has the cols student_id and interest_id.
To find out what interests a student has I do
select interests.interest_name from `students`
inner join `interest_lookup`
on interest_lookup.student_id = students.student_id
inner join `interests`
on interests.interest_id = interest_lookup.interest_id
What I want to do is get a result set like
student_id | students.name | interest_a | interest_b | ...
where the column name 'interest_a' is a value in interests.name and
the interest_ columns are 0 or 1 such that the value is 1 when
there is a record in interest_lookup for the given
student_id and interest_id and 0 when there is not.
Each entry in the interests table must appear as a column name.
I can do this with subselects (which is super slow) or by making a bunch of joins, but both of these really require that I first select all the records from interests and write out a dynamic query.
You're doing an operation called a pivot. #Slider345 linked to (prior to editing his answer) another SO post about doing it in Microsoft SQL Server. Microsoft has its own special syntax to do this, but MySQL does not.
You can do something like this:
SELECT s.student_id, s.name,
SUM(i.name = 'a') AS interest_a,
SUM(i.name = 'b') AS interest_b,
SUM(i.name = 'c') AS interest_c
FROM students s
INNER JOIN interest_lookup l USING (student_id)
INNER JOIN interests i USING (interest_id)
GROUP BY s.student_id;
What you cannot do, in MySQL or Microsoft or anything else, is automatically populate columns so that the presence of data expands the number of columns.
Columns of an SQL query must be fixed and hard-coded at the time you prepare the query.
If you don't know the list of interests at the time you code the query, or you need it to adapt to changing lists of interest, you'll have to fetch the interests as rows and post-process these rows in your application.
What your trying to do sounds like a pivot.
Most solutions seem to revolve around one of the following approaches:
Creating a dynamic query, as in Is there a way to pivot rows to columns in MySQL without using CASE?
Selecting all the attribute columns, as in How to pivot a MySQL entity-attribute-value schema
Or, identifying the columns and using either a CASE statement or a user defined function as in pivot in mysql queries
I don't think this is possible. Actually I think this is just a matter of data representatioin. I would try to use a component to display the data that would allow me to pivot the data (for instance, the same way you do on excel, open office's calc, etc).
To take it one step further, you should think again why you need this and probably try to solve it in the application not in the database.
I know this doesn't help much but it's the best I can think of :(