Access Select Query to show the same field with a different criteria - sql

I have a select query in Access 2010 which shows a 'Level Name' where the 'Period ID' is set to 1
How can i add another field to the query which also shows the Level Name where the Period ID is set to 2?
I would like them both to be next to each other in separate rows
For reference, my current query looks like:
SELECT
qryMaster.[First Name] & " " & qryMaster.[Last Name] AS ChildName,
qryMaster.LevelName
FROM
qryMaster
WHERE
(
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 1)
);
I have added a picture of how my current query looks like in a sub form. I would like a new Column next to september, but for a different period

A WHERE clause is always for all fields. So if you want two different WHERE clauses then you need two queries.
Otherwise try
AND (qryMaster.PeriodID In(1,2))

I know this thread was active five month ago, but I had the same problem, found this page with google. Asuming others will arrive here too, I'll post the two solutions that I found below.
SELECT t1.ChildName, t1.LevelName1, qryMaster.LevelName
FROM
((SELECT
qryMaster.[First Name] & " " & qryMaster.[Last Name] AS ChildName,
qryMaster.LevelName as LevelName1
FROM qryMaster
WHERE
(
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 1)
)) AS t1)
LEFT JOIN qryMaster
ON t1.ChildName = (qryMaster.[First Name] & " " & qryMaster.[Last Name])
WHERE (
(qryMaster.ClassID = [Forms]![frmViewRecords_subject]![cboClass])
AND
(qryMaster.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject])
AND
(qryMaster.PeriodID = 2)
)
As I do not have your data I couldn't test the code for your data, therefore I am not sure whether the "ON" clause works like this. In my case I have some customer ID there.
And the second one:
SELECT t1.[First Name] & " " & t1.[Last Name] AS ChildName, t1.LevelName AS LevelName1, t2.levelName AS LevelName2
FROM qryMaster t1
INNER JOIN qryMaster t2 ON t1.Childname=(t2.[First Name] & " " & t2.[Last Name])
WHERE (
(t1.ClassID = [Forms]![frmViewRecords_subject]![cboClass]) AND
(t1.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject]) AND
(t1.PeriodID = 1) AND
(t2.ClassID = [Forms]![frmViewRecords_subject]![cboClass]) AND
(t2.SubjectID = [Forms]![frmViewRecords_subject]![cboSubject]) AND
(t2.PeriodID = 2)
)

Related

MS Access Query SQL Union Select returns -1

I have a MS Access Query with a SQL Union Select that returns a -1 on my reports. I assume that the -1 is because the query is returning a null value, but I cannot figure out how to use an IFF() statement to stop showing the -1 in my report. This is the SQL Query:
SELECT [Employees].[Last Name] & ", " & [First Name] AS EmployeeName, Employees.[Active Employee], Employees.[Active Employee], Employees.[Active Employee]
FROM Employees
WHERE (((Employees.[Active Employee])=True))
ORDER BY [Employees].[Last Name] & ", " & [First Name];
UNION SELECT [Employees].[Last Name] & ", " & [First Name] AS EmployeeName, TypeOfAbsence.TypeOfAbsence, [Vacation Calendar].[Date Used], [Vacation Calendar].Time
FROM TypeOfAbsence INNER JOIN (Employees INNER JOIN [Vacation Calendar] ON Employees.ID = [Vacation Calendar].EmployeeID) ON TypeOfAbsence.ID = [Vacation Calendar].TypeID
WHERE ((([Vacation Calendar].[Date Used])<[Forms]![Week Ending Report Form]![End_Date] And ([Vacation Calendar].[Date Used])>[Forms]![Week Ending Report Form]![Start_Date]));
Consider using Null as field placeholder for UNION. This will eliminate the -1 values from the repeated [Active Employee] fields. Remove embedded semi-colon as that will cause UNION to fail. ORDER BY clause is likely useless because sorting should be managed by report and if report Sorting & Grouping is set, the query order will definitely be disregarded. First SELECT line defines field data types and names. Do not need to repeat alias field names in subsequent SELECT lines.
SELECT [Last Name] & ", " & [First Name] AS EmployeeName, Null AS TOA, Null AS DU, Null AS TU
FROM Employees
WHERE (((Employees.[Active Employee])=True))
UNION SELECT [Last Name] & ", " & [First Name], TypeOfAbsence, [Date Used], [Time]
FROM TypeOfAbsence
INNER JOIN (Employees INNER JOIN [Vacation Calendar]
ON Employees.ID = [Vacation Calendar].EmployeeID)
ON TypeOfAbsence.ID = [Vacation Calendar].TypeID
WHERE ((([Vacation Calendar].[Date Used])<[Forms]![Week Ending Report Form]![End_Date] And ([Vacation Calendar].[Date Used])>[Forms]![Week Ending Report Form]![Start_Date]));
Also consider this filter criteria:
WHERE [Date Used] BETWEEN [Forms]![Week Ending Report Form]![Start_Date] AND [Forms]![Week Ending Report Form]![End_Date]

