I have following statement that is used to select some fields from MySQL DB
select finance_budget_issue.budget_date, SUM(finance_budget_issue.amount) AS amount, finance_vote.office_id as vote_office_id, finance_office.office_head as head,
finance_office.office_name AS office_name,
finance_budget.ref_no, finance_budget_issue.view_status, tbl_signature.office_head as sign_office_head, tbl_signature.name AS name,
tbl_signature.post AS post, tbl_signature.sign_id
from finance_budget_issue
inner join finance_budget on finance_budget.budget_id=finance_budget_issue.budget_id
left join finance_vote on finance_budget_issue.vote_id=finance_vote.vote_id
left join finance_vote_description on finance_vote.description=finance_vote_description.vote_description_id
left join finance_office on finance_budget_issue.office=finance_office.office_id
left join tbl_signature on finance_office.office_id=tbl_signature.office_id
The statement is working fine, but didn't outs the following fields
tbl_signature.office_head as sign_office_head,
tbl_signature.name AS name,
tbl_signature.post AS post
What may be going wrong ? I think that I used incorrect Joins. Can anyone help ?
Tables as follows :
finance_office
+----+-----------+-------------+------+
| id | office_id | office_name | head |
+----+-----------+-------------+------+
| 1 | 48 | A | SS |
| 2 | 69 | B | VV |
+----+-----------+-------------+------+
finance_vote
+---------+-----------+----------------+
| vote_id | office_id | vote |
+---------+-----------+----------------+
| 1 | 48 | 320-1-2-1-1001 |
| 2 | 48 | 320-2-2-2-2002 |
| 3 | 69 | 319-1-2-1-1001 |
| 4 | 69 | 319-1-2-2-1102 |
| 5 | 30 | 318-1-1-2-1101 |
+---------+-----------+----------------+
tbl_signature
+---------+-----------+---------+------------+-------------+
| sign_id | office_id | name | post | office_head |
+---------+-----------+---------+------------+-------------+
| 1 | 48 | Noel | Accountant | Manager |
| 2 | 69 | Jhon | Accountant | Manager |
| 3 | 30 | Micheal | Accountant | Manager |
+---------+-----------+---------+------------+-------------+
finance_budget
+-----------+--------+-------------+
| budget_id | ref_no | budget_date |
+-----------+--------+-------------+
| 1 | Acc/01 | 2020-01-20 |
| 2 | Acc/02 | 2020-01-22 |
+-----------+--------+-------------+
finance_budget_issue
+----+-----------+--------+---------------+-----------------+
| id | budget_id | amount | budget_status | transfer_status |
+----+-----------+--------+---------------+-----------------+
| 1 | 1 | 75000 | issues | Approved |
| 2 | 1 | 22000 | issues | Approved |
| 3 | 2 | 65000 | issues | Approved |
+----+-----------+--------+---------------+-----------------+
Desired Output
+--------+----------------+------+--------+------------------+------+------------+
| amount | vote_office_id | head | ref_no | sign_office_head | name | post |
+--------+----------------+------+--------+------------------+------+------------+
| 75000 | 48 | SS | Acc/01 | Manager | Noel | Accountant |
| 22000 | 48 | SS | Acc/01 | Manager | Noel | Accountant |
| 65000 | 69 | VV | Acc/02 | Manager | Jhon | Accountant |
+--------+----------------+------+--------+------------------+------+------------+
Generated Output (Incorrect)
+--------+----------------+------+--------+------------------+------+------+
| amount | vote_office_id | head | ref_no | sign_office_head | name | post |
+--------+----------------+------+--------+------------------+------+------+
| 75000 | 48 | SS | Acc/01 | | | |
| 22000 | 48 | SS | Acc/01 | | | |
| 65000 | 69 | VV | Acc/02 | | | |
+--------+----------------+------+--------+------------------+------+------+
This is easier to read:
SELECT i.budget_date
, SUM(i.amount) amount
, v.office_id vote_office_id
, o.office_head head
, o.office_name
, b.ref_no
, i.view_status
, s.office_head sign_office_head
, s.name
, s.post
, s.sign_id
FROM finance_budget_issue i
JOIN finance_budget b
ON b.budget_id = i.budget_id
LEFT
JOIN finance_vote v
ON v.vote_id = i.vote_id
LEFT
JOIN finance_vote_description d
ON d.vote_description_id = v.description
LEFT
JOIN finance_office o
ON i.office = o.office_id
LEFT
JOIN tbl_signature s
ON s.office_id = o.office_id
You have an aggregate function (and non-aggregated columns) but no GROUP BY clause; that's not going to work. You have a LEFT JOINed table from which you select no columns; that's pointless.
For further help, see Why should I provide an MCRE for what seems to me to be a very simple SQL query
Related
I have following tables to manage purchase and issues of items.
item Table
+---------+-----------+
| item_id | item_name |
+---------+-----------+
| 500 | A4 |
| 501 | A5 |
| 502 | B5 |
| 503 | B4 |
| 504 | A3 |
+---------+-----------+
supplier Table
+-------------+---------------+
| sup_id | supplier_name |
+-------------+---------------+
| 1 | ABC Suppliers |
| 2 | DEF Suppliers |
| 3 | GHI Suppliers |
+-------------+---------------+
officer Table
+------------+--------------+
| officer_id | officer_name |
+------------+--------------+
| 1 | Jhon |
| 2 | William |
| 3 | Ken |
| 4 | Robert |
+------------+--------------+
purchase / issue table
+-----------+---------+---------+---------+------------+-----+-------------+
| update_id | bill_no | sup_id | item_id | date | qty | type |
+-----------+---------+---------+---------+------------+-----+-------------+
| 1000 | 10 | 1 | 500 | 2018-11-01 | 50 | purchase |
| 1001 | 40 | 1 | 500 | 2018-11-02 | 25 | purchase |
| 1002 | 32 | 2 | 500 | 2018-11-04 | 10 | issue |
| 1003 | 25 | 3 | 500 | 2018-11-05 | 12 | issue |
| 1004 | 14 | 1 | 500 | 2018-11-08 | 22 | purchase |
| 1005 | 55 | 2 | 501 | 2018-11-09 | 10 | purchase |
| 1006 | 30 | 2 | 502 | 2018-11-10 | 40 | purchase |
+-----------+---------+---------+---------+------------+-----+-------------+
02) purchase / issue table holds the purchase details and issue details by mentioning the "type" at the end of table.
03) I need to get the following output.
+-----------+------------------------------+------------+-----+------------+
| item_name | supplier_name / officer_name | date | qty |type |
+-----------+------------------------------+------------+-----+------------+
| A4 | ABC Suppliers | 2018-11-01 | 50 | purchase |
| A4 | ABC Suppliers | 2018-11-02 | 25 | purchase |
| A4 | William | 2018-11-04 | 10 | issue |
| A4 | Ken | 2018-11-05 | 12 | issue |
| A4 | ABC Suppliers | 2018-11-08 | 22 | purchase |
| A5 | DEF Suppliers | 2018-11-09 | 10 | purchase |
| B5 | DEF Suppliers | 2018-11-10 | 40 | purchase |
+-----------+------------------------------+------------+-----+------------+
03) I used the following query
select item.item_name,
supplier.supplier_name,
purchase.date,
purchase.qty,
purchase.type
from purchase
join item on item.item_id = purchase.item_id
where supplier.sup_id in (select sup_id from supplier)
04) But I did't get the desired output. I can not understand what I am going wrong. Can anyone help me ?
In your SELECT clause, you are referring to supplier table, without joining to that table. Now, it seems that you want to show officer_name when the purchase type is issue, else supplier_name when it is purchase.
We can do a LEFT JOIN to both the tables, and use CASE .. WHEN to determine the respective name.
I have removed the WHERE .. IN subquery, which does not seem to serve any purpose here.
select item.item_name,
CASE purchase.type
WHEN 'purchase' THEN supplier.supplier_name
WHEN 'issue' THEN officer.officer_name
END AS `supplier_name_officer_name`
purchase.date,
purchase.qty,
purchase.type
from purchase
join item on item.item_id = purchase.item_id
left join supplier on purchase.sup_id = supplier.sup_id
left join officer on purchase.sup_id = officer.officer_id
You need to join the supplier just as you did for the item.
And I see no point in the where clause at all.
I have the following tables:
clients:
| id | name | code | zone |
--------------------------------
| 1 | client 1 | a1b1 | zone1|
| 2 | client 2 | a2b2 | zone2|
contacts:
| id_contact | first_name | last_name |
----------------------------------------
| 11 | first1 | last1 |
| 22 | first2 | last2 |
| 33 | first3 | last3 |
| 44 | first4 | last4 |
client_contacts:
| id_client | id_contact |
--------------------------
| 1 | 11 |
| 1 | 22 |
| 1 | 33 |
| 2 | 11 |
| 2 | 44 |
offers:
| id_offer | id_client | value |
--------------------------
| 111 | 1 | 100 |
| 222 | 1 | 200 |
| 333 | 1 | 300 |
| 444 | 2 | 400 |
I would like through a optimal select to obtain:
| id_client | name | code | zone | contacts_pers | total_offer_value |
----------------------------------------------------------------------------
| 1 | client 1 | a1b1 | zone1 | first1 last1; | 600 |
first2 last2;
first3 last3;
| 2 | client 2 | a2b2 | zone2 | first1 last1; | 400 |
first4 last4;
I know how to get the desired result with "group_concat" and stored procedures for "total_offer_value". But how to get the desired result from a single efficient select?
SELECT c.id, c.name, c.code, c.zone, GROUP_CONCAT(DISTINCT CONCAT(co.first_name, " ", c.last_name) SEPARATOR ";") AS contact_pers, func_total_offer_value(c.id) AS total_offer_value
FROM clients c
LEFT OUTER JOIN (client_contacts cc, contacts co) ON ( c.id = cc.id_client AND cc.id_contact = co.id_contact )
GROUP BY c.id
I have one key table, a number of data tables with same column names in them, and one users table. I am trying to select values from the key table, join this output with some selected values from each of the data tables by unique ID (uaID) to the entries selected already from the key table (each key table result will have a relative join from only one of the range of data tables, not all of them and some entries will return a null result from the data tables and we don't want this to break anything or be omitted because of the null result), and then finally join some user data to each result from the users table. This will always have a result.
Let me "draw" a basic version of my tables so you can see.
keyTable
-----------------------------------------
| uaID | userID | key | appName |
|---------------------------------------|
| 1 | 7 | ABC01 | Physics |
| 2 | 9 | DEF20 | Geometry |
| 3 | 12 | XJG14 | Biology |
| 4 | 19 | DAF09 | Chemistry |
| 5 | 27 | KYT78 | Algebra |
| 6 | 29 | PLF43 | Statistics|
| 7 | 34 | COG89 | Geology |
| 8 | 45 | HYL72 | Art |
| 9 | 48 | TSK45 | History |
| 10 | 53 | BBS94 | GeoChem |
| 11 | 59 | DOD10 | BioChem |
| 12 | 27 | HKV62 | Music |
-----------------------------------------
dataTable01
-----------------------------------------------
| uaID | sector | subSector | topic |
|---------------------------------------------|
| 2 | circle | volumn | measure |
| 7 | triangle | hypotenuse |pythagoras |
| 8 | square | | |
| 11 | triangle | hypotenuse |pythagoras |
-----------------------------------------------
dataTable02
---------------------
| uaID | topic |
|-------------------|
| 1 | door |
| 3 | window |
| 9 | porch |
| 12 | |
---------------------
dataTable03
-----------------------------------------------
| uaID | sector | subSector | topic |
|---------------------------------------------|
| 4 | cat | feline | kitty |
| 5 | dog | canine | rover |
| 6 | kangaroo | marsupial | jack |
| 10 | bunny | leporidae | peter |
-----------------------------------------------
users
------------------------------------------------------------------------
| userID | Title | firstName | lastName | email |
|----------------------------------------------------------------------|
| 7 | Dr | Melissa | Smith | mel#email.com |
| 9 | Mr | Bob | Andrews | bob#email.com |
| 12 | Miss | Clare | Greco | clare#email.com |
| 19 | Mr | Dan | Fonseca | dan#email.com |
| 27 | Mr | Matt | Jones | matt#email.com |
| 29 | Mr | Chris | Nimmo | chris#email.com |
| 34 | Mrs | Lisa | Araujo | lisa#email.com |
| 45 | Miss | Raquel | Bailey | raquel#email.com |
| 48 | Dr | Steven | Dowd | steven#email.com |
| 53 | Prof | Roger | Hesp | roger#email.com |
| 59 | Prof | Sally | Bryce | sally#email.com |
| 65 | Mrs | Elena | Eraway | elena#email.com |
------------------------------------------------------------------------
And this is what I am trying to achieve as the end result:
-------------------------------------------------------------------------------------------------------------------------------
| uaID | key | appName | sector | subSector | topic | title | firstName | lastName | email |
|-----------------------------------------------------------------------------------------------------------------------------|
| 1 | ABC01 | Physics | | | door | Dr | Melissa | Smith | mel#email.com |
| 2 | DEF20 | Geometry | circle | volumn | measure | Mr | Bob | Andrews | bob#email.com |
| 3 | XJG14 | Biology | | | window | Miss | Clare | Greco | clare#email.com |
| 4 | DAF09 | Chemistry | cat | feline | kitty | Mr | Dan | Fonseca | dan#email.com |
| 5 | KYT78 | Algebra | dog | canine | rover | Mr | Matt | Jones | matt#email.com |
| 6 | PLF43 | Statistics| kangaroo | marsupial | jack | Mr | Chris | Nimmo | chris#email.com |
| 7 | COG89 | Geology | triangle | hypotenuse |pythagoras | Mrs | Lisa | Araujo | lisa#email.com |
| 8 | HYL72 | Art | square | | | Miss | Raquel | Bailey | raquel#email.com |
| 9 | TSK45 | History | | | porch | Dr | Steven | Dowd | steven#email.com |
| 10 | BBS94 | GeoChem | bunny | leporidae | peter | Prof | Roger | Hesp | roger#email.com |
| 11 | DOD10 | BioChem | triangle | hypotenuse |pythagoras | Prof | Sally | Bryce | sally#email.com |
| 12 | HKV62 | Music | | | | Mr | Matt | Jones | matt#email.com |
-------------------------------------------------------------------------------------------------------------------------------
I am attempting to achieve this by executing:
$sql = "SELECT keyTable.uaID, keyTable.userID, keyTable.key,
keyTable.appName, dataTable01.sector, dataTable01.subSector,
dataTable01.topic, dataTable02.topic, dataTable03.sector,
dataTable03.subSector, dataTable03.topic, users.title,
users.firstName, users.lastName, users.email
FROM keyTable
LEFT OUTER JOIN dataTable01 ON keyTable.uaID = dataTable01.uaID
LEFT OUTER JOIN dataTable02 ON keyTable.uaID = dataTable02.uaID
LEFT OUTER JOIN dataTable03 ON keyTable.uaID = dataTable03.uaID
LEFT OUTER JOIN users ON keyTable.userID = users.userID";
I get all the keyTable data. I get all the users data right where it's supposed to join up all ok. I get all the dataTable03 data as well, but I do not get any data from dataTable01 or dataTable02 showing up in the result. If I omit the call to dataTable03 I then get all the relevant data from dataTable02 showing up, but no data from dataTable01. The call to the users table is at the end and always shows up fine. So clearly it's an issue with the matching field names in the data tables. I get no errors at all and the process completes, just with the mentioned data missing. I've tried different JOINS - INNER JOIN, OUTER JOIN, LEFT OUTER JOIN. There obviously has to be a way to achieve this but cannot seem to find any references on the web to this specific problem. Can someone tell me what I am doing incorrectly please?
After joining, you can use COALESCE to get the non-null value from the table with a matching row.
$sql = "SELECT k.uaID, k.userID, k.key, k.appName,
COALESCE(d1.sector, d3.sector, '') AS sector,
COALESCE(d1.subSector, d3.subSector, '') AS subSector,
COALESCE(d1.topic, d2.topic, d3.topic, '') AS topic,
users.title, users.firstName, users.lastName, users.email
FROM keyTable AS k
LEFT OUTER JOIN dataTable01 AS d1 ON k.uaID = d1.uaID
LEFT OUTER JOIN dataTable02 AS d2 ON k.uaID = d2.uaID
LEFT OUTER JOIN dataTable03 AS d3 ON k.uaID = d3.uaID
LEFT OUTER JOIN users ON k.userID = users.userID
ORDER BY k.uaID";
Another way to merge the data from the datatablesNN tables into the same column os tp use UNION.
SELECT k.uaID, k.userID, k.key, k.appName, IFNULL(d.sector, '') AS sector, IFNULL(d.subSector, '') AS subSector, IFNULL(d.topic, '') AS topic,
u.title, u.firstName, u.lastName, u.email
FROM keyTable AS k
LEFT OUTER JOIN (
SELECT uaID, sector, subSector, topic
FROM dataTable01
UNION
SELECT uaID, NULL, NULL, topic
FROM datatable02
UNION
SELECT uaID, sector, subSector, topic
FROM datatable03) AS d
ON k.uaID = d.uaID
LEFT JOIN users AS u ON u.userID = k.userID
ORDER BY k.uaID
DEMO
You would have to use aliases
simular issue and solution here:
php-mysql-how-to-resolve-ambiguous-column-names-in-join-operation
select * from common inner join (
(select link from table1)
union
(select link from table2)
) as unionT
on unionT.link = common.link
I have several tables that I combine in an application I'm creating in PHP that essentially creates a check list. I realize I could solve this problem using a conditional in PHP, but am curious if MySQL is capable of accomplishing this and if so, how? Specifically, I have four tables which are queried using the following statement:
SELECT
cl_status.status,
users.user_first,
cl_status.date AS status_date,
cl_status.id AS status_id,
cl_status.criteria_id,
cl_criteria.id AS cid,
cl_criteria.description AS description
FROM cl_criteria
LEFT JOIN cl_lists
ON cl_criteria.cl_id = cl_lists.id
RIGHT JOIN cl_status
ON cl_criteria.id = cl_status.criteria_id
LEFT JOIN users
ON cl_status.user_id = users.user_id
WHERE cl_lists.id = '1'
Table one - cl_lists:
+----+------------------+------------+------------+-------+
| id | title | date | comp_level | owner |
+----+------------------+------------+------------+-------+
| 1 | Newcomer's guide | 1452473606 | 1 | 1 |
+----+------------------+------------+------------+-------+
Table two - cl_assign:
+----+-------+-------+------------+
| id | cl_id | owner | date |
+----+-------+-------+------------+
| 1 | 1 | 1 | 1455843514 |
+----+-------+-------+------------+
Table three - cl_status:
+----+-------------+---------+-------------+------------+--------+----------+
| id | criteria_id | user_id | description | date | status | comments |
+----+-------------+---------+-------------+------------+--------+----------+
| 2 | 66 | 1 | | NULL | 1 | NULL |
| 15 | 65 | 1 | | 1455842197 | 5 | NULL |
| 16 | 67 | 1 | | 1455842201 | 5 | NULL |
| 17 | 68 | 1 | | 1455842203 | 5 | NULL |
| 18 | 69 | 1 | | 1455842217 | 0 | NULL |
| 19 | 70 | 1 | | 1455842222 | 5 | NULL |
| 20 | 72 | 1 | | 1455842237 | 1 | NULL |
| 21 | 71 | 1 | | 1455842234 | 0 | NULL |
| 22 | 73 | 1 | | 1455842246 | 5 | NULL |
| 23 | 76 | 1 | | 1455842249 | 5 | NULL |
| 24 | 77 | 1 | | 1455842268 | 5 | NULL |
| 25 | 78 | 152 | | 1455854420 | 3 | NULL |
| 26 | 81 | 1 | | 1455843660 | 5 | NULL |
+----+-------------+---------+-------------+------------+--------+----------+
Table four - users:
+---------+------------+
| user_id | user_first |
+---------+------------+
| 1 | Mark |
| 2 | Test |
+---------+------------+
Ideally, I'd like the join to look like this:
+--------+------------+-------------+-----------+-------------+------+-----------------------------+
| status | user_first | status_date | status_id | criteria_id | cid | description |
+--------+------------+-------------+-----------+-------------+------+-----------------------------+
| 5 | Mark | 1455842197 | 15 | 65 | 65 | Tour of facility |
| 5 | Mark | 1455842201 | 16 | 67 | 67 | Tax forms |
| 5 | Mark | 1455842203 | 17 | 68 | 68 | 2 forms of ID |
| 0 | Mark | 1455842217 | 18 | 69 | 69 | Benefits | |
| 5 | Mark | 1455842246 | 22 | 73 | 73 | Intro to policies |
| 5 | Mark | 1455842249 | 23 | 76 | 76 | Setup email account |
| NULL | NULL | NULL | NULL | 78 | 78 | Setup Computer account |
+--------+------------+-------------+-----------+-------------+------+-----------------------------+
However, it looks like this:
+--------+------------+-------------+-----------+-------------+------+-----------------------------+
| status | user_first | status_date | status_id | criteria_id | cid | description |
+--------+------------+-------------+-----------+-------------+------+-----------------------------+
| 5 | Mark | 1455842197 | 15 | 65 | 65 | Tour of facility |
| 5 | Mark | 1455842201 | 16 | 67 | 67 | Tax forms |
| 5 | Mark | 1455842203 | 17 | 68 | 68 | 2 forms of ID |
| 0 | Mark | 1455842217 | 18 | 69 | 69 | Benefits |
| 5 | Mark | 1455842246 | 22 | 73 | 73 | Intro to policies |
| 5 | Mark | 1455842249 | 23 | 76 | 76 | Setup email account |
| 3 | Temp | 1455854420 | 25 | 78 | 78 | Setup Computer account |
+--------+------------+-------------+-----------+-------------+------+-----------------------------+
Is there a way to apply the conditional before the join? Or another way to accomplish the result set that I want?
EDIT
This is a screenshot of what the application looks like:
The criteria table will include steps of every checklist I have. The list table is a list of the various checklists. The status table allows every user (such as Mark, or Test) to look at the same checklist and complete it as if it was a separate document. It also populates the date/time that the item was updated by that user.
I suspect that the RIGHT JOIN you have in your query is causing the records you want to appear to be filtered out. Remember that t1 RIGHT JOIN t2 is the same as t2 LEFT JOIN t1, meaning that t1 will lose any record which does not appear in t2, with t2 keeping all its records. Try this:
SELECT cl_status.status, users.user_first, cl_status.date AS status_date,
cl_status.id AS status_id, cl_status.criteria_id, cl_criteria.id AS cid,
cl_criteria.description AS description
FROM cl_criteria LEFT JOIN cl_lists
ON cl_criteria.cl_id = cl_lists.id
LEFT JOIN cl_status
ON cl_criteria.id = cl_status.criteria_id
LEFT JOIN users
ON cl_status.user_id = users.user_id
WHERE cl_lists.id = '1'
I'm trying to produce a formula which pits our students' reward points against their negative behaviour flags.
Students are given LEAP points (in the transactions table) for their positive behaviour. They get more points depending on the category of their reward, i.e. Model Citizen gives the student 10 points.
On the other hand, students are given single Flags for negative behaviour. The category of the Flag is then weighted in a database table, i.e. the Aggressive Defiance category will have a high weighting of 4 whereas Low Level Disruption will only be worth 1.
The difficulty therefore is trying to factor in the Flag categories' weightings. They're stored in the categories table under the Weight column.
Here's the SQL fiddle: http://sqlfiddle.com/#!2/2e5756
In my head, the pseudo-SQL code would look something like this...
SELECT
CONCAT( stu.Surname, ", ", stu.Firstname ) AS `Student`,
SUM(t.Points) AS `LEAP Points`,
SUM(<<formula>>) AS `Flags`
( `LEAP Points` - `Flags` ) AS `Worked Out Points Thing`
FROM student stu
LEFT JOIN transactions t ON t.Recipient_ID = stu.id
LEFT JOIN flags f ON f.Student_ID = stu.id
LEFT JOIN categories c ON f.Category_ID = c.ID
GROUP BY stu.id
However, it's the <<formula>> that I have no idea how to implement in MySQL. It needs to be something like this:
SUM OF[ Each of Student's Flags * that Flag's Category Weighting ]
So, if a student has these flags...
#1 f.Reason "Being naughty", f.Category_ID "1", c.Title "Low Level Disruption", c.Weight "1"
#1 Reason "Aggressively naughty!", Category "Aggressive Defiance", Category Weighting "4"
#1 Reason "Missed detention", Category "Missed Detention", Category Weighting "3"
They would have a total of 1+4+3 = 9 points to use in the Worked Out Points Thing equation.
The desired output therefore is essentially...
Student LEAP Points Flags Equation Points LEAP Points minus Flag Points
D Wraight 1000 800 200
D Wraight2 500 800 -300
D Wraight3 1200 300 900
From the SQL fiddle above, here is the required output.. I've missed out some students because I had to work these out manually:
STUDENT FLAGS LEAP EQUATION
137608 4 (2+2) 12 (2+5+5) 8 (12-4)
139027 2 (2) 7 (2+5) 5 (7-2)
139041 4 (2+1+1+NULL) 8 (2+2+2+2) 4 (8-4)
139892 4 (4) 0 -4 (0-4)
138832 4 (4) 0 -4 (0-4)
34533 4 (4) 0 -4 (0-4)
137434 0 10 (2*5) 10 (10-0)
Which will help us to work out the choices we make available to each student when looking at end of year reward trips.
Hope that makes sense.. it's kinda boggled my head trying to explain it..
Thanks in advance,
figure out your 'formula' bit first because it's the deepest part. work outwards.
build a table of flags * weight per student
select sum(weight), student_id from flags f
join categories c
on f.category_id = c.id
group by student_id
so now you've got a table of flag values to minus from sum of transactions per student
select sum(points), recipient_id from transactions
group by recipient_id
so now we have two tables with positive and negative values by student id (assuming obviously that student id is recipient id)
you want those with transactions but without flags to appear in the result, so outer join.
and number minus null is null so ifnull function on the flags to get 0
select a.student, points - ifnull(penalties, 0) as netPoints
from
(select sum(points) as points, recipient_id as student from transactions
group by student) as a
left outer join
(select sum(weight) as penalties, student_id as student from flags f
join categories c
on f.category_id = c.id
group by student) as b
on
a.student = b.student
so with the name in there it's just
select
concat(firstname, ', ', surname) as name,
ifnull(points,0) as totalPoints,
ifnull(penalties,0) as totalPenalties,
ifnull(points,0) - ifnull(penalties, 0) as netPoints,
ifnull(countFlags, 0)
from
student
left join
(select sum(points) as points, recipient_id as student from transactions
group by student) as a
on student.id = a.student
left join
(select sum(weight) as penalties, count(f.id) as countFlags, student_id as student from flags f
join categories c
on f.category_id = c.id
group by student) as b
on
student.id = b.student
join condition is always from student's id column, which is never null.
there are probably more efficient ways, but who cares?
Returning to the question (and at the risk of repeating myself!), given the following data set, what would the desired result set look like...
SELECT * FROM flags;
+------+------------+----------+---------------------+-----------+-------------+--------------------------+---------------------+
| ID | Student_ID | Staff_ID | Datetime | Period_ID | Category_ID | Action_Taken_Category_ID | Action_Taken_Status |
+------+------------+----------+---------------------+-----------+-------------+--------------------------+---------------------+
| 8843 | 137608 | 35003 | 2014-03-11 08:31:00 | 8 | 16 | 7 | P |
| 8844 | 137608 | 35003 | 2014-03-11 08:31:00 | 8 | 16 | 7 | P |
| 8845 | 139027 | 35003 | 2014-03-11 08:31:00 | 8 | 16 | 7 | P |
| 8846 | 139041 | 35003 | 2014-03-11 08:31:00 | 8 | 16 | 7 | P |
| 8847 | 139041 | 34961 | 2014-03-11 09:01:02 | 2 | 12 | 26 | P |
| 8848 | 139041 | 34996 | 2014-03-11 09:23:21 | 3 | 12 | 27 | C |
| 8849 | 139041 | 35022 | 2014-03-11 11:07:46 | 4 | 34 | 28 | P |
| 8850 | 139892 | 138439 | 2014-03-11 11:12:47 | 4 | 21 | 7 | C |
| 8851 | 138832 | 138439 | 2014-03-11 11:12:48 | 4 | 21 | 7 | C |
| 8852 | 34533 | 138439 | 2014-03-11 11:12:48 | 4 | 21 | 7 | C |
+------+------------+----------+---------------------+-----------+-------------+--------------------------+---------------------+
SELECT * FROM categories;
+----+------+--------------------------------------+--------+----------+
| ID | Type | Title | Weight | Added_By |
+----+------+--------------------------------------+--------+----------+
| 10 | F | Low level disruption | 1 | NULL |
| 11 | F | Swearing directly at another student | 2 | NULL |
| 12 | F | Late | 1 | NULL |
| 13 | F | Absconded | 3 | NULL |
| 14 | F | Refusal to follow instruction | 3 | NULL |
| 15 | F | Smoking | 2 | NULL |
| 16 | F | No homework | 2 | NULL |
| 17 | F | Disruptive outside classroom | 2 | NULL |
| 18 | F | Eating/drinking in lesson | 1 | NULL |
| 19 | F | Incorrect uniform/equipment | 1 | NULL |
| 20 | F | Phone out in lesson | 3 | NULL |
| 21 | F | Aggressive defiance | 4 | NULL |
| 22 | F | Missed detention | 3 | NULL |
| 23 | F | Inappropriate behaviour/comments | 3 | NULL |
| 32 | F | IT Misuse | NULL | NULL |
| 34 | F | Inappropriate attitude towards staff | NULL | NULL |
| 35 | F | Care & Guidance | NULL | NULL |
+----+------+--------------------------------------+--------+----------+
SELECT * FROM transactions;
+----------------+------------+----------+--------------+--------+-------------+
| Transaction_ID | Datetime | Giver_ID | Recipient_ID | Points | Category_ID |
+----------------+------------+----------+--------------+--------+-------------+
| 34 | 2011-09-07 | 35019 | 137608 | 2 | 1 |
| 35 | 2011-09-07 | 35019 | 139027 | 2 | 1 |
| 36 | 2011-09-07 | 35019 | 139041 | 2 | 1 |
| 37 | 2011-09-07 | 35019 | 139041 | 2 | 1 |
| 38 | 2011-09-07 | 35019 | 139041 | 2 | 1 |
| 39 | 2011-09-07 | 35019 | 139041 | 2 | 1 |
| 40 | 2011-09-07 | 35019 | 137434 | 2 | 1 |
| 41 | 2011-09-07 | 35019 | 137434 | 2 | 1 |
| 42 | 2011-09-07 | 35019 | 137434 | 2 | 1 |
| 43 | 2011-09-07 | 35019 | 137434 | 2 | 1 |
| 44 | 2011-09-07 | 35006 | 137434 | 2 | 1 |
| 45 | 2011-09-07 | 35006 | 90306 | 2 | 1 |
| 46 | 2011-09-07 | 35006 | 90306 | 2 | 1 |
| 47 | 2011-09-07 | 35006 | 90306 | 2 | 1 |
| 48 | 2011-09-07 | 35023 | 137608 | 5 | 2 |
| 49 | 2011-09-07 | 35023 | 139027 | 5 | 2 |
| 50 | 2011-09-07 | 35023 | 139564 | 5 | 2 |
| 51 | 2011-09-07 | 35023 | 139564 | 5 | 2 |
| 52 | 2011-09-07 | 35023 | 139564 | 5 | 2 |
| 53 | 2011-09-07 | 35023 | 137608 | 5 | 3 |
+----------------+------------+----------+--------------+--------+-------------+
SELECT id,UPN,Year_Group,Tutor_Group,SEN_Status,Flags FROM student;
+--------+---------------+------------+-------------+------------+--------+
| id | UPN | Year_Group | Tutor_Group | SEN_Status | Flags |
+--------+---------------+------------+-------------+------------+--------+
| 137608 | A929238400044 | 11 | 11VID | A | |
| 139027 | A929238401045 | 10 | 10KS | | |
| 139041 | A929238402017 | 10 | 10RJ | A | FSM |
| 139892 | A929238403018 | 9 | 9BW | | |
| 139938 | A929238403020 | 9 | 9RH | | |
| 137434 | A929238500027 | 11 | 11VID | | |
| 138832 | A929238502002 | 10 | 10RY | A | FSM,PA |
| 34533 | A929238599028 | 0 | | | PA |
| 139564 | A929241500025 | 12 | | | PA |
| 90306 | A929253100006 | 12 | SLH | A | PA |
+--------+---------------+------------+-------------+------------+--------+