My goal is to get a table that counts the correct answers from a game.
For example I want this
| G.Name | E.Action
| game 1 | correctAnswer
| game 1 | correctAnswer
| game 2 | correctAnswer
| game 3 | correctAnswer
| game 3 | correctAnswer
to become this
| G.Name | Count(*)
| game 1 | 2
| game 2 | 1
| game 3 | 2
the problem is that im getting this instead:
| G.Name | Count(*)
| game 1 | 5
| game 2 | 5
| game 3 | 5
where 5 is the sum of 2+1+2
This is my query
SELECT G.Name, Count(*)
FROM enduser EU
INNER JOIN prescription P
ON EU.UserRefID = P.EndUserRefID
INNER JOIN prescriptiongame PG
ON PG.PrescriptionRefID = P.PrescriptionID
INNER JOIN games G
ON G.GameID = PG.GameRefID
INNER JOIN session S
ON S.PrescriptionRefID = P.PrescriptionID
INNER JOIN entries E
ON E.SessionGameRefID = S.Session
WHERE P.EndUserRefID = 889
AND E.Action = 'correctAnswer'
GROUP BY G.Name
ORDER BY G.Name
How can I solve this issue, when I googled people are using the same method but they get good results
Thanks in advance
I'd bet money that one of your joins is inflating the result. Strip your query down to just the critical tables: prescription, session, and entries. Do you still get excessive results? If not, try adding joins back in, one at a time, until you get over-counting.
Your joins are somehow multiplying the number of rows. This happens when you join tables along different dimensions that are not related to each other. This is a common problem, but I don't understand your data structure so the following is a best-guess.
Your example can be fixed by using count(distinct) on something. So try this:
SELECT G.Name, Count(distinct SessionGameRefID)
Should there be a relationship between session and game?
I wonder if this simplification of your query would fix the problem (it removes the first two tables):
SELECT G.Name, Count(*)
FROM prescriptiongame PG
INNER JOIN games G
ON G.GameID = PG.GameRefID
INNER JOIN session S
ON S.PrescriptionRefID = PG.PrescriptionRefID
INNER JOIN entries E
ON E.SessionGameRefID = S.Session
WHERE PG.EndUserRefID = 889
AND E.Action = 'correctAnswer'
GROUP BY G.Name
ORDER BY G.Name;
supposing all the joins are needed try this query:
SELECT G.Name, Count(G.Name)
FROM enduser EU
INNER JOIN prescription P
ON EU.UserRefID = P.EndUserRefID
INNER JOIN prescriptiongame PG
ON PG.PrescriptionRefID = P.PrescriptionID
INNER JOIN games G
ON G.GameID = PG.GameRefID
INNER JOIN session S
ON S.PrescriptionRefID = P.PrescriptionID
INNER JOIN entries E
ON E.SessionGameRefID = S.Session
WHERE P.EndUserRefID = 889
AND E.Action = 'correctAnswer'
GROUP BY G.Name
ORDER BY G.Name
select G.Name , count(*) from enduser EU, prescription P,prescriptiongame PG ,
games G ,session S ,entries E where P.EndUserRefID = 889 and E.action='correctAnswer' and (EU.UserRefID = P.EndUserRefID) and (PG.PrescriptionRefID = P.PrescriptionID) and (G.GameID = PG.GameRefID) and (S.PrescriptionRefID = P.PrescriptionID) and (E.SessionGameRefID = S.Session)
GROUP BY G.Name
ORDER BY G.Name
Related
So I have 3 tables
User Table
UserId User
Language Table
LanguageId Language Fluency
User Language Table
UserLanguageId UserId LanguageId
Basically what I need is a query where PriLang would be where Fluency='Primary' and SecLang is Fluency='Secondary' and looks somethin like this
+------------+-----------------+-----------+
| User | PriLang | SecLang |
+------------+-----------------+-----------+
| Jimbo | English | Spanish |
+------------+-----------------+-----------+
| Norm | French | Spanish |
+------------+-----------------+-----------+
| Kathy | Japanese | Italian |
+------------+-----------------+-----------+
In my view, the most straightforward approach involves two joins to the user_languages table, as well as a join to the langauges table for each of them.
select usr.User, lg1.Language PriLang, lg2.Language SecLang
from users usr
left join user_languages ul1
on ul1.userId = usr.userId
and ul1.Fluency='Primary'
left join user_languages ul2
on ul2.userId = usr.userId
and ul2.Fluency='Secondary'
left join languages lg1
on lg1.languageId = ul1.languageId
left join languages lg2
on lg2.languageId = ul2.languageId
One option uses conditional aggregation:
select
u.user,
max(case when l.fluency = 'Primary' then l.language end) as pri_lang,
max(case when l.fluency = 'Secondary' then l.language end) as sec_lang
from users u
left join user_languages ul on ul.user_id = u.user_id
left join languages l on l.language_id = ul.language_id
group by u.user_id, u.user
Maybe something like this depending on your setup; this should get you close using a subquery:
SELECT u.User,
(SELECT lt.Language
FROM Language_table lt
JOIN UserLanguage_table ult ON lt.LanguageId = ult.LanguageId
JOIN User_table u ON ult.UserId = u.UserId
WHERE lt.Language_Fluency = 'primary'
AND ult.UserId = u.UserId
AND lt.LanguageId = ult.LanguageId) AS primary_lang,
(SELECT lt.Language
FROM Language_table lt
JOIN UserLanguage_table ult ON lt.LanguageId = ult.LanguageId
JOIN User_table u ON ult.UserId = u.UserId
WHERE lt.Language_Fluency = 'secondary'
AND ult.UserId = u.UserId
AND lt.LanguageId = ult.LanguageId) AS secondary_lang
FROM User_table u;
I want to fetch record associated with all values in array. but the problem is, query is fetching record if any one values in IN() is present in db . i want to fetch record ONLY if all values are true.
SELECT J.ID , J.U_POST_ID,
J.TITLE,J.CREATION_DATE,J.STATUS,
R.FIRST_NAME, R.LAST_NAME,R.CLINICAL_CLINIC_NAME,
J.REQUIREMENT,J.STATE,J.CITY,J.DESCRIPTION,
J.CALL_DUR,J.USER_ID
FROM df_job_meta M
LEFT OUTER JOIN df_job_post J ON M.JOB_ID = J.ID
LEFT OUTER JOIN df_register_users R ON R.ID = J.USER_ID
WHERE
J.STATUS='ACTIVE' AND
R.OCCUPATION !='student' AND
J.STATE IN ('Maharashtra') AND
J.CITY IN ('Nagpur') and
M.VALUE IN ('Clinical','Fresher','BDS Intern','Full Time')
table df_job_meta
---------------------------------------------
***VALUE*** | **META_KEY** | JOB_ID
--------------------------------------------
-----------------------------------------
Part Time | work_hour | 103
-------------------------------
BDS Intern |qualification | 103
----------------------------------------
Clinical |profile | 103
----------------------------------------
1 |num_vacancy | 103
----------------------------------------
1 to 3 Years |experience | 103
--------------------------------------
I think you'll need to generate some Dynamic SQL. For the set of coded values you gave:
SELECT J.ID , J.U_POST_ID,
J.TITLE,J.CREATION_DATE,J.STATUS,
R.FIRST_NAME, R.LAST_NAME,R.CLINICAL_CLINIC_NAME,
J.REQUIREMENT,J.STATE,J.CITY,J.DESCRIPTION,
J.CALL_DUR,J.USER_ID
FROM (
SELECT M1.ID
FROM df_job_meta M1
INNER JOIN df_job_meta M2 ON M1.JOB_ID = M2.JOB_ID
INNER JOIN df_job_meta M3 ON M1.JOB_ID = M3.JOB_ID
INNER JOIN df_job_meta M4 ON M1.JOB_ID = M4.JOB_ID
WHERE M1.VALUE = 'Clinical'
AND M2.VALUE = 'Fresher'
AND M3.VALUE = 'BDS Intern'
AND M4.VALUE = 'Full Time'
) as JOBS_MATCHING_META
LEFT OUTER JOIN df_job_post J ON M.JOB_ID = J.ID
LEFT OUTER JOIN df_register_users R ON R.ID = J.USER_ID
WHERE
J.STATUS='ACTIVE' AND
R.OCCUPATION !='student' AND
J.STATE IN ('Maharashtra') AND
J.CITY IN ('Nagpur')
;
(untested)
I would note that looking at your sample data for df_job_meta whether you need to be looking at the META_KEY column too - ie the value is only valid if it's for the right thing, for example
WHERE M1.META_KEY = 'qualification' AND M1.VALUE = 'BDS Intern'
As a final observation, it looks like yuo are trying to implement some form of facetted search; perhaps it might be worth looking at some alternative data stores that implement that directly?
I got these 3 tables:
fieldValues|values|formCustomizeValues |
-----------|------|--------------------|
FieldID |ID |FormCustomizeFieldID|
ValueID |Name |FieldID |
| |ValueID |
-----------|------|--------------------|
And the data on these tables looks like this:
fieldValues|values|formCustomizeValues|
-----------|------|-------------------|
4 |1 |1 |
1 |James |4 |
-----------|------|3 |
4 |2 |-------------------|
2 |Ben |
-----------|------|
|3 |
|Daniel|
What i'm trying to do is to get all the values for the specific field.
so lets say i want to grab all the values with the FieldID that equals to 4, i should get:
James
Ben
Daniel
But i tried 5 different queries and the only things i'm getting is or James, Ben or Daniel.
This is the query that returning me zero results:
SELECT v.* FROM `fieldValues` fv
LEFT JOIN `values` v ON fv.ValueID = v.ID
LEFT JOIN formCustomizeValues fcv ON fcv.FieldID = fv.FieldID AND fcv.ValueID = v.ID
WHERE fv.FieldID = 4 AND fcv.FormCustomizeFieldID = 1
And that query returning me only James, Ben:
SELECT v.* FROM `fieldValues` fv
LEFT JOIN `values` v ON fv.ValueID = v.ID
LEFT JOIN formCustomizeValues fcv ON fcv.ValueID = v.ID
WHERE fv.FieldID = 4
How can i get them all together?
Any help will be appreciated!!
Thanks!
Here is SQLfiddle link: http://sqlfiddle.com/#!2/43b56/1
This is what you want :
1 Query to retrieve names via fieldValues
1 Query to retrieve names via formCustomizeValues
Union to join both result
The query :
SELECT
v.`Name`
FROM
`values` v
INNER JOIN `fieldValues` as fv
on v.`ID` = fv.`ValueID`
and fv.`FieldID` = 4
UNION
SELECT
v.`Name`
FROM
`values` v
INNER JOIN `formCustomizeValues` as fcv
on v.`ID` = fcv.`ValueID`
and fcv.`FieldID` = 4
Here the SQLFIDDLE UPDATED
Setting aside any criticisms of the schema design…
SELECT v.name
FROM `values` v
LEFT JOIN `fieldValues` fv ON fv.ValueID = v.ID
LEFT JOIN `formCustomizeValues` fcv ON fcv.ValueID = v.ID
WHERE fv.FieldID = 4
OR fcv.FormCustomizeFieldID = 1
;
Updated Fiddle.
Update
I see now that your first query that you said resulted in no rows was actually pretty close. You want all the rows from values that are defined in either fieldValues or formCustomizeValues. Using AND results in no rows because no row meets both conditions. Therefore you want to use OR or use a UNION as Ryx5 has suggested.
SELECT v.name
FROM `values` v
LEFT JOIN `fieldValues` fv ON fv.ValueID = v.ID
LEFT JOIN `formCustomizeValues` fcv ON fcv.ValueID = v.ID
WHERE fv.FieldID = 4
OR fcv.FormCustomizeFieldID = 1
;
Updated updated Fiddle.
I'm trying to show a matrix table with the results from a vendor in a category. Like:
+-----------+-------------+-------------+------+
| | Category 1 | Category 2 | ... |
+-----------+-------------+-------------+------+
| Vendor 1 | 8900 | 0 | ... |
| Vendor 2 | 56890 | 4000 | ... |
| ... | ... | ... | ... |
+-----------+-------------+-------------+------+
I already made a query for just one vendor:
SELECT ut.unit_name, IFNULL(SUM(commission_fix_out),0)
FROM transaction t
JOIN office_per_transaction opt
ON t.id = opt.transaction_id
JOIN_vendor_per_transaction ppt
ON t.id = ppt.transaction_id
AND ppt.vendor_id = 2
RIGHT JOIN unit_type ut
ON t.unit_type_id = ut.id
AND transaction_end_week BETWEEN 0 AND 14
AND YEAR(transaction_end_date) = 2012
GROUP BY ut.id
Which gives me following result:
+-------------+---------+
| Category | Result |
+-------------+---------+
| Category 1 | 56890 |
| Category 2 | 4000 |
| ... | ... |
+-------------+---------+
Now i would like to see a concatenation of this query per vendor in a given office.
First, I tried replacing AND ppt.vendor_id = 2 with AND ppt.vendor_id IN (SELECT id FROM vendor WHERE office_id = 1) but that gave me the total result of all the vendors in that office.
Secondly, I tried using a subquery. But that gave me an error stating unknown column.
What i want to achieve is a resultset like:
+-----------+--------- -------+
| Vendor | Results |
+-----------+-----------------+
| Vendor 1 | 8900,0,... |
| Vendor 2 | 56890,4000,... |
| ... | ...,...,... |
+-----------+-----------------+
Am i trying something unrealistic and should i rather perform above query per vendor. Or am i missing something here?
#SashiKant I've tried many queries last days, but it was something like this:
SELECT v.id, GROUP_CONCAT(r.result) FROM vendor v,
( SELECT ut.unit_name, IFNULL(SUM(commission_fix_out),0) as result
FROM transaction t JOIN office_per_transaction opt ON t.id = opt.transaction_id
JOIN vendor_per_transaction ppt ON t.id = ppt.transaction_id
AND ppt.vendor_id = p.id
RIGHT JOIN unit_type ut ON unit_type_id = ut.id
AND transaction_end_week BETWEEN 0 AND 14
AND YEAR(transaction_end_date) = 2012 GROUP BY ut.id) as r
You can use group_concat.
Pseudo SQL:
select vendor, group_concat(result)
from mytable
group by vendor
You might "simplify" it by creating a view. Since I don't know your table structure, this is just guessing
create view commissions as
SELECT ppt.vendor_id as vendor, ut.unit_name as category,
IFNULL(SUM(commission_fix_out),0) as commission
FROM transaction t
JOIN office_per_transaction opt
ON t.id = opt.transaction_id
JOIN_vendor_per_transaction ppt
ON t.id = ppt.transaction_id
RIGHT JOIN unit_type ut
ON t.unit_type_id = ut.id
AND transaction_end_week BETWEEN 0 AND 14
AND YEAR(transaction_end_date) = 2012
GROUP BY ppt.vendor_id, ut.id;
and then select
select vendor, group_concat(commission)
from commissions
group by vendor;
You probably need to join against the vendors table to get the vendors you want (rather than a single vendor). Also you need more clauses in the GROUP BY (and you really should use all the non aggregate columns from the SELECT in the GROUP BY clause - mysql doesn't object but most flavours of SQL do object if you miss some out).
Something like this (not tested so please excuse any typos)
SELECT vendor_id, ut.id, ut.unit_name, IFNULL(SUM(commission_fix_out),0)
FROM transaction t
INNER JOIN office_per_transaction opt
ON t.id = opt.transaction_id
INNER JOIN_vendor_per_transaction ppt
ON t.id = ppt.transaction_id
INNER JOIN vendor ve
ON ve.id = ppt.vendor_id
RIGHT JOIN unit_type ut
ON t.unit_type_id = ut.id
AND transaction_end_week BETWEEN 0 AND 14
AND YEAR(transaction_end_date) = 2012
WHERE ve.office_id = 1
GROUP BY vendor_id, ut.id, ut.unit_name
ORDER BY vendor_id, ut.id, ut.unit_name
If you want a row per vendor with a single column for all the amounts for that vendor then something like this.
SELECT vendor_id, GROUP_CONCAT(CommisionAmount)
FROM (
SELECT vendor_id, ut.id, ut.unit_name, IFNULL(SUM(commission_fix_out),0) AS CommisionAmount
FROM transaction t
INNER JOIN office_per_transaction opt
ON t.id = opt.transaction_id
INNER JOIN_vendor_per_transaction ppt
ON t.id = ppt.transaction_id
INNER JOIN vendor ve
ON ve.id = ppt.vendor_id
RIGHT JOIN unit_type ut
ON t.unit_type_id = ut.id
AND transaction_end_week BETWEEN 0 AND 14
AND YEAR(transaction_end_date) = 2012
WHERE ve.office_id = 1
GROUP BY vendor_id, ut.id, ut.unit_name
ORDER BY vendor_id, ut.id, ut.unit_name) Sub1
I'm rather new to normalizing tables and I'm having some troubles wrapping my head around getting the correct information out of 3 tables. I made an example involving reserving books out of different libraries. I have 3 tables. Books, locations, reservations (listed below):
//SQL query:
$sql =
"SELECT * FROM books
JOIN (location LEFT JOIN reservations ON location.locID = reservations.locID)
ON books.bookID = location.bookID
WHERE location.locID=2
";
and the output I was hoping to achieve if I were to list the books in Campus B:
title |locName |status
Book 1|Campus B|1
Book 2|Campus B|0
Book 3|Campus B|0
Book 4|Campus B|0
Book 5|Campus B|1
For some reason I'm definitely not getting the output I think I should, and I was curious if anyone has some suggestions. I'm sure once I see whats going on I'll understand what I did incorrectly.
table: books
bookID|title
1 | Book 1
2 | Book 2
3 | Book 3
4 | Book 4
5 | Book 5
table: location
locID|locName
1 | campus A
2 | campus B
3 | campus C
table: reservations
bookID|locID|status
1 | 1 | 1
3 | 1 | 1
4 | 1 | 1
1 | 2 | 1
5 | 2 | 1
4 | 3 | 1
5 | 3 | 1
I think this is more in line with what you're looking for:
SELECT *
FROM books b
LEFT JOIN reservations r ON b.bookID = r.bookID
JOIN location l on r.locID = l.locID
WHERE l.locID = 2
This will return a list of the books reserved at the location with locID=2.
In this case I have a LEFT JOIN to preserve your original query, however given your WHERE clause any records with NULL in the location.locID field will not be selected.
Therefore, I could re-write your query with all INNER joins, like so:
SELECT *
FROM books b
JOIN reservations r ON b.bookID = r.bookID
JOIN location l on r.locID = l.locID
WHERE l.locID = 2
Other queries that you might find interesting:
Get ALL books, regardless of whether or not they are reserved anywhere:
SELECT *
FROM books b
LEFT JOIN reservations r ON b.bookID = r.bookID
JOIN location l on r.locID = l.locID
Get ALL locations, regardless of whether or not there are books reserved there:
SELECT *
FROM books b
JOIN reservations r ON b.bookID = r.bookID
RIGHT JOIN location l on r.locID = l.locID
Get ALL books and ALL locations:
SELECT *
FROM books b
LEFT JOIN reservations r ON b.bookID = r.bookID
RIGHT JOIN location l on r.locID = l.locID
SELECT
books.title
, location.locName
, IFNULL(reservations.status, 0) status
FROM
books
JOIN location
LEFT JOIN reservations ON (
location.locID = reservations.locID
AND books.bookID = location.bookID
)
WHERE location.locID = 2