PostgreSQL joining multiple tables

Hi guys I am trying to join tables here, I want to add table called Table2 so that students from that table are displayed too. The thing which is confusing is I already have joins in this query, so how should add another join so that students from that Table2 are displayed as well, without breaking the existing code . Also, there is no way I can check output
The ID varables are stsidno in stTable 1, sidno in Table2, scsidno in table schedprd
Here's the code:
String selS = "select distinct stdistrict,stschool,stsidno,"
+ " sname as name,stgrade,"
+ "S.recnum as recnum, S.stldate as stldate,scsec,sctea,sccor,scgrade,scclsprd,scgrdprd,"
+ "case when P.scchangestartdate is null then C.clstart else "
+ "P.scchangestartdate end as scchangestartdate, "
+ "case when S.stedate is null or S.stedate<C.clstart "
+ "then C.clstart else S.stedate end as stedate "
+ "from stTable1 as S join schedprd as P on "
+ "(scyear=styear and scdistrict=stdistrict and scschool=stschool "
+ "and stsidno=scsidno and (scsec is not null and scsec<>'')) "
+ "left outer join calendar as C on (C.clyear=S.styear and "
+ "C.cldistrict=S.stdistrict and C.clschool=S.stschool and C.cltype='10') "
+ "where styear=? and stdistrict=? ";
You could UNION Table1 and Table2 together in a Common Table Expression (CTE) and then reference the CTE instead of Table1 in your query, like below:
WITH CTE
AS
(
SELECT *
FROM Table1
UNION
SELECT *
FROM Table2
)
select distinct
stdistrict,
stschool,
stsidno,
sname as name,
stgrade,
S.recnum as recnum,
S.stldate as stldate,
scsec,
sctea,
sccor,
scgrade,
scclsprd,
scgrdprd,
case when P.scchangestartdate is null then C.clstart else P.scchangestartdate end as scchangestartdate,
case when S.stedate is null or S.stedate<C.clstart then C.clstart else S.stedate end as stedate
from CTE as S
join schedprd as P on (scyear=styear and scdistrict=stdistrict and scschool=stschool and stsidno=scsidno and (scsec is not null and scsec<>''))
left outer join calendar as C on (C.clyear=S.styear and C.cldistrict=S.stdistrict and C.clschool=S.stschool and C.cltype='10')
where styear=? and stdistrict=?;

SQL Join fields from 3 tables

