SQL - Issue with Having and Grouping - mysql

Hi I'm having an issue with a query that was once working. My SQL skills aren't all that great, not sure what I'm missing. Or if this is the correct approach. Maybe use a temp table instead?
The basic gist is given a certain time frame, I need to calculate the highest aggregate of points over 5 classes.
trialScores - keeps scores/points,
trials, dog, people and member tables are just meta data
classId 5 requires a different date range
Here is my Query on MySQL
select
t.id,
d.id,
p.id,
p.firstname,
p.lastname,
d.id dogId,
d.dogName,
c.id,
c.class,
t.trialStartDate,
s.points,
if(c.id = 5, '2012-08-01', '2012-11-18') as startDate,
if(c.id = 5, '2013-07-31', '2013-12-31') as endDate,
SUM(ts.points) AS pointsAggregate
from trialScores ts
inner join trials t on t.id = ts.trialId
inner join dogs d on d.id = ts.dogId
inner join people p on p.id = ts.personId
inner join classes c on c.id = ts.classId
where t.deletedAt is null
and ts.deletedAt is null
and ts.memberAtTrial = 1
and d.omitFromTripleCrownDOY = 0
and t.associationId = 1
GROUP BY p.id, ts.dogId, ts.classId
having t.trialStartDate between startDate and endDate
order by ts.classId, pointsAggregate desc
Looks like this fixed it, too much in the select and not in Group by?:
select
d.dogName,
c.class,
p.firstName,
p.lastName,
SUM(ts.points) AS pointsAggregate
from trialScores ts
inner join trials t on t.id = ts.trialId
inner join dogs d on d.id = ts.dogId
inner join people p on p.id = ts.personId
inner join classes c on c.id = ts.classId
where t.deletedAt is null
and ts.deletedAt is null
and ts.memberAtTrial = 1
and d.omitFromTripleCrownDOY = 0
and t.associationId = 1
and t.trialStartDate between if(c.id = 5, '2012-08-01', '2012-11-18') and if(c.id = 5, '2013-07-31', '2013-12-31')
GROUP BY ts.dogId, ts.classId
order by ts.classId, pointsAggregate desc

Can you try below query and let if it's work or not ?
select
d.dogName,
c.class,
p.firstName,
p.lastName,
SUM(ts.points) AS pointsAggregate
from trialScores ts
inner join trials t on t.id = ts.trialId
inner join dogs d on d.id = ts.dogId
inner join people p on p.id = ts.personId
inner join classes c on c.id = ts.classId
where t.deletedAt is null
and ts.deletedAt is null
and ts.memberAtTrial = 1
and d.omitFromTripleCrownDOY = 0
and t.associationId = 1
and t.trialStartDate between if(c.id = 5, '2012-08-01', '2012-11-18') and if(c.id = 5, '2013-07-31', '2013-12-31')
GROUP BY ts.classId,p.firstName,p.lastName
order by ts.classId, pointsAggregate desc

Related

Extracting latest version of articles from the results of a previous query

I have the following query:
SELECT e_c.*, c.name, j.status, j.version, j.articleId, j.title FROM assetcategory AS c
INNER JOIN assetentries_assetcategories AS e_c
ON c.categoryId = e_c.categoryId AND c.name = 'news'
INNER JOIN assetentry AS e
ON e.entryId = e_c.entryId
INNER JOIN journalarticle AS j
ON j.resourcePrimKey = e.classPK
AND e.classNameId = (SELECT classNameId FROM classname_ WHERE value = 'com.liferay.portlet.journal.model.JournalArticle')
AND j.companyId= e.companyId
WHERE j.status = 0
which returns all the category news in the journalarticles. From the results I need to select the most recent versions for each articleId. For example suppose there is an article with 4 versions, even with different title, it is the same article because it will have the same articleId. So therefore for each unique articleId I need the latest version. How can I do that?
Add a join to a subquery which finds the most recent version for each article:
SELECT e_c.*, c.name, j1.status, j1.version, j1.articleId, j1.title
FROM assetcategory AS c
INNER JOIN assetentries_assetcategories AS e_c
ON c.categoryId = e_c.categoryId AND c.name = 'news'
INNER JOIN assetentry AS e
ON e.entryId = e_c.entryId
INNER JOIN journalarticle AS j1
ON j1.resourcePrimKey = e.classPK AND
e.classNameId = (SELECT classNameId FROM classname_
WHERE value = 'com.liferay.portlet.journal.model.JournalArticle') AND
j.companyId = e.companyId
INNER JOIN
(
SELECT articleId, MAX(version) AS max_version
FROM journalarticle
WHERE status = 0
GROUP BY articleId
) j2
ON j1.articleId = j2.articleId AND j1.version = j2.max_version;
The basic idea behind the join to the subquery aliased as j2 above is that it restricts the result set to only the most recent version of each article. We don't necessarily have to change the rest of the query.

