I have these tables:
single_user_has_university_has_course
single_user_users_id_user university_has_course_university_id_university university_has_course_course_id_course first_year_school last_year_school grade
1 1 1 2000 2001 15
And
university_has_course
university_id_university course_id_course
1 1 <<< I want to select this
15 1
1 3
15 3
The problem is that the query below return all rows where course_id_course = 1 but ignore theuniversity_id_university = 1`. Then, will return two rows.
query:
SELECT A.first_year_school, A.last_year_school, A.grade, U.university, C.course, T.type_course
FROM single_user_has_university_has_course A
INNER JOIN university_has_course Q
ON A.university_has_course_course_id_course = Q.course_id_course
INNER JOIN university U
ON Q.university_id_university = U.id_university
INNER JOIN course C
ON Q.course_id_course = C.id_course
INNER JOIN type_course T
ON C.type_course_id_type_course = T.id_type_course
AND A.single_user_users_id_user = ?
You are joining the last table to the previous joins on 2 constraints C.type_course_id_type_course = T.id_type_course AND A.single_user_users_id_user = ?. I think you want to write it as a WHERE clause. So replace your last line with:
WHERE A.single_user_users_id_user = ?
But you're not also trying to filter university_id_university = 1, so you may want to add it to the WHERE clause as well:
WHERE A.single_user_users_id_user = ? AND Q.university_id_university = ?
Related
I´m trying to filter data with some categories where i get a result matching all given slug / type parameteres.
Currently i got stuck with extendending my current query to get the data with a single query. My current query looks like that:
SELECT t.slug, tc.t_id, tc.c_id
FROM tc
LEFT JOIN t ON t.id = tc.t_id
WHERE
(t.type = 'offerAges' AND t.slug = '14-16')
OR
(t.type = 'offerSportTypes' AND t.slug = 'football')
Gives me following result:
# slug t_id c_id
1 football 13 40
2 14-16 28 39
3 14-16 28 40
The result i want is that i just get the results where t_id AND c_id are matching. For example in my table the items 1 & 3.
Fiddle: https://www.db-fiddle.com/f/vQUU9C9iXj4gotE7YGDq6W/1
You can use aggregation. In this case:
SELECT tc.c_id
FROM tc JOIN
t
ON t.id = tc.t_id
WHERE (t.type = 'offerAges' AND t.slug = '14-16') OR
(t.type = 'offerSportTypes' AND t.slug = 'football')
GROUP BY tc.c_id
HAVING COUNT(DISTINCT t.type) = 2;
If you want the slugs, I would recommend using GROUP_CONCAT() to put them in a single column:
GROUP_CONCAT(t.slug)
A have a table called advert_property
And I have a table advert, which is not important, advert properties connects to advert by advert_id column in advert_property table.
I wrote this SQL request :
SELECT *
FROM `advert`
JOIN advert_property ON advert.id = advert_property.advert_id
WHERE (advert_property.property_id = 1
AND advert_property.property_value = "Манчего")
AND (advert_property.property_id = 2
AND advert_property.property_value = "козий")
What I want to get, is advert that have certain properties, for example : I want an idvert that have property_id = 1 and property_value = "Манчего" AND have property_id = 2 and property_value = "козий". SQL request returns null, how should I change my SQL request. Thanks!
Assuming I'm understanding your question correctly and you want to return all adverts that have both properties, then there are a couple ways of doing this using multiple joins, exists, in, group by...
Here is the method using multiple joins:
SELECT a.*
FROM `advert` a
JOIN advert_property ap ON a.id=ap.advert_id
AND ap.property_id = 1 AND ap.property_value = 'Манчего'
JOIN advert_property ap2 ON a.id=ap2.advert_id
AND ap2.property_id = 2 AND ap2.property_value = 'козий'
You can't return all columns * where the property_id is both 1 and 2 because a record can't have two values for the same field. You can, however, return records where the property_id is 1 OR 2. You could then have it only return DISTINCT advert_id where this is true:
SELECT DISTINCT advert_id
FROM `advert` JOIN advert_property ON advert.id=advert_property.advert_id
WHERE (advert_property.property_id = 1 AND advert_property.property_value = "Манчего")
OR (advert_property.property_id = 2 AND advert_property.property_value = "козий")
Query which you are trying to execute will never give you a result because it is trying to get a row with property id = 1 and property id = 2
For same row, there will never be two property_ids (1,2).
You need to review your where conditions.
My be what you need in where condition is as below(Either id will be 1 or id will be 2):
Try this :
(advert_property.property_id = 1 AND advert_property.property_value = "Манчего")
OR
(advert_property.property_id = 2 AND advert_property.property_value = "козий")
SELECT dieet.snr, soort.nsnaam FROM soort
JOIN dieet ON soort.snr = dieet.snr
JOIN voedsel ON dieet.voednr = voedsel.voednr
WHERE voedsel.voednr = 22
GROUP BY dieet.snr
HAVING COUNT(*) = 1 ;
the where condition messes up my output, what am i doing wrong
I suspect that you are looking for "snr"s that have exactly one record that is a "voednr = 22". Your query is getting all "snr"s that have exactly one such "voednr", along with other "voednr"s.
Let me suggest the following query:
SELECT dieet.snr, soort.nsnaam
FROM soort
JOIN dieet ON soort.snr = dieet.snr
JOIN voedsel ON dieet.voednr = voedsel.voednr
GROUP BY dieet.snr
HAVING COUNT(*) = 1 and max(voedsel.voednr) = 22
This will get you the rows with the one and only 22.
I am new to complex SQL statements and need help.
I have managed to display half of the result set and struggling with remaining.
Result required:
PSU | pregnancy number| pregnancy percentage | % of live birth out of the pregnancy number.
1 | 2 | 67% | 40%
2 | 1 | 33% | 80%
With the sql written below , I have managed to get the first 3 columns.
The 2nd and the 3rd columns required where statement of fieldname = 'Q111'. While the 4th column requires percentage with where statement of fieldname = 'Q112.
How do I combine different where statements together.
SELECT sms_psu.name1 AS PSU,
woman_data.answertext AS NumberOfPreg,
Count(woman_data.answertext) / (SELECT Count(woman_data.answertext)
FROM woman_data
INNER JOIN sms_household
ON woman_data.prim_key =
ms_household.hhid
INNER JOIN sms_psu
ON sms_psu.psu =
sms_household.psu
WHERE sms_psu.state = 19
AND sms_psu.district = 1
AND sms_psu.psu = 2
AND fieldname = 'Q139') AS
totalcpuntpreg
FROM woman_data
INNER JOIN sms_household
ON woman_data.prim_key = sms_household.hhid
INNER JOIN sms_psu
ON sms_psu.psu = sms_household.psu
WHERE sms_psu.state = 19
AND sms_psu.district = 1
AND sms_psu.psu = 2
AND fieldname = 'Q111'
GROUP BY woman_data.answertext,
sms_household.psu
Gordon,Your suggestion helped me a lot.I updated my query accordingly.The issue that i am having write now is that iam getting an additional row for Q112
PSU | pregnancy number| pregnancy percentage | % of live birth out of the pregnancy number.
1 | 2 | 67% | 40%
2 | 1 | 33% | 80%
2 | 1 | 0% | 20% (3rd row is additional for Q112)
But I do not require the Q112 entry while i do group by. Can i use group by in case statements and in main where statement separately ? I tried using "having " with group by but dint get expected result.
Maybe something like this:
SELECT sms_psu.name1 AS PSU,
woman_data.answertext AS NumberOfPreg,
SUM(fieldname = 'Q111') / SUM(fieldname = 'Q139') AS pregnancyPercentage,
SUM(fieldname = 'Q112') / SUM(fieldname = 'Q139') AS liveBirthPercentage
FROM woman_data
INNER JOIN sms_household
ON woman_data.prim_key = sms_household.hhid
INNER JOIN sms_psu
ON sms_psu.psu = sms_household.psu
WHERE sms_psu.state = 19
AND sms_psu.district = 1
AND sms_psu.psu = 2
GROUP BY woman_data.answertext,
sms_household.psu
HAVING SUM(fieldname = 'Q111') > 0
The query first retrieves rows with all fieldname values and groups them same as before. When counting, only specific fieldname entries are counted (using the SUM(condition) trick) as necessary. To make sure that the output contains only groups that have rows with fieldname = 'Q111', the SUM(fieldname = 'Q111') > 0 condition was added (as a HAVING clause).
Your query is, as you mentioned, complex. It's hard for somebody unfamiliar with your schema to make sense of it. So I will offer a general suggestion for queries that summarize multiple items.
Use a decent client program that lets you save query text. If it also prettyprints (formats) your query text that is helpful.
Develop and test each summary query separately. Make sure each one, standing alone, produces the correct summary result you need from it.
Then, join those queries together on the reporting key (PSU in your case I believe) so it produces the multiple summary results. Make sure it is working.
Put a query name and version number in a comment right after the SELECT statement: for example,
SELECT /* pregnancy outcomes 1.1 */
sms_psu.name1 AS PSU,
woman_data.answertext AS NumberOfPreg, etc.
This will let you use the MySQL SHOW FULL PROCESSLIST to figure out which exact queries are running.
Finally, if the result query (consisting of lots of nested subqueries) is too slow for your application's requirements, optimize it.
If you follow these steps, your next step is to develop your % live birth summary query, I believe.
The answer to your question is: the CASE statement.
The idea is to extend the outer WHERE clause to include all rows you care about. Then, use a CASE statement in the SELECT clause to filter the rows, on a single variable basis.
I tried to put this together as:
SELECT sms_psu.name1 AS PSU,
woman_data.answertext AS NumberOfPreg,
Count(case when sms_psu.state = 19 AND sms_psu.district = 1 AND sms_psu.psu = 2 AND fieldname = 'Q111'
then woman_data.answertext
end) /
(SELECT Count(woman_data.answertext)
FROM woman_data INNER JOIN
sms_household
ON woman_data.prim_key = ms_household.hhid INNER JOIN
sms_psu
ON sms_psu.psu = sms_household.psu
WHERE sms_psu.state = 19 AND sms_psu.district = 1 AND sms_psu.psu = 2 AND
fieldname = 'Q139'
) AS totalcpuntpreg,
Count(case when sms_psu.state = 19 AND sms_psu.district = 1 AND sms_psu.psu = 2 AND fieldname = 'Q112'
then woman_data.answertext
end) /
(SELECT Count(woman_data.answertext)
FROM woman_data INNER JOIN
sms_household
ON woman_data.prim_key = ms_household.hhid INNER JOIN
sms_psu
ON sms_psu.psu = sms_household.psu
WHERE sms_psu.state = 19 AND sms_psu.district = 1 AND sms_psu.psu = 2 AND
fieldname = 'Q139'
) AS totalcpuntpreg
FROM woman_data INNER JOIN
sms_household
ON woman_data.prim_key = sms_household.hhid INNER JOIN
sms_psu
ON sms_psu.psu = sms_household.psu
WHERE sms_psu.state = 19 AND sms_psu.district = 1 AND sms_psu.psu = 2 AND
fieldname in ('Q111', 'Q112')
GROUP BY woman_data.answertext
sms_household.psu
However, I might have missed some details.
I'm trying to find number of rows for two tables:
Example 1 returns 81 (which is wrong).
SELECT p_id FROM j_posts
INNER JOIN j_blogs ON p_blog_id = b_id && b_approved = 1
WHERE p_is_draft = 0
UNION SELECT ep_id FROM j_external_posts
INNER JOIN j_blogs ON ep_blog_id = b_id && b_approved = 1
I have then tried to split up the query in two:
SELECT ep_id FROM j_external_posts INNER JOIN j_blogs ON ep_blog_id = b_id
&& b_approved = 1
First part of the query returns 70, and the second returns 39. This is the right amount of rows.
SELECT p_id FROM j_posts INNER JOIN j_blogs ON p_blog_id = b_id
&& b_approved = 1 WHERE p_is_draft = 0
What am I doing wrong in Example 1? It should return 109 instead of 81.
Thanks in advance
Use UNION ALL, UNION would return distinct rows
I think you must say "UNION ALL" instead of UNION.
UNION Does a implicit DISTINCT so same values are displayed only once..