I have 3 tables of data that I need to join to make one table and show the following fields:
u.master_id, p.surname, p.forename1, c.number, u.status
Here are the table details:
Table 1 (person p)
Field name = entity_id (number)
Field name = surname(text)
Field name = forename1(text)
Field name = auditflag
Table 2 (users u)
Field name = master_id (number)
Field name = email (number)
Field name = status (text)
Field name = auditflag
Table 3 (contact c)
Field name = master_id (number)
Field name = entity_id (number)
Field name = number (text = holds the actual email address)
Field name = auditflag
The master_id field from table 2 and 3 links to the person entity_id ( master_id=p.entity_id )
The email field from table 2 links to the entity_id in table 3 ( u.email=c.entity_id ) to get the number
The auditflag is used to mark each as an active record i.e. ( p.auditflag=1 AND u.auditflag=1 AND c.auditflag=1 )
I'm using Excel 2010 VBA - joining to a PostGreSQL database to get the data.
Below is the code I am using to join the 2 tables which works fine, but my problem is that "email" only shows a number because the actual address is in a 3rd table (Contact) under the field called "number".
I don't know how to include the 3rd table to show the field c.number in my query.
Const sqlconnection = "Provider=oledb;"
Dim conn As New Connection
conn.ConnectionString = sqlconnection
conn.Open
Dim rs As Recordset
Dim prs As String
prs = "SELECT u.master_id, p.surname, p.forename1, u.email, u.status " _
& "FROM users u INNER JOIN person p ON u.master_id=p.entity_id " _
& "WHERE u.auditflag=1 AND p.auditflag=1 " _
& "ORDER BY u.master_id "
Set rs = conn.Execute(prs)
With ActiveSheet.QueryTables.Add(Connection:=rs, Destination:=Range("A1"))
.Refresh
End With
You have all the pieces; all you need to do is add the third table to the query and select the columns you want.
Dim prs As String
prs = "SELECT u.master_id, p.surname, p.forename1, c.number as email, u.status " _
& "FROM users u INNER JOIN person p ON u.master_id=p.entity_id " _
& " INNER JOIN contact c ON c.master_id=p.entity_id and u.email=c.entity_id " _
& "WHERE u.auditflag=1 AND p.auditflag=1 AND c.auditflag=1 " _
& "ORDER BY u.master_id "
As written, this query will only get users that have active (auditflag=1) person rows and active contact rows. Changing to left joins and moving the auditflag checks to the join condition would allow returning users without active rows in all three tables.
As a side note, I find the column names in your tables are actively working against easily understanding what they mean; if you can, I'd suggest re-thinking the names you're using.

Sql Joins on multiple table returning product of two columns

I am trying to generate a report on a sql server database in asp.net and I am getting the results of some columns as a product of two columns. Here is the code
comm.CommandText = "SELECT Count(Courses.CourseID) AS CourseCount, Count(Students.StudentID) AS StudentCount, Schools.Name, Schools.StartDate, Schools.SchoolFees " +
"FROM Schools" +
"LEFT JOIN Courses ON (Schools.SchoolID = Courses.SchoolID)" +
"LEFT JOIN Students ON (Schools.SchoolID = Students.SchoolID) " +
"WHERE Schools.Active = 1 " +
"GROUP BY Schools.Name, Schools.StartDate, Schools.SchoolFees";
When I run the code, the result displays, but the columns for "CourseCount" and "StudentCount" display a value that is a product of each individual column. "CourseCount" is normally 288 and "StudentCount" is 38 but when I run the code, both "CourseCount" and "StudentCount" display 10944 which is 38 x 288.
Anyway I can make them display the correct values?
Changing your code from using a count of all rows, to a count of distinct values only, should return the results you expect
comm.CommandText = "SELECT Count(DISTINCT Courses.CourseID) AS CourseCount, Count(DISTINCT Students.StudentID) AS StudentCount, Schools.Name, Schools.StartDate, Schools.SchoolFees " +
"FROM Schools" +
"LEFT JOIN Courses ON (Schools.SchoolID = Courses.SchoolID)" +
"LEFT JOIN Students ON (Schools.SchoolID = Students.SchoolID) " +
"WHERE Schools.Active = 1 " +
"GROUP BY Schools.Name, Schools.StartDate, Schools.SchoolFees";
The results being returned are technically correct, if all schools have courses, and all courses have students
As stated above, it is how you are using the COUNT (), You are asking it to count all, which is why it returns so many. Use count on just the two values you want counted.
This might perform better than the DISTINCT Count method..
comm.CommandText =
"SELECT cc.CourseCount, sc.StudentCount, Schools.Name, Schools.StartDate, Schools.SchoolFees " +
"FROM Schools" +
"OUTER APPLY (SELECT Count(Students.StudentID) StudentCount FROM Students WHERE Students.SchoolID = Schools.SchoolID) sc " +
"OUTER APPLY (SELECT Count(Courses.CourseID) CourseCount FROM Courses WHERE Courses.SchoolID = Schools.SchoolID) cc " +
"WHERE Schools.Active = 1 ";

