SQL adding multiple clauses on the JOIN - sql

I've got the query below which almost works. It's returning the correct number of records and the way I want the records formatted. The thing is I need to return data based on a family so I want the returned data to include the father and mother on a single row of data if they belong to that family or two rows if they have a different familyID.
I've got the following query, the only issue I have is it is returning father and mother on the same line even if they are separated. I've looked at the code and I know why its happening, due to the way I have joined the father and mother to relations table. To handle separations I have a table called family and my relation table contains the familyID key. I need to somehow incorporate to check whether mothers familyID = father familyID somewhere where I make my join on the relation table for both parents, but I'm a little stuck.
I started this query with INNER JOINS, but changed to LEFT JOINS as some of the pupil data didn't have a both parents, so the data returned incorrect number of rows - however seems to work OK with LEFT JOINS.
SELECT p.pk_PupilID, p.Title, p.Forename, p.Surname,
father.pk_PersonID, father.Title, father.Forename, father.Surname,
mother.pk_PersonID, mother.Title, mother.Forename, mother.Surname,
ff.Salutation
FROM Pupil AS p
LEFT JOIN RELATION AS father_r
ON p.pk_PupilID = father_r.fk_PersonID
AND father_r.Relationship IN ('Father','Father')
LEFT JOIN PERSON AS father
ON father_r.fk_RelatedPersonID = father.pk_PersonID
LEFT JOIN RELATION AS mother_r
ON p.pk_PupilID = mother_r.fk_PersonID
AND mother_r.Relationship IN ('Mother','Stepmother')
LEFT JOIN PERSON AS mother
ON mother_r.fk_RelatedPersonID = mother.pk_PersonID
LEFT JOIN Family AS ff
father_r.fk_FamilyID = ff.pk_FamilyID
OR
mother_r.fk_FamilyID = ff.pk_FamilyID

