I am getting from the below query
SELECT co.mobility_theme, COUNT(DISTINCT ca.user_id) AS n
FROM courses_apply AS ca LEFT JOIN dy41s_courses AS co ON ca.course_id = co.id
WHERE ca.submission IS NULL AND ca.`call` LIKE '1b'
GROUP BY co.mobility_theme
ORDER BY co.mobility_theme ASC
The below result total (133)
mobility_theme n
1 =>70
4 =>18
5 =>45
What I want to do is: for each mobility theme (1,2 and 5), I have repeated users, so the total unique user_id should be (130), I cannot manage to get unique user_id group by (mobility theme), any help?
One approach is to arbitrarily choose one of the mobility themes. This method chooses the one with the minimum value:
select mobility_theme, COUNT(*) as Numusers
from (select ca.user_id, MIN(co.mobility_theme) as mobility_theme
from courses_apply ca LEFT JOIN
dy41s_courses co
ON ca.course_id = co.id
WHERE ca.submission IS NULL AND ca.`call` LIKE '1b'
group by ca.user_id
) caco
group by mobility_theme
Related
I've got a query with avg results. In another table I have the results of that
avg result in text.
Right now this is my query:
select round(avg(breed_ratings.rating)) as result, breed_ratings.score_name, count(*) as total, breeds.name_en
from breed_ratings
inner join breeds on breeds.id = breed_ratings.breed_id
where breeds.id = 188
group by score_name, breeds.name_en
The rating_result table looks like this:
id
rating
result_text
How can I get the result_text in this query?
Please help me out.
--EDIT
I need to get the result from the image below in text.
So I have another table where this is stored I need to get the result_nl where it matches the rating:
Desired result (if rating is 5):
result: 5
score_name: ADULT_FRIENDLY
total: 117
name_en: American Staffordshire Terrier
result_nl: I am extremely dominant
I think you want to join the average to the first rating in rating_results where the average is bigger than the listed rating there. If so:
select br.*, rr.result_text
from (select round(avg(br.rating)) as result, br.score_name, count(*) as total, b.name_en
from breed_ratings br join
breeds b
on b.id = br.breed_id
where b.id = 188
group by br.score_name, b.name_en
) br left join
(select rr.*, lead(rr.rating) over (order by rr.rating) as next_rating
from rating_result rr
) rr
on br.result >= rr.rating and
(br.result < rr.next_rating or rr.next_rating is null)
My query does return the lowest price from the two columns (price_base, price_special) but it is not returning the correct store_id that corresponds to the lowest price found.
My Query:
SELECT grocery_item.id, grocery_item.category,
grocery_category.name AS cat, grocery_item.name AS itemName,
MIN( if( grocery_price.price_special>0,
grocery_price.price_base)) AS price,
grocery_price.store_id,
grocery_store.name AS storeName
FROM grocery_item
LEFT JOIN grocery_category ON
grocery_category.id=grocery_item.category
LEFT JOIN grocery_price
ON grocery_price.item_id = grocery_item.id
LEFT JOIN grocery_store
ON grocery_store.id=grocery_price.store_id
WHERE grocery_price.selection='no'
AND buy='yes'
GROUP BY grocery_price.item_id
ORDER BY store_id, grocery_item.category, grocery_item.name
Returns this:
ID category cat itemName price store_id storeName
92 3 Bread/Bakery Arnold Bread 2.14 1 Food Lion
But the grocery_price table holds this info:
item_id price_base price_special store_id
92 4.29 2.14 9
92 3.99 0.00 1
so the store_id I need to be returned is 9 (the storeName returned would NOT then be Food Lion)
EDIT: WORKING QUERY based on Uueerdo's comments (thank you!)
SELECT minP.item_id, gi.category, gc.name AS cat,
gi.name as itemName, gp.store_id,
gs.name AS storeName, minP.price
FROM
(SELECT p.item_id, MIN(IF(p.price_special >0,
p.price_special,p.price_base)) AS price
FROM grocery_item AS i
INNER JOIN grocery_price AS p ON (i.id = p.item_id)
WHERE i.buy = 'yes'
GROUP BY p.item_id) AS minP
INNER JOIN grocery_item AS gi ON minP.item_id = gi.id
INNER JOIN grocery_category AS gc on gi.category = gc.id
LEFT JOIN grocery_price AS gp
ON minP.price = IF(gp.price_special > 0,
gp.price_special,gp.price_base)
AND gp.item_id = gi.id
INNER JOIN grocery_store AS gs ON gp.store_id = gs.id
GROUP BY gi.id
ORDER BY gs.id, gi.category,gi.name
The values returned for non-grouped, non-aggregated fields are an (effectively) random selection from the values encountered with the grouped fields' values. Most RDBMS do not even consider such a query valid, and even newer versions of MySQL default to disallowing such queries.
In cases like yours, where you need the non-grouped value(s) associated with the aggregate result (min in this case); the aggregating query must be converted into a subquery, that can be joined back to the aggregated tables to find the source row(s) that correspond to the aggregated value.
Edit: Basically, you need to look at the problem slightly differently. You're currently finding the lowest price for an item and a store that item is listed for; you need to find the lowest price for an item, and use that to find the store(s) that have the item at that price.
This gets you the lowest price for item's marked "buy":
SELECT p.item_id, MIN(IF(p.price_special > 0,p.price_special,p.price_base)) AS price
FROM grocery_item AS i
INNER JOIN grocery_price AS p ON (i.id = p.item_id)
WHERE i.buy = 'yes'
GROUP BY p.item_id
You can then take that to get the rest of the results:
SELECT minP.item_id
, gi.name
, gi.category, gc.category_name AS cat, gi.Name as itemName, gi.buy
, gp.store_id, gp.name AS storeName
, minP.price
FROM ([the query above]) AS minP
INNER JOIN grocery_item AS gi ON minP.item_id = gi.id
INNER JOIN grocery_category AS gc on gi.category = gc.grocery_category_id
/* Guessing on this join since grocery_category_id
was not qualified with it's table name */
INNER JOIN grocery_price AS gp
ON minP.price = IF(gp.price_special > 0,gp.price_special,gp.price_base)
/* Alternatively: ON minP.price IN (gp.price_special, gp.price_base)
... though this could cause false positives if the minP.price is 0
from one store's base price being "free"
*/
INNER JOIN grocery_store AS gs ON gp.store_id = gs.id
;
Query with OR which outputs wrong
SELECT DISTINCT
sm___employees.id,
sm___employees.employee_code,
sm___employees.leaving_date,
sm___employees.name_of_employee,
sm___employees.position,
sm___employees.rating,
sm___employees.entry_date
FROM
sm___employees
JOIN
sm___employee_skills
ON
sm___employees.id=sm___employee_skills.employee_id
WHERE
((sm___employee_skills.skill_id=1 AND sm___employee_skills.ans LIKE '%MBA%')
**OR**
(sm___employee_skills.skill_id=5 AND sm___employee_skills.ans IN (3)))
AND
sm___employees.rating IN (1)
ORDER BY
sm___employee_skills.date DESC
But I want it by And
SELECT DISTINCT
sm___employees.id,
sm___employees.employee_code,
sm___employees.leaving_date,
sm___employees.name_of_employee,
sm___employees.position,
sm___employees.rating,
sm___employees.entry_date
FROM
sm___employees
JOIN
sm___employee_skills
ON
sm___employees.id=sm___employee_skills.employee_id
WHERE
((sm___employee_skills.skill_id=1 AND sm___employee_skills.ans LIKE '%MBA%')
**AND**
(sm___employee_skills.skill_id=5 AND sm___employee_skills.ans IN (3)))
AND
sm___employees.rating IN (1)
ORDER BY
sm___employee_skills.date DESC
When am using first query with OR of MBA or 3, It gives me result for both which is correct as per OR operation
I want only those records which are having MBA AND 3 which gives me blank records when there are records available with this comparison
So please help me to resolve this.
Thank you in advance
To start with: DISTINCT often indicates a badly written query. This is the case here. You are joining records only to dismiss them later. If you want employee records, then select from the employee table. If you have criteria on the skills table check this in the WHERE clause. Don't join.
Then the WHERE clause looks at one row at a time. So neither skill_id = ... AND skill_id = ... nor skill_id = ... OR skill_id = ... can work for you. You must look up the skills table twice:
SELECT
id,
employee_code,
leaving_date,
name_of_employee,
position,
rating,
entry_date
FROM sm___employees
WHERE rating IN (1)
AND id IN
(
SELECT employee_id
FROM sm___employee_skills
WHERE skill_id = 1 AND ans LIKE '%MBA%'
)
AND id IN
(
SELECT employee_id
FROM sm___employee_skills
WHERE skill_id = 5 AND ans IN (3)
);
And here is a way to look up skills just once:
SELECT
id,
employee_code,
leaving_date,
name_of_employee,
position,
rating,
entry_date
FROM sm___employees
WHERE rating IN (1)
AND id IN
(
SELECT employee_id
FROM sm___employee_skills
WHERE (skill_id = 1 AND ans LIKE '%MBA%')
OR (skill_id = 5 AND ans IN (3))
GROUP BY employee_id
HAVING COUNT(DISTINCT skill_id) = 2 -- both skills
);
It seems strange though that you consider ans to be a string in one place (ans LIKE '%MBA%') and a number in another (ans IN (3)).
UPDATE: If you want to sort by skill date, you should consider by which skill's date. For this to happen, you would join, but not join the skills table, but the skills aggregate result. E.g.:
SELECT
e.id,
e.employee_code,
e.leaving_date,
e.name_of_employee,
e.position,
e.rating,
e.entry_date
FROM sm___employees e
JOIN
(
SELECT employee_id, MAX(date) AS max_date
FROM sm___employee_skills
WHERE (skill_id = 1 AND ans LIKE '%MBA%')
OR (skill_id = 5 AND ans = 3)
GROUP BY employee_id
HAVING COUNT(DISTINCT skill_id) = 2 -- both skills
) s ON s.employee_id = e.id
WHERE e.rating = 1
ORDER BY s.max_date;
Please try this :
SELECT DISTINCT
sm1.id,
sm1.employee_code,
sm1.leaving_date,
sm1.name_of_employee,
sm1.position,
sm1.rating,
sm1.entry_date
FROM sm___employees sm1
LEFT JOIN sm___employee_skills sm2 ON sm1.id = sm2.employee_id
WHERE ((sm2.skill_id=1 AND sm2.ans LIKE '%MBA%')
AND (sm2.skill_id=1 AND sm2.ans=3))
AND sm1.rating IN (1)
ORDER BY sm2.date DESC;
I am having issue with my query having both SUM and GROUP_CONCAT function.
The sum values changes as GROUP_CONCAT values increases.
Below is my code:
SELECT ul.display_name,
ul.photo,
ul.user_id,
Sum(ulr.level_score) AS level_scores,
Sum(ulr.level_timer) AS level_timer,
Group_concat(ulr.level_completed) AS levels,
Group_concat(DISTINCT c.bit_id) AS bit_id
FROM user_level_responses AS ulr
INNER JOIN user_login AS ul
ON (
ul.user_id=ulr.user_id)
INNER JOIN c_member AS cm
ON (
cm.user_id=ul.user_id
AND cm.user_approval='Y'
AND cm.delete_status='0'
AND cm.status='1')
INNER JOIN ctree ct
ON (
cm.circuit_id=ct.circuit_id )
INNER JOIN cir AS c
ON (
c.circuits_id=cm.circuit_id
AND c.builtin=0
AND c.delete_status='0'
AND c.status='1')
WHERE Match(ct.circuit_path) against ('_902_')
AND ulr.institution_id=321
AND ulr.delete_status=0
AND ulr.status=1
AND ul.delete_status=0
GROUP BY ulr.user_id
ORDER BY level_scores DESC,
level_timer ASC,
ul.display_name limit 500
If the actual score is 900 and if i have 2 ids in GROUP_CONCAT then actual score is double the original.
Expected OUTPUT:
user1 2010.cs,btech 960 00:01:08 Completed
user2 btech 920 00:01:08 Completed
OUTPUT GETTING:
user1 2010.cs,btech 1920 00:01:08 Completed
user2 btech 920 00:01:08 Completed
twice the actual amount ie 960.
Your problem is that your multiple ids are doubling the rows that your result has before the grouping. You can solve this problem by joining in all of the external data in a subquery.
I have absolutely no idea the structure of your database, nor all of the functions, but this is a stab in the dark at reorganizing your query. If you need, I can write up a much simpler SQLFiddle to show you what I mean.
SELECT ul2.display_name,
ul2.photo,
ul2.user_id,
Sum(ulr.level_score) AS level_scores,
Sum(ulr.level_timer) AS level_timer,
Group_concat(ulr.level_completed) AS levels,
ul2.bit_id
FROM user_level_responses AS ulr
INNER JOIN (
SELECT
ul.display_name,
ul.photo,
ul.user_id,
GROUP_CONTACT(DISTINCT c.bit_id) as bit_id
FROM user_login AS ul
INNER JOIN c_member AS cm
ON (
cm.user_id=ul.user_id
AND cm.user_approval='Y'
AND cm.delete_status='0'
AND cm.status='1')
INNER JOIN ctree ct
ON (
cm.circuit_id=ct.circuit_id )
INNER JOIN cir AS c
ON (
c.circuits_id=cm.circuit_id
AND c.builtin=0
AND c.delete_status='0'
AND c.status='1')
WHERE Match(ct.circuit_path) against ('_902_')
AND ul.delete_status=0
GROUP BY ul.user_id
) AS ul2
ON (
ulr.user_id = ul2.user_id )
WHERE ulr.institution_id=321
AND ulr.delete_status=0
AND ulr.status=1
GROUP BY ulr.user_id
ORDER BY level_scores DESC,
level_timer ASC,
ul.display_name limit 500
I have to do a query without using views that displays the automobile brand that has the maximum number of cars that have a single owner.
that's the table that I have
CAR(idcar, brand, name, year_p)
OWNER(idowner,name, b_date)
PROPERTY(idcar,idowner,date_b, date_s)
That's what I was writing..
SELECT Car.brand, COUNT(PROPERTY.idowner) as con
FROM PROPERTY JOIN CAR ON Car.idcar=Property.idcar
GROUP BY Car.brand
ORDER BY con ASC
LIMIT 1;
It's ok? what I can do to improve it?
That's how it should work
CAR
-----------------
1|FIAT|test1|2000
2|Alfa|test2|2011
3|FIAT|test3|2001
4|Alfa|test4|2006
5|Alfa|test5|2004
OWNER
-----------
1|John|1990
2|Jack|1980
3|Sam |1991
4|Rick|1980
5|Cris|1993
6|Holm|1992
PROPERTY
-------------
1|1|2000|2000
2|1|2001|2003
3|2|2000|2004
1|3|2002|2005
4|4|2004|2006
5|6|2003|2008
2|5|2001|2009
So the query should return Alfa because I've 3 people that have only one car and those 3 people have one alfa ( so 3 alfa). It can't be FIAT because I only have 2 people with only one car that is a FIAT(so 2 FIAT). The OWNER n1 is excluded because he has 2 car
I think you were on the right path with your query, it's only need a little modification...
First if you want to select brand with most owner than you should order them in descending order so the max will be at the top... And second you need to add WHERE clause which will exclude all owner that have more then one car...
It should look like this:
SELECT c.brand, COUNT(p.idowner) as con
FROM PROPERTY p
JOIN CAR c
ON c.idcar=p.idcar
WHERE p.idowner NOT IN (SELECT idowner
FROM (SELECT idowner, COUNT(idowner) as c
FROM PROPERTY
GROUP BY idowner) x
WHERE c > 1)
GROUP BY c.brand
ORDER BY con DESC
LIMIT 1;
Here is the SQL Fiddle to take a look how it's work...
GL!
This is too long for a comment.
Your query is not correct. It returns the brands that have the most properties for its cars. That may or may not have to do with the number of owners. I'm sure there's a relationship of some sort ("no properties" --> "no owners" and vice versa).
In any case, I don't know what you mean by "the maximum number of cars that have a single owner". You should edit your question with sample data and desired results. A SQL Fiddle would also be helpful.
--CTE to Get single owner
WITH CTEsingleowner(ct, idowner)
AS (SELECT Count(1) AS ct,
idowner
FROM property WITH(nolock)
GROUP BY idowner
HAVING Count(1) = 1)
-- Select brand with maximum number of single owner
-- with ties is used to resolve confilict more than one record set returned
SELECT TOP (1) WITH ties Count(1) AS cnt,
brand
FROM CTEsingleowner ct
JOIN property p WITH(nolock)
ON p.idowner = ct.idowner
JOIN car c WITH(nolock)
ON ( c.idcar = p.idcar )
GROUP BY brand
ORDER BY cnt DESC ;
--CTE to Get single owner
WITH CTEsingleowner(ct, idowner)
AS (SELECT Count(1) AS ct,idowner
FROM property WITH(nolock)
GROUP BY idowner
HAVING Count(1) = 1)
-- Select brand with maximum number of single owner
-- with ties is used to resolve conflict more than one rows returned
SELECT TOP (1) WITH ties Count(1) AS cnt, brand
FROM CTEsingleowner ct
JOIN property p WITH(nolock)
ON p.idowner = ct.idowner
JOIN car c WITH(nolock)
ON ( c.idcar = p.idcar )
GROUP BY brand
ORDER BY cnt DESC ;