Update record if matching values in same table

I have a MS Access database with a list of transactions. I am trying to update a "Match" field on both records where they have some of the same values in fields (Document Number, Voucher Number, Subhead) but opposite amounts. It also needs to avoid duplicates.
Document Number Amount ABS Match
N6809561990112 438.48 438.48
N6809561990112 438.48 438.48
N6809561990112 -438.48 438.48
What I the end result after the SQL should look like
Document Number Amount ABS Match
N6809561990112 438.48 438.48 Y
N6809561990112 438.48 438.48
N6809561990112 -438.48 438.48 Y
The table name is "tblUnmatched"
I tried the following but it updated every record in the table to "Y"
strSql = "Update tblUnmatched SET match = 'Y' WHERE EXISTS(select * " & _
"from tblUnmatched t1 " & _
"inner join tblUnmatched t2 on " & _
"t1.[DOCUMENT NUMBER] = t2.[DOCUMENT NUMBER]" & _
"where t1.ABS = t2.ABS AND t1.AMOUNT <> t2.AMOUNT AND t1.SUBH = t2.SUBH)"
DoCmd.RunSQL strSql
I also tried this but it couldn't handle the duplicate problem.
strSql = "Update tblUnmatched SET match = 'Y' WHERE [DOCUMENT NUMBER] IN(select t1.[DOCUMENT NUMBER] " & _
"from tblUnmatched t1 " & _
"inner join tblUnmatched t2 on " & _
"t1.[DOCUMENT NUMBER] = t2.[DOCUMENT NUMBER]" & _
"where t1.ABS = t2.ABS AND t1.AMOUNT <> t2.AMOUNT AND t1.SUBH = t2.SUBH)"
DoCmd.RunSQL strSql
Your task is impractical in Access SQL without a primary key field. Although there is no such key in the data source you import, that does not prohibit you from adding one in Access.
Add an autonumber primary key, id, to tblUnmatched. Then for each new batch of incoming data:
import into a scratch table, tblScratch
DELETE FROM tblUnmatched
append the rows from tblScratch into tblUnmatched
(The process could be cleaner if you can use SELECT FROM <your data source> to append directly to tblUnmatched, instead of first importing to tblScratch.)
Save the following SELECT statement as qryFindMatches:
SELECT
sub.[Document Number],
sub.Amount,
sub.MinOfid,
DCount(
"*",
"tblUnmatched",
"[Document Number]='" & [Document Number]
& "' AND Amount = -1 * " & [Amount]
) AS match_count
FROM
(
SELECT [Document Number], Amount, Min(id) AS MinOfid
FROM tblUnmatched
GROUP BY [Document Number], Amount
) AS sub;
Then the UPDATE you want can be fairly easy to create. Beware the performance may not be blazing fast; hopefully you can accommodate it once a month.
UPDATE tblUnmatched
SET [Match] = True
WHERE id In
(
SELECT MinOfId
FROM qryFindMatches
WHERE match_count > 0
);
I added an additional row to your sample data and tested with Access 2007. I think this is what you want ...
id Document Number Amount Match
1 N6809561990112 $438.48 True
2 N6809561990112 $438.48 False
3 N6809561990112 ($438.48) True
4 N6809561990112 $5.00 False