I am trying to bring through the site.Site_Name, for each hive.hiveno and it's max(hiverdg.invdate). Running the code below doesn't work because site.Site_Name is not aggrigated. If I add site.Site_Name to the Group By, the code runs, but the ouput displays the results repeated, once for each site.Site_Name
select site.Site_Name ,hive.hiveno, max(hiverdg.invdate)
from hiverdg
inner join hive
on hiveRdg.hive_Link = hive.hive_Link
inner join Customer
on customer.Customer_Link = hive.Customer_Link
inner join site
on site.Customer_Link = customer.Customer_Link
where
(hiverdg.xtype = 'N'
and customer.CustomerName = 'Cust1')
or
(hiverdg.xtype = 'A'
and customer.CustomerName = 'Cust1')
group by hive.hiveno
The easiest way to do this, with your query, is the substring_index()/group_concat() trick:
select substring_index(group_concat(s.Site_Name order by rdg.invdate desc separator '|'
), '|', 1
) as SiteName,
h.hiveno, max(rdg.invdate)
from hiverdg rdg inner join
hive h
on rdg.hive_Link = h.hive_Link inner join
Customer c
on c.Customer_Link = h.Customer_Link inner join
site s
on s.Customer_Link = c.Customer_Link
where rdg.xtype in ('N', 'A') and c.CustomerName = 'Cust1')
group by h.hiveno;
I also made the following changes to your query:
Introduced table aliases, to make the query easier to write and to read.
Changed the where to use in, simplifying the logic.
Related
I need assistance in joining the two query statements together using subquery. I am confused on how I can combine the two together. I appreciate the help.
SELECT * FROM MEDICAL_PROCEDURE
JOIN PROCEDURE_CATEGORY ON medical_procedure.procedure_category_id = PROCEDURE_CATEGORY.PROCEDURE_CATEGORY_ID;
SELECT
Medical_procedure.medical_procedure_id,
COUNT(procedure_tool_supply.medical_procedure_id) AS Supply_Needed
FROM Procedure_tool_supply
JOIN Medical_Procedure on Procedure_tool_supply.medical_procedure_id = Medical_procedure.medical_procedure_id
GROUP BY Procedure_tool_supply.medical_procedure_id
HAVING COUNT(Procedure_tool_supply.medical_procedure_id) < 3;
Can't really test without test data, but this should work. Hopefully I figured out correctly what you're trying to do:
SELECT *
FROM
MEDICAL_PROCEDURE P
JOIN PROCEDURE_CATEGORY C ON
P.procedure_category_id = C.PROCEDURE_CATEGORY_ID
cross apply (
SELECT
COUNT(T.medical_procedure_id) AS Supply_Needed
FROM
Procedure_tool_supply T
where
T.medical_procedure_id = P.medical_procedure_id
GROUP BY
T.medical_procedure_id
HAVING
COUNT(T.medical_procedure_id) < 3
) T
It's not clear what you are trying to achieve. But if your intent is to include the derived Supply_Needed column from the second query on each row from the first query, and to restrict the rows returned to those that have a medical_procedure_id value returned by the second query, then...
you could do something like this:
SELECT mp.*
, pc.*
, ct.Supply_Needed
FROM MEDICAL_PROCEDURE mp
JOIN PROCEDURE_CATEGORY pc
ON mp.procedure_category_id = pc.PROCEDURE_CATEGORY_ID
JOIN ( SELECT pr.medical_procedure_id
, COUNT(ts.medical_procedure_id) AS Supply_Needed
FROM Procedure_tool_supply ts
JOIN Medical_Procedure pr
ON ts.medical_procedure_id = pr.medical_procedure_id
GROUP BY ts.medical_procedure_id
HAVING COUNT(ts.medical_procedure_id) < 3
) ct
ON ct.medical_procedure_id = mp.medical_procedure_id
Some sql query gives me the following result:
As you can see, it already has GROUP BY.
So what I need? I need to group it again (by treatment_name) and count rows for each group. See more details on screenshot.
Here is full query:
SELECT
treatment_summaries.*
FROM `treatment_summaries`
INNER JOIN
`treatments`
ON
`treatments`.`treatment_summary_id` = `treatment_summaries`.`id`
AND
(treatment <> '' and treatment is not null)
INNER JOIN
`treatment_reviews`
ON
`treatment_reviews`.`treatment_id` = `treatments`.`id`
INNER JOIN
`conditions_treatment_reviews`
ON
`conditions_treatment_reviews`.`treatment_review_id` = `treatment_reviews`.`id`
INNER JOIN
`conditions` ON `conditions`.`id` = `conditions_treatment_reviews`.`condition_id`
INNER JOIN `conditions_treatment_summaries` `conditions_treatment_summaries_join`
ON
`conditions_treatment_summaries_join`.`treatment_summary_id` = `treatment_summaries`.`id`
INNER JOIN `conditions` `conditions_treatment_summaries`
ON `conditions_treatment_summaries`.`id` = `conditions_treatment_summaries_join`.`condition_id`
WHERE
`conditions`.`id` = 9
AND `conditions`.`id` IN (9)
AND (latest_review_id is not null)
GROUP BY
treatment_reviews.id
ORDER BY
treatment_summaries.reviews_count desc
LIMIT 20 OFFSET 0
Maybe there is another issue, cause GROUP BY should not leave same lines (for given column), but anyway you can wrap it like this:
SELECT * FROM ( YOUR_SQL_SELECT_WITH_EVERYTHING ) GROUP BY id
So the result you get will behave as another table and you can do all operations like GROUP BY again.
I've created sqlfiddle to try and get my head around this http://sqlfiddle.com/#!2/21e72/1
In the query, I have put a max() on the compiled_date column but the recommendation column is still coming through incorrect - I'm assuming that a select statement will need to be inserted on line 3 somehow?
I've tried the examples provided by the commenters below but I think I just need to understand this from a basic query to begin with.
As others have pointed out, the issue is that some of the select columns are neither aggregated nor used in the group by clause. Most DBMSs won't allow this at all, but MySQL is a little relaxed on some of the standards...
So, you need to first find the max(compiled_date) for each case, then find the recommendation that goes with it.
select r.case_number, r.compiled_date, r.recommendation
from reporting r
join (
SELECT case_number, max(compiled_date) as lastDate
from reporting
group by case_number
) s on r.case_number=s.case_number
and r.compiled_date=s.lastDate
Thank you for providing sqlFiddle. But only reporting data is given. we highly appreciate if you give us sample data of whole tables.
Anyway, Could you try this?
SELECT
`case`.number,
staff.staff_name AS ``case` owner`,
client.client_name,
`case`.address,
x.mx_date,
report.recommendation
FROM
`case` INNER JOIN (
SELECT case_number, MAX(compiled_date) as mx_date
FROM report
GROUP BY case_number
) x ON x.case_number = `case`.number
INNER JOIN report ON x.case_number = report.case_number AND report.compiled_date = x.mx_date
INNER JOIN client ON `case`.client_number = client.client_number
INNER JOIN staff ON `case`.staff_number = staff.staff_number
WHERE
`case`.active = 1
AND staff.staff_name = 'bob'
ORDER BY
`case`.number ASC;
Check below query:
SELECT c.number, s.staff_name AS `case owner`, cl.client_name,
c.address, MAX(r.compiled_date), r.recommendation
FROM case c
INNER JOIN (SELECT r.case_number, r.compiled_date, r.recommendation
FROM report r ORDER BY r.case_number, r.compiled_date DESC
) r ON r.case_number = c.number
INNER JOIN client cl ON c.client_number = cl.client_number
INNER JOIN staff s ON c.staff_number = s.staff_number
WHERE c.active = 1 AND s.staff_name = 'bob'
GROUP BY c.number
ORDER BY c.number ASC
SELECT
case.number,
staff.staff_name AS `case owner`,
client.client_name,
case.address,
(select MAX(compiled_date)from report where case_number=case.number),
report.recommendation
FROM
case
INNER JOIN report ON report.case_number = case.number
INNER JOIN client ON case.client_number = client.client_number
INNER JOIN staff ON case.staff_number = staff.staff_number
WHERE
case.active = 1 AND
staff.staff_name = 'bob'
GROUP BY
case.number
ORDER BY
case.number ASC
try this
I have the following query to return all user_attributes and attributes which have a specified tag:
SELECT `user_attributes`.*, `attributes`.*
FROM `user_attributes`
INNER JOIN `attributes` ON (`attributes`.`id` = `user_attributes`.`attribute_id`)
INNER JOIN `user_tags` ON (`attributes`.`id` = `user_tags`.`attribute_id`)
INNER JOIN `tags` ON (`user_tags`.`tag_id` = `tags`.`id`)
WHERE `user_attributes`.`user_id` = '1'
AND `tags`.`title` IN ('tag1')
I would like to adjust the query so that it finds all values that have 2 tags. At the moment I have:
SELECT `user_attributes`.*
FROM `user_attributes`
INNER JOIN `attributes` ON (`attributes`.`id` = `user_attributes`.`attribute_id`)
INNER JOIN `user_tags` ON (`attributes`.`id` = `user_tags`.`attribute_id`)
INNER JOIN `tags` ON (`user_tags`.`tag_id` = `tags`.`id`)
WHERE `user_attributes`.`user_id` = '1'
AND `tags`.`title` IN ('tag1', 'tag2')
HAVING (COUNT(DISTINCT `tags`.`title`) = 2)
Is it breaking because I'm using HAVING without a GROUP BY?
HAVING should be used in combination with GROUP BY indeed. MySQL is the only database what will handle HAVING without GROUP BY as some kind off WHERE
Some more proof for the downvoter..
MySQL http://www.sqlfiddle.com/#!2/ba8d6/3 (this is WRONG and looks like HAVING IS USED AS WHERE)
Oracle http://www.sqlfiddle.com/#!4/ba8d6/1 (this is correct ORA-00979: not a GROUP BY expression Oracle is missing the GROUP BY)
Postgresql http://www.sqlfiddle.com/#!1/ba8d6/2 (this is correct ERROR: column "data.username" must appear in the GROUP BY clause or be used in an aggregate function Postgresql wants to have an GROUP BY
Im trying to use a variable to count the number of rows i have for a specific id, if i use it without inner joins it works perfectly, otherwise no, here is the section without joins
select
cd.basis_point bpt,
cd.created,
#version:=#version+1 version
from tbl_class_det cd, (select #version:=1) v
where (cd.class_uuid='{$row['uuid']}')
and (cd.created>(
select
created
from tbl_class_det
where (class_uuid=cd.class_uuid)
order by created asc
limit 1
))
order by cd.created asc
the section with joins that gives an error:
select c.name,
fd.value bpt,
fd.created,
#version:=#version+1 version
from tbl_fee_det fd, (select #version:=1) v
INNER JOIN tbl_fee f ON f.uuid = fd.fee_uuid
INNER JOIN tbl_class c ON c.uuid = f.class_uuid
where (fd.created>(
select
created
from tbl_class_det
where (fee_uuid=f.uuid)
order by created asc
limit 1
))
order by fd.created asc;
You are using a combination of explicit and implicit joins. You should not mix the JOIN syntax with the comma syntax. If you need to you this then use a subquery similar to this:
select name,
value bpt,
created,
#version:=#version+1 version
from
(
select c.name,
fd.value,
fd.created,
f.uuid
FROM tbl_fee_det fd
INNER JOIN tbl_fee f
ON f.uuid = fd.fee_uuid
INNER JOIN tbl_class c
ON c.uuid = f.class_uuid
) f, (select #version:=1) v
where (created>(select created
from tbl_class_det
where (fee_uuid=f.uuid)
order by created asc
limit 1))
order by created asc;