SQL orderby select

i have SQL query. I would like to orderby this by parent category. But i return only default category. I would like to know if i can
ORDER BY SELECT id_parent FROM cats WHERE id_category = id_default_category
Here is my query :
SELECT cp.`id_product_attribute`,
cp.`id_product`, cp.`quantity` AS cart_quantity,
cp.id_shop, pl.`name`,
p.`is_virtual`,
pl.`description_short`,
pl.`available_now`,
pl.`available_later`,
product_shop.`id_category_default`,
p.`id_supplier`,
p.`id_manufacturer`,
product_shop.`on_sale`,
product_shop.`ecotax`,
product_shop.`additional_shipping_cost`,
product_shop.`available_for_order`,
product_shop.`price`,
product_shop.`active`,
product_shop.`unity`,
product_shop.`unit_price_ratio`,
stock.`quantity` AS quantity_available,
p.`width`,
p.`height`,
p.`depth`,
stock.`out_of_stock`,
p.`weight`,
p.`date_add`,
p.`date_upd`,
IFNULL(stock.quantity, 0) as quantity,
pl.`link_rewrite`,
cl.`link_rewrite` AS category,
CONCAT(LPAD(cp.`id_product`, 10, 0),
LPAD(IFNULL(cp.`id_product_attribute`, 0), 10, 0),
IFNULL(cp.`id_address_delivery`, 0)) AS unique_id,
cp.id_address_delivery,
product_shop.advanced_stock_management,
ps.product_supplier_reference supplier_reference
FROM `ps_cart_product` cp
LEFT JOIN `ps_product` `p` ON p.`id_product` = cp.`id_product`
INNER JOIN `ps_product_shop` product_shop ON (product_shop.`id_shop` = cp.`id_shop` AND product_shop.`id_product` = p.`id_product`)
LEFT JOIN `ps_product_lang` `pl` ON p.`id_product` = pl.`id_product`
AND pl.`id_lang` = 1 AND pl.id_shop = cp.id_shop
LEFT JOIN `ps_category_lang` `cl` ON product_shop.`id_category_default` = cl.`id_category`
AND cl.`id_lang` = 1 AND cl.id_shop = cp.id_shop
LEFT JOIN `ps_product_supplier` `ps` ON ps.`id_product` = cp.`id_product` AND ps.`id_product_attribute` = cp.`id_product_attribute` AND ps.`id_supplier` = p.`id_supplier`
LEFT JOIN ps_sanishopstock_available stock
ON (stock.id_product = cp.id_product AND stock.id_product_attribute = IFNULL(`cp`.id_product_attribute, 0) AND stock.id_shop = 1 AND stock.id_shop_group = 0 )
WHERE cp.`id_cart` = 757
ORDER BY product_shop.id_category_default ASC, cp.id_product, cp.date_add ASC;
There is a lot of different table, i'm lost !
If someone have any idea.
Thanks a lot !
Yes. But like any subquery, you need parentheses:
ORDER BY (SELECT c.id_parent FROM cats c WHERE id_category = id_default_category)
I would also qualify the column names in the WHERE, but I don't know where they come from.

MySQL: JOIN multiple tables

I have the following query I am trying to join 2 tables (' Industry' , 'Country' ) on 2 conditions, but it gives me the following error
Error Code: 1054. Unknown column 'i.id' in 'on clause'
Does anybody know how should I tackle this?
SELECT c.name AS country_name, i.name as industry_name, num_projects, num_consultants, admin_rating
FROM industry i, country c
JOIN (SELECT pc.country_id, pi.industry_id, COUNT(p.id) AS num_projects
FROM project p, project_country pc, project_industry pi
where p.id = pc.project_id and pi.project_id=p.id
GROUP BY pc.country_id,pi.industry_id) x ON x.country_id = c.id and x.industry_id=i.id
JOIN (SELECT u.country_id,ie.industry_id, COUNT(u.id) AS num_consultants
FROM user u, consultant_profile, industry_experience ie
WHERE u.is_active = 1 AND u.type = 0 and
ie.consultant_profile_id= consultant_profile.id
and u.id= consultant_profile.id
GROUP BY u.country_id,ie.industry_id) y ON y.country_id = c.id and y.industry_id = i.id order by num_projects DESC limit 20;
EDIT the table structure is as following:
industry - id
project_industry - industry_id, project_id
industry_experience - consultant_profile_id, industry_id
consultant_profile - id,user_id
Since you still did not provide any sql fiddle
you can start from my one:
http://sqlfiddle.com/#!9/6c0569/1
SELECT pc.country_id, pi.industry_id,
COUNT(p.id) AS num_projects,
COUNT(u.id) AS num_consultants
FROM project p
INNER JOIN project_country pc
ON p.id = pc.project_id
INNER JOIN project_industry pi
ON pi.project_id=p.id
INNER JOIN `user` u
ON u.is_active = 1 AND u.type = 0
and u.country_id = pc.country_id
INNER JOIN industry_experience ie
ON u.id = ie.consultant_profile_id
AND ie.industry_id = pi.industry_id
GROUP BY pc.country_id, pi.industry_id
if you will add some data into that fiddle we can discuss deeper

MySql query: sometimes getting an empty result set

I have this query:
SELECT CONCAT(f.name, ' ', f.parent_names) AS FullName,
stts.name AS 'Status',
u.name AS Unit,
city.name AS City,
hus.mobile1 AS HusbandPhone,
wife.mobile1 AS WifePhone,
f.phone AS HomePhone,
f.contact_initiation_date AS InitDate,
fh.created_at AS StatusChangeDate,
cmt.created_at AS CommentDate,
cmt.comment AS LastComment,
f.reconnection_date AS ReconnectionDate,
(
SELECT GROUP_CONCAT(t.name)
FROM taggings tgs JOIN tags t
ON tgs.tag_id = t.id
WHERE tgs.taggable_type = 'family' AND
tgs.taggable_id = f.id
) AS HandlingStatus
FROM families f
JOIN categories stts ON f.family_status_cat_id = stts.id
JOIN units u ON f.unit_id = u.id
JOIN categories city ON f.main_city_cat_id = city.id
JOIN contacts hus ON f.husband_id = hus.id
JOIN contacts wife ON f.wife_id = wife.id
JOIN comments cmt ON f.id = cmt.commentable_id AND
cmt.created_at = (SELECT MAX(created_at) FROM comments WHERE commentable_id = f.id)
JOIN family_histories fh ON f.id = fh.family_id AND
fh.created_at = (SELECT MAX(created_at) FROM family_histories WHERE family_id = f.id AND family_history_cat_id = 1422) AND
fh.family_history_cat_id = 1422
WHERE f.id = 12212
The problem is with the second SELECT (the column - HandlingStatus).
I don't understand but when the column has results (tested as a stand alone query) - I get an empty result set, and when there are no results - I get a result.
Why?

Getting the latest date from a id

I run the above sql statement and i got this.[IMG]http://i1093.photobucket.com/albums/i422/walkgirl_1993/asd-1_zps5506632e.jpg[/IMG] i'm trying display the latest date which you can see the 3 and 4. For caseid 3, it should display the latest row which is the 2012-12-20 16:12:36.000. I tried using group by, order by. Google some website said to use rank but i'm not sure about the rank as i dont really get rank. Some suggestions?
select [Case].CaseID, Agent.AgentName, Assignment.Description, A.AgentName as EditedBy, A.DateEdited from Agent inner join [Case-Agent] on [Case-Agent].AgentID = Agent.AgentID inner join [Assignment] on Assignment.AssignmentID = [Case-Agent].AssignmentID inner join [Case] on [Case].CaseID = [Case-Agent].CaseID inner join (select EditedCase.CaseID, [EditedCase].DateEdited, [Agent].AgentName from EditedCase inner join [Agent] on [Agent].AgentID = [EditedCase].AgentID) A on A.CaseID = [Case].CaseID where [Assignment].AssignmentID = 0
To do it using RANK you just need to add the RANK to the subquery and get to rank the DateEdited for each CaseID and Agent and then in the main query put a WHERE clause to only select rows where the rank is 1. I think I have got the partition clause right - its a bit hard without seeing your data.
Like this:
SELECT
[Case].CaseID
,Agent.AgentName
,Assignment.Description
,A.AgentName AS EditedBy
,A.DateEdited
FROM Agent
INNER JOIN [Case-Agent] ON [Case-Agent].AgentID = Agent.AgentID
INNER JOIN [Assignment] ON Assignment.AssignmentID = [Case-Agent].AssignmentID
INNER JOIN [Case] ON [Case].CaseID = [Case-Agent].CaseID
INNER JOIN (SELECT
EditedCase.CaseID
,[EditedCase].DateEdited
,[Agent].AgentName
,RANK ( ) OVER (PARTITION BY EditedCase.CaseID, [Agent].AgentName
ORDER BY [EditedCase].DateEdited DESC ) AS pos
FROM EditedCase
INNER JOIN [Agent] on [Agent].AgentID = [EditedCase].AgentID) A on A.CaseID = [Case].CaseID
WHERE [Assignment].AssignmentID = 0
AND pos = 1
You could also change the sub query into an aggregate query that brings back the MAX date like this:
SELECT
[Case].CaseID
,Agent.AgentName
,Assignment.Description
,A.AgentName AS EditedBy
,A.DateEdited
FROM Agent
INNER JOIN [Case-Agent] ON [Case-Agent].AgentID = Agent.AgentID
INNER JOIN [Assignment] ON Assignment.AssignmentID = [Case-Agent].AssignmentID
INNER JOIN [Case] ON [Case].CaseID = [Case-Agent].CaseID
INNER JOIN (SELECT
EditedCase.CaseID
,MAX([EditedCase].DateEdited) AS DateEdited
,[Agent].AgentName
FROM EditedCase
INNER JOIN [Agent] on [Agent].AgentID = [EditedCase].AgentID
GROUP BY
EditedCase.CaseID
,[Agent].AgentName) A on A.CaseID = [Case].CaseID
WHERE [Assignment].AssignmentID = 0
AND pos = 1
You were on the right track; you need to use a ranking function here, for example row_number():
with LatestCase as
(
select [Case].CaseID
, Agent.AgentName
, Assignment.Description
, A.AgentName as EditedBy
, A.DateEdited
, caseRank = row_number() over (partition by [Case].CaseID order by A.DateEdited desc)
from Agent
inner join [Case-Agent] on [Case-Agent].AgentID = Agent.AgentID
inner join [Assignment] on Assignment.AssignmentID = [Case-Agent].AssignmentID
inner join [Case] on [Case].CaseID = [Case-Agent].CaseID
inner join
(
select EditedCase.CaseID
, [EditedCase].DateEdited
, [Agent].AgentName
from EditedCase
inner join [Agent] on [Agent].AgentID = [EditedCase].AgentID
) A on A.CaseID = [Case].CaseID where [Assignment].AssignmentID = 0
)
select *
from LatestCase
where caseRank = 1