This post is under the assumption the database is MySQL and I can use #variables within the query
I would start with a query of all possible "Parent" types of father, mother or other and sort their respective priority to a position type for all families and group by the person ID in the relationship. Since you appear to be pulling for ALL pupils, we can pre-gather all possible parents per person. Using SQLVariables, we can help pre-group possible entities regardless of parental type relation.
SELECT
Family.fk_PersonID,
Family.fk_FamilyID,
#nextParent := if( #lastPerson = Family.fk_PersonID
AND #lastFamily = Family.fk_FamilyID, #nextParent, 1 ) as parentSeq,
#lastPerson := Family.fk_PersonID as lastPersonSeq,
#lastFamily := Family.fk_FamilyID as lastFamilySeq,
if( #nextParent == 1, Family.pk_PersonID, " " ) as Parent1PersonID,
if( #nextParent == 1, Family.Relationship, " " ) as Parent1Type,
if( #nextParent == 1, Family.Title, " " ) as Parent1Title,
if( #nextParent == 1, Family.Forename, " " ) as Parent1Forename,
if( #nextParent == 1, Family.Surname, " " ) as Parent1Surname,
if( #nextParent == 2, Family.pk_PersonID, " " ) as Parent2PersonID,
if( #nextParent == 2, Family.Relationship, " " ) as Parent2Type,
if( #nextParent == 2, Family.Title, " " ) as Parent2Title,
if( #nextParent == 2, Family.Forename, " " ) as Parent2Forename,
if( #nextParent == 2, Family.Surname, " " ) as Parent2Surname
from
( select
#lastPerson := 0,
#lastFamily := 0,
#nextParent := 0 ) sqlvars,
( SELECT
fr.fk_PersonID,
fk_FamilyID,
fr.fk_RelatedPersonID,
fr.relationship,
whatParent.pk_PersonID,
whatParent.Title,
whatParent.Forename,
whatParent.Surname,
CASE when fr.relationship in ('Father', 'Stepfather' ) then 1
when fr.relationship in ('Mother', 'Stepmother' ) then 2 end as reltype
from
Relation fr
JOIN PERSON AS whatParent
ON fr.fk_RelatedPersonID = whatParent.pk_PersonID
where
fr.relationship in ('Father', 'Stepfather', 'Mother', 'Stepmother' )
order by
fr.fk_PersonID,
fr.fk_FamilyID,
CASE when fr.relationship in ('Father', 'Stepfather' ) then 1
when fr.relationship in ('Mother', 'Stepmother' ) then 2 end ) as Family
group by
Family.fk_PersonID,
Family.fk_FamilyID
The inner order by clause will force any Father / Stepfather in the first position and mother / step mother in second. This now qualifies for all possible conditions of things like f=father, sf=step, m=mother, sm=step (f/m, f/sm, sf/m, f/f, m/m, m/sm, etc). If you want other parental considerations, add them to the inner where clause and relation ship type sequence for priority positioning.
Due to the group by of per person, it SHOULD be able to ignore issues about not having aggregate columns in the group by clause... of which, you could always wrap each of the OTHER non aggreates to MAX() such as
MAX( #nextParent := if( #lastPerson = Family.fk_PersonID, #nextParent, 1 )) as parentSeq,
MAX( #lastPerson := Family.fk_PersonID ) as lastPersonSeq,
MAX( if( #nextParent == 1, Family.Relationship, " " )) as Parent1Type,
MAX( if( #nextParent == 1, Family.Title, " " )) as Parent1Title,
MAX( if( #nextParent == 1, Family.Forename, " " )) as Parent1Forename,
MAX( if( #nextParent == 1, Family.Surname, " " )) as Parent1Surname,
MAX( if( #nextParent == 2, Family.Relationship, " " )) as Parent2Type,
MAX( if( #nextParent == 2, Family.Title, " " )) as Parent2Title,
MAX( if( #nextParent == 2, Family.Forename, " " )) as Parent2Forename,
MAX( if( #nextParent == 2, Family.Surname, " " )) as Parent2Surname
So now, all the parental relationships are all rolled up to one row based on the fk_PersonID AND FAMILY. Now, just join that to the pupil's table, something like..
SELECT
p.pk_PupilID,
parents.fk_FamilyID,
p.Title,
p.Forename,
p.Surname,
Parents.Parent1PersonID,
Parents.Parent1Type,
Parents.Parent1Title,
Parents.Parent1Forename,
Parents.Parent1Surname,
Parents.Parent2PersonID,
Parents.Parent2Type,
Parents.Parent2Title,
Parents.Parent2Forename,
Parents.Parent2Surname,
ff.Salutation
FROM
Pupil AS p
LEFT JOIN ( entire query from above ) as Parents
ON p.pk_PupilID = Parents.fk_PersonID
LEFT JOIN Family AS ff
ON parents.fk_FamilyID = ff.pk_FamilyID
ORDER BY
p.pk_PupilID,
parents.fk_FamilyID

Related

Create subquery using peewee, using `.select` on the subquery results

I have a rather complex peewee query that looks like that:
SolutionAlias = Solution.alias()
fields = [
SolutionAlias.id.alias('solution_id'),
SolutionAlias.solver.id.alias('solver_id'),
SolutionAlias.exercise.id.alias('exercise_id'),
]
query = (
User
.select(*fields)
.join(Exercise, JOIN.CROSS)
.join(Course, JOIN.LEFT_OUTER, on=(Exercise.course == Course.id))
.join(SolutionAlias, JOIN.LEFT_OUTER, on=(
(SolutionAlias.exercise == Exercise.id)
& (SolutionAlias.solver == User.id)
))
.where(
(Exercise.id << self.get_exercise_ids()),
(User.id << self.get_user_ids()),
)
.group_by(Exercise.id, User.id, SolutionAlias.id)
.having(
(SolutionAlias.id == fn.MAX(SolutionAlias.id))
| (SolutionAlias.id.is_null(True))
)
.alias('solutions_subquery')
)
full_query_fields = [
query.c.solver_id,
query.c.exercise_id,
Solution.id.alias('solution_id'),
SolutionAssessment.icon.alias('assessment_icon'),
]
solutions = (
Solution
.select(*full_query_fields)
.join(query, JOIN.RIGHT_OUTER, on=(
Solution.id == query.c.solution_id
))
.join(SolutionAssessment, JOIN.LEFT_OUTER, on=(
(Solution.assessment == SolutionAssessment.id)
))
)
This one actually works, generating the following SQL query:
SELECT
"solutions_subquery"."solver_id",
"solutions_subquery"."exercise_id",
"t1"."id" AS "solution_id",
"t2"."icon" AS "assessment_icon"
FROM
"solution" AS "t1"
RIGHT OUTER JOIN (
SELECT
"t3"."id" AS "solution_id",
"t4"."id" AS "solver_id",
"t5"."id" AS "exercise_id"
FROM
"user" AS "t4" CROSS
JOIN "exercise" AS "t5"
LEFT OUTER JOIN "course" AS "t6" ON ("t5"."course_id" = "t6"."id")
LEFT OUTER JOIN "solution" AS "t3" ON (
("t3"."exercise_id" = "t5"."id")
AND ("t3"."solver_id" = "t4"."id")
)
WHERE
(
(
"t5"."id" IN (155, 156, 157)
)
AND (
"t4"."id" IN (1, 24, 25, 26, 27, 28)
)
)
GROUP BY
"t5"."id",
"t4"."id",
"t3"."id"
HAVING
(
(
"t3"."id" = MAX("t3"."id")
)
OR ("t3"."id" IS NULL)
)
) AS "solutions_subquery" ON (
"t1"."id" = "solutions_subquery"."solution_id"
)
LEFT OUTER JOIN "solutionassessment" AS "t2" ON ("t1"."assessment_id" = "t2"."id")
But I don't really want to use RIGHT_JOIN as it isn't supported by SQLite.
When trying to query using the subquery query and JOINing the Solution table into the subquery's result, I get an error from peewee.
The new query:
solutions = (
query
.select(*full_query_fields)
.join(Solution, JOIN.LEFT_OUTER, on=(
Solution.id == query.c.solution_id
))
.join(SolutionAssessment, JOIN.LEFT_OUTER, on=(
(Solution.assessment == SolutionAssessment.id)
))
)
The generated query:
SELECT
"solutions_subquery"."solver_id",
"solutions_subquery"."exercise_id",
"t1"."id" AS "solution_id",
"t1"."checker_id",
"t1"."state",
"t1"."submission_timestamp",
"t2"."name" AS "assessment",
"t2"."icon" AS "assessment_icon"
FROM
"user" AS "t3" CROSS
JOIN "exercise" AS "t4"
LEFT OUTER JOIN "course" AS "t5" ON ("t4"."course_id" = "t5"."id")
LEFT OUTER JOIN "solution" AS "t6" ON (
("t6"."exercise_id" = "t4"."id")
AND ("t6"."solver_id" = "t3"."id")
)
LEFT OUTER JOIN "solution" AS "t1" ON (
"t1"."id" = "solutions_subquery"."solution_id"
)
LEFT OUTER JOIN "solutionassessment" AS "t2" ON ("t1"."assessment_id" = "t2"."id")
WHERE
(
(
"t4"."id" IN (155, 156, 157)
)
AND (
"t3"."id" IN (1, 24, 25, 26, 27, 28)
)
)
GROUP BY
"t4"."id",
"t3"."id",
"t6"."id"
HAVING
(
(
"t6"."id" = MAX("t6"."id")
)
OR ("t6"."id" IS NULL)
)
Which results in:
psycopg2.errors.UndefinedTable: missing FROM-clause entry for table "solutions_subquery"
LINE 1: ...EFT OUTER JOIN "solution" AS "t1" ON ("t1"."id" = "solutions...
During handling of the above exception, another exception occurred:
[Truncated for readability...]
loguru.logger.critical(str(list(solutions.dicts().execute())))
[Truncated for readability...]
peewee.ProgrammingError: missing FROM-clause entry for table "solutions_subquery"
LINE 1: ...EFT OUTER JOIN "solution" AS "t1" ON ("t1"."id" = "solutions...
Why does peewee flatten the query? Is there another way to use LEFT_JOIN?
Eventually found the Select function in the documentation, which allows me to kind of wrap the previous query:
solutions = (
Select(columns=full_query_fields)
.from_(query)
.join(Solution, JOIN.LEFT_OUTER, on=(
Solution.id == query.c.solution_id
))
.join(SolutionAssessment, JOIN.LEFT_OUTER, on=(
(Solution.assessment == SolutionAssessment.id)
))
)
This solution works.

Power BI DAX - find repeatability

Given data as such:
Month ValueA
1 T
2 T
3 T
4 F
Is there a way to make a measure that would find if for each month, last three Values were True?
So the output would be (F,F,T,F)?
That would propably mean that my actual problem is solvable, which is finding from:
Month ValueA ValueB ValueC
1 T F T
2 T T T
3 T T T
4 F T F
the count of those booleans for each row, so the output would be (0,0,2[A and C],1[B])
EDIT:
Okay, I managed to solve the first part with this:
Previous =
VAR PreviousDate =
MAXX(
FILTER(
ALL( 'Table' ),
EARLIER( 'Table'[Month] ) > 'Table'[Month]
),
'Table'[Month]
)
VAR PreviousDate2 =
MAXX(
FILTER(
ALL( 'Table' ),
EARLIER( 'Table'[Month] ) - 1 > 'Table'[Month]
),
'Table'[Month]
)
RETURN
IF(
CALCULATE(
MAX( 'Table'[Value] ),
FILTER(
'Table',
'Table'[Month] = PreviousDate
)
) = "T"
&& CALCULATE(
MAX( 'Table'[Value] ),
FILTER(
'Table',
'Table'[Month] = PreviousDate2
)
) = "T"
&& 'Table'[Value] = "T",
TRUE,
FALSE
)
But is there a way to use it with unknown number of columns?
Without hard - coding every column name? Like a loop or something.
I would redo the data table in power query (upivoting the ValueX-columns) and changing T/F to 1/0. Then have a dim table with a relationship to Month, like this:
Then add a measure like this:
Three Consec T =
var maxMonth = MAX('Data'[Month])
var tempTab =
FILTER(
dimMonth;
'dimMonth'[MonthNumber] <= maxMonth && 'dimMonth'[MonthNumber] > maxMonth -3
)
var sumMonth =
MAXX(
'dimMonth';
CALCULATE(
SUM('Data'[OneOrZero]);
tempTab
)
)
return
IF(
sumMonth >= 3;
"3 months in a row";
"No"
)
Then I can have a visual like this when the slicer indicates which time window I'm looking at and the table shows if there has been 3 consecutive Ts or not.

Using Multiple ANDs and ORs in ANSI SQL

I have a simple SQL query:
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND w.buzz IS NOT NULL
AND w.foo = 12
In pseudo-code, this WHERE clause could be thought of as:
if(specialId == 2394 && buzz != null && foo == 12)
I now want to change this query so that it returns all widgets whose special_id is 2394, and whose buzz is not null, and whose foo is 12, OR whose special_id is 2394, and whose blah is 'YES', and whose num is 4. In pseudo-code:
if(specialId == 2394 && (buzz != null && foo == 12) || (blah == "YES" && num == 4))
I tried the following, only to get errors:
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND
(
w.buzz IS NOT NULL
AND w.foo = 12
)
OR
(
w.blah = 'YES'
AND w.num = 4
)
Any ideas? Thanks in advance!
SELECT
w.fizz
FROM
widgets w
WHERE
w.special_id = 2394
AND
(
(
w.buzz != null
AND w.foo = 12
)
OR
(
w.blah = 'YES'
AND w.num = 4
)
)
Add additional brackets surrounding "OR", because "OR" has less priority than "AND".

sql statement how to keep null value

This query here is executed on 3 tables(students) one which makes a zero on the exam so his q.correctanswer != ur.response, how can I keep the 0 value in my output. When i execute this statement it only gives me two values instead of 3 for each student.
select count(*) as Test1
from users u, question q, userresponse ur
where q.eno = '1'
and q.eno = ur.eno
and q.qno = ur.qno
and ur.response = q.correctanswer
and u.uno = ur.uno
group by u.uno
sample data:
Note:
- "||" is used to concatenate strings
- each string is between a pair of single quotes.
- each record is between "(" and ")".
- fields are ordered according to fields in tables
- "\n" means a new line
======exams data==========
(1,'Java Programming',60,1)
(3,'Elementary History',10,3)
======questions data===========
(1,1,'Choose the operations that can be performed on String
objects:(A) +\n(B) + =\n(C) -\n(D) %\n(E) ^','B')
(1,2,'What will be the result of the expression\na % b\nwhen a and b
are of type int and their values are a = -17 and b = -6?','A')
(1,3,'What will be the result of the expression\na % b\nwhen a and b
are of type int and their values are a = 10 and b = 6?','B')
(1,4,'Consider the following code:\nint x, y, z\ny = 1\nz = 5\nx = 0
- (++y) + z++\nAfter execution of this, what will be the values of x, y and z?','C')
(1,5,'Identify the statements that are correct:\n(A) int a = 13,
a>>2 = 3\n(B) int b = -8, b>>1 = -4\n(C) int a = 13, a>>>2 = 3\n(D)
int b = -8, b>>>1 = -4','E')
(1,6,'If not assigned a value, a variable of type char has the
following default value:','A')
(1,7,'What will be the value of a after execution of the following
statements:\nint a = 23, b = 34\na = ((a < b) ? (b + a) : (b -
a)','B')
(1,8,'Which of the following is not a hexadecimal number?\n(A)
999\n(B) (hex)23\n(C) 0x556\n(D) 0x1F2','C')
(1,9,'if(check4Biz(storeNum) != null) {}\nReferring to the above,
what datatype could be returned by method check4Biz()?','D')
(1,10,'Select the invalid assignment statements from the
following:\n(A) float x = 238.88\n(B) double y = 0x443\n(C) int n =
(int) true\n(D) long m =778645','A')
(1,11,'int j\nfor(int i=0i<14i++) {\nif(i<10) {\nj = 2 +
i\n}\nSystem.out.println("j: " + j + " i: " + i)\n}\nWhat is WRONG
with the above code?','E')
(1,12,'Consider the following code:\nclass ClassA\n{\npublic static
void main(String args [ ])\n{\nClassB b = classB()\n}\nClassA(int x) {
}\n}\nclass ClassB extends ClassA\n{\n}\nWhat will happen when we
compile and run this code?','A')
(1,13,'The keywords reserved but not used in the initial version of
Java are:\n(A) union\n(B) const\n(C) inner\n(D) goto\n(E) boolean\n(F)
synchronized','C')
(1,14,'We would like to make a member of a class visible in all
subclasses regardless of what package they are in. Which one of the
following keywords would achieve this?','D')
(1,15,'Which of the following are not keywords?\n(A) NULL\n(B)
implements\n(C) protected\n(D) extended\n(E) string','B')
(3,1,'The Battle of Gettysburg was fought during which war?','C')
(3,2,'Neil Armstrong and Buzz Aldrin walked how many \n' ||
'minutes on the moon in 1696?','B')
(3,3,'Which Presidents held office during World War II?','D')
(3,4,'In a communist economic system, people:','B')
(3,5,'Which president did not die while in office?','D')
(3,6,'Which state refused to attend the Constitutional Convention
\n' ||
'in 1787 because it didn''t want the United States government \n' ||
'to interfere with already established state affairs?','A')
(3,7,'Who founded Buddhism?','A')
(3,8,'Where is India?','D')
(3,9,'What is the dominant religion in India?','B')
(3,10,'Near which river did archaeologists find India''s \n' ||
'first civilization?','B')
========== answerOption data ============
(3,8,'A','Australia') (3,8,'B','America') (3,8,'C','Africa')
(3,8,'D','Asia') (3,1,'A','World War II') (3,1,'B','The
Revolutionary War') (3,1,'C','The Civil War') (3,1,'D','World War I')
(3,2,'A','123') (3,2,'B','None') (3,2,'C','10') (3,2,'D','51')
(3,3,'A','Franklin D. Roosevelt') (3,3,'B','Dwight D. Eisenhower')
(3,3,'C','Harry Truman') (3,3,'D','Both A and C') (3,4,'A','Are
forced to work as slaves') (3,4,'B','Work for the common good')
(3,4,'C','Work from home computers') (3,4,'D','Don''t work')
(3,5,'A','John F. Kennedy') (3,5,'B','Franklin D. Roosevelt')
(3,5,'C','Abraham Lincoln') (3,5,'D','Ronald Reagan')
(3,5,'E','James A. Garfield') (3,7,'A','Siddharta Gautama')
(3,7,'B','Jesus Christ') (3,7,'C','Mahatma Gandhi')
(3,7,'D','Muhammad') (3,6,'A','Rhode Island') (3,6,'B','New
Hampshire') (3,6,'C','New Jersey') (3,6,'D','New York')
(3,9,'A','Islam') (3,9,'B','Hinduism') (3,9,'C','Christianity')
(3,9,'D','Buddhism') (3,10,'A','The Tiber River') (3,10,'B','The
Indus River') (3,10,'C','The Yellow River') (3,10,'D','The Nile
River') (1,1,'A','(D) & (E)') (1,1,'B',' (A) & (B)') (1,1,'C','(D)')
(1,1,'D','(A)') (1,1,'E','None of these') (1,2,'A','-17')
(1,2,'B','5') (1,2,'C','3') (1,2,'D','-5') (1,2,'E','None of these')
(1,3,'A','1.66') (1,3,'B','4') (1,3,'C','2') (1,3,'D','1')
(1,3,'E','None of these') (1,4,'A','x = 4, y = 1, z = 5') (1,4,'B',' x
= -7, y = 1, z = 5') (1,4,'C','x = 3, y = 2, z = 6') (1,4,'D',' x = 4, y = 2, z = 6') (1,4,'E',' x = 8, y = 2, z = 1') (1,5,'A','(C) & (D) ')
(1,5,'B',' (A), (B) & (C) ') (1,5,'C','(A), (B), (C) & (D)')
(1,5,'D','(A) & (B) ') (1,5,'E','None of the above')
(1,6,'A','\uffff') (1,6,'B','\u0000') (1,6,'C','" " (space)')
(1,6,'D','\u0001') (1,6,'E','None of the above') (1,7,'A','23')
(1,7,'B','Error. Cannot be executed.') (1,7,'C','57') (1,7,'D','11')
(1,7,'E','34') (1,8,'A','(A), (B) & (C)') (1,8,'B','(C)')
(1,8,'C','(A) & (B) ') (1,8,'D','(A)') (1,8,'E','(D)')
(1,9,'A','Boolean') (1,9,'B','Int') (1,9,'C','String')
(1,9,'D','Char') (1,9,'E','Byte') (1,10,'A','(A) & (C)')
(1,10,'B','(A) & (B)') (1,10,'C','(B) ') (1,10,'D','(B) & (D) ')
(1,10,'E','(D)') (1,11,'A','Integer "j" is not initialized.')
(1,11,'B','Nothing.') (1,11,'C','You cannot declare integer i inside
the for-loop declaration.') (1,11,'D','The syntax of the "if"
statement is incorrect.') (1,11,'E','You cannot print integer values
without converting them to strings.') (1,12,'A','Will compile and run
successfully ') (1,12,'B','Error. ClassA does not define a no-argument
constructor ') (1,12,'C','Error. There is no code in the constructor
ClassA(int x) ') (1,12,'D','Error. ClassB does not define a
no-argument constructor ') (1,12,'E','Error. There is no code in the
class ClassB ') (1,13,'A','(C) & (E) ') (1,13,'B','(B),(C) & (D)')
(1,13,'C','(A), (C) & (E)') (1,13,'D','All of these. ')
(1,13,'E','None of these. ') (1,14,'A','private ') (1,14,'B','public')
(1,14,'C','protected') (1,14,'D','private OR protected')
(1,14,'E','All of the above') (1,15,'A','(C), (D) & (E)')
(1,15,'B','(D) ') (1,15,'C','(A), (D) & (E)') (1,15,'D','(D) & (E) ')
(1,15,'E','(A)')
===== users data ====
(1,'1#gmail.com','','George','Ronald','','','Atlanta','GA','30303')
(2,'2#gmail.com','','Mary','Erikson','','','San Diego','CA','91901')
(3,'3#gmail.com','','John','Washington','','','Atlanta','GA','30314')
====enrolls data=====
(1,1,to_date('2012/02/15 10:00:00', 'yyyy/mm/dd
hh24:mi:ss'),to_date('2012/02/22 10:00:00', 'yyyy/mm/dd hh24:mi:ss')
(2,1,to_date('2012/02/15 10:00:00', 'yyyy/mm/dd
hh24:mi:ss'),to_date('2012/02/22 10:00:00', 'yyyy/mm/dd hh24:mi:ss')
(3,1,to_date('2012/02/17 10:00:00', 'yyyy/mm/dd
hh24:mi:ss'),to_date('2012/02/24 10:00:00', 'yyyy/mm/dd hh24:mi:ss')
(1,3,to_date('2012/02/17 10:00:00', 'yyyy/mm/dd
hh24:mi:ss'),to_date('2012/02/24 10:00:00', 'yyyy/mm/dd hh24:mi:ss')
(2,3,to_date('2012/02/20 10:00:00', 'yyyy/mm/dd
hh24:mi:ss'),to_date('2012/02/27 10:00:00', 'yyyy/mm/dd hh24:mi:ss')
(3,3,to_date('2012/02/20 10:00:00', 'yyyy/mm/dd
hh24:mi:ss'),to_date('2012/02/27 10:00:00', 'yyyy/mm/dd hh24:mi:ss')
===userResponse data====
(1,1,1,'A') (1,1,2,'B') (1,1,3,'A') (1,1,4,'B') (1,1,5,'N')
(1,1,6,'C') (1,1,7,'D') (1,1,8,'A') (1,1,9,'B') (1,1,10,'B')
(1,1,11,'A') (1,1,12,'B') (1,1,13,'A') (1,1,14,'A') (1,1,15,'A')
(2,1,1,'B') (2,1,2,'B') (2,1,3,'E') (2,1,4,'C') (2,1,5,'D')
(2,1,6,'A') (2,1,7,'C') (2,1,8,'B') (2,1,9,'B') (2,1,10,'A')
(2,1,11,'A') (2,1,12,'B') (2,1,13,'B') (2,1,14,'A') (2,1,15,'A')
(3,1,1,'C') (3,1,2,'C') (3,1,3,'D') (3,1,4,'D') (3,1,5,'A')
(3,1,6,'A') (3,1,7,'D') (3,1,8,'D') (3,1,9,'A') (3,1,10,'A')
(3,1,11,'B') (3,1,12,'B') (3,1,13,'A') (3,1,14,'A') (3,1,15,'C')
(1,3,1,'N') (1,3,2,'A') (1,3,3,'A') (1,3,4,'B') (1,3,5,'B')
(1,3,6,'C') (1,3,7,'D') (1,3,8,'A') (1,3,9,'A') (1,3,10,'B')
(2,3,1,'B') (2,3,2,'C') (2,3,3,'A') (2,3,4,'C') (2,3,5,'B')
(2,3,6,'D') (2,3,7,'D') (2,3,8,'D') (2,3,9,'A') (2,3,10,'A')
(3,3,1,'B') (3,3,2,'A') (3,3,3,'A') (3,3,4,'B') (3,3,5,'B')
(3,3,6,'C') (3,3,7,'D') (3,3,8,'A') (3,3,9,'A') (3,3,10,'B')
Thanks,
What I think you're asking is "how many questions did any user get right?" If so, based on the query you have - and the fact that there's no direct relation between users and questions - I've come up with the following:
select u.uno, sum(case ur.response when null then 0 else 1 end) as Test1
from question q
cross join users u
left join userresponse ur
on q.eno = ur.eno
and q.qno = ur.qno
and q.correctanswer = ur.response
and u.uno = ur.uno
where q.eno = '1'
group by u.uno
So we do a cartesion join between users and questions, because we don't have a better way to join them. We then do an left outer join against the userresponse table; unless everything matches correctly, the user either didn't answer the question or answered it wrong. We cast whether or not that value's null to a 0 if null and 1 if if it's not, so the sum of those is the number of correct answers per user.
If I've understood your query correctly, the following ought to work. It uses the old Oracle join syntax:
SELECT u.uno, COUNT(*)
FROM users u, userresponse ur, question q
WHERE u.uno = ur.uno
AND ur.response = q.correctanswer(+)
AND ur.eno = q.eno(+)
AND ur.qno = q.qno(+)
AND q.eno(+) = 1
GROUP BY u.uno
I think that you are trying to get all users and the associated quiz score. If I understood correctly, then using appropriate joins clauses, you can easily get the expected results:
select u.uno, count (ur.response) as NumberAnswered, count (q.correctanswer) as NumberCorrect
from users u
join userresponse ur --inner join means we limit user rows to users who have responses
on u.uno = ur.uno
left outer join question q --outer join means we look for row data, but don't exclude users based on the fact that the row doesn't match the join conditions
on ur.response = q.correctanswer
and q.eno = 1 --only include rows where the question.eno value is 1(?)
and q.eno = ur.eno --only include rows where question.eno and userresponse.eno are the same (the answer was correct)
group by u.uno

How to join three tables?

SELECT
PC_SL_ACNO, -- DB ITEM
SLNAME, -- ACCOUNT NAME:
SL_TOTAL_AMOUNT -- TOTAL AMOUNT:
FROM GLAS_PDC_CHEQUES
WHERE PC_COMP_CODE=:parameter.COMP_CODE
AND pc_bank_from = :block02.pb_bank_code
AND pc_due_date between :block01.date_from
AND :block01.date_to
AND nvl(pc_discd,'X') IN(‘X’, 'R')
GROUP BY
pc_comp_code, pc_sl_ldgr_code, pc_sl_acno
ORDER BY pc_sl_acno
ACCOUNT NAME:
BEGIN
SELECT COAD_PTY_FULL_NAME INTO :BLOCK03.SLNAME
FROM GLAS_PTY_ADDRESS,GLAS_SBLGR_MASTERS
WHERE SLMA_COMP_CODE = :PARAMETER.COMP_CODE
AND SLMA_ADDR_ID = COAD_ADDR_ID
AND SLMA_ADDR_TYPE = COAD_ADDR_TYPE
AND SLMA_ACNO = :BLOCK03.PC_SL_ACNO
AND SLMA_COMP_CODE = COAD_COMP_CODE;
EXCEPTION WHEN OTHERS THEN NULL;
END;
TOTAL AMOUNT:
BEGIN
SELECT SUM(PC_AMOUNT) INTO :SL_TOTAL_AMOUNT
FROM GLAS_PDC_CHEQUES
WHERE PC_DUE_DATE BETWEEN :BLOCK01.DATE_FROM AND :BLOCK01.DATE_TO
AND PC_BANK_FROM = :block02.PB_BANK_CODE
AND PC_SL_ACNO = :BLOCK03.PC_SL_ACNO
AND NVL(PC_DISCD,'X') = 'R'
AND PC_COMP_CODE = :PARAMETER.COMP_CODE;
EXCEPTION WHEN OTHERS THEN :block03.SL_TOTAL_AMOUNT := 0;
END;
How can I join the three tables?
You'll have to adjust depending on precisely what criteria and required fields you have for your query or queries.
SELECT
c.PC_SL_ACNO,
a.COAD_PTY_FULL_NAME,
SUM(c.PC_AMOUNT)
FROM
GLAS_PDC_CHEQUES c
LEFT JOIN
GLAS_SBLGR_MASTERS m
ON ( c.PC_SL_ACNO = m.SLMA_ACNO
AND c.PC_COMP_CODE = m.SLMA_COMP_CODE
)
LEFT JOIN
GLAS_PTY_ADDRESS a
ON ( m.SLMA_ADDR_ID = a.COAD_ADDR_ID
AND m.SLMA_COMP_CODE = a.COAD_COMP_CODE
AND m.SLMA_ADDR_TYPE = a.COAD_ADDR_TYPE
)
WHERE
c.PC_COMP_CODE = :PARAMETER.COMP_CODE
AND c.PC_SL_ACNO = :BLOCK03.PC_SL_ACNO
AND c.PC_BANK_FROM = :BLOCK02.PB_BANK_CODE
AND NVL(c.PC_DISCD,'X') IN (‘X’, 'R')
AND c.PC_DUE_DATE BETWEEN :BLOCK01.DATE_FROM AND :BLOCK01.DATE_TO
GROUP BY
c.PC_SL_ACNO, -- not sure which grouping exactly you need.
a.COAD_PTY_FULL_NAME
ORDER BY
c.PC_SL_ACNO
I notice that in the first query you have pc_comp_code as a search criterion, and on the leading edge of your grouping - is that what you need?
This is a bit of an 'estimate' due to the enigmatic nature of your question!