Nested MySQL query? - mysql

I have this MySQL statement which works fine:
SELECT claim_items.item_id, claim_items.quantity*items_rate.rate as per_item
FROM claim_items, items_rate
WHERE claim_items.claim_id = 1 AND claim_items.item_id = items_rate.items_id
However what I want to do is to get the sum of the per_item field generated in the MySQL statement. Is it possible to do a nested statement to do that? I know I could create a view and then do it, but would prefer to do it in one statement.
Thanks for your help, much appreciated!

select t.id, SUM(t.per_item)
from
(
SELECT claim_items.item_id as id, claim_items.quantity*items_rate.rate as per_item
FROM claim_items, items_rate
WHERE claim_items.claim_id = 1 AND claim_items.item_id = items_rate.items_id
) t
group by t.id
Hope this should help.

If you just want the sum over all rows you can do it like that (using explicit joins for better readability):
SELECT SUM( claim_items.quantity * items_rate.rate )
FROM claim_items
JOIN items_rate ON ( items_rate.items_id = claim_items.item_id )
WHERE claim_items.claim_id = 1

Related

How to optimize a query that is a join of 2 very similar queries but with different aggregation

I have the following query:
SELECT OBJ_DESC_ERRORS.description, OBJ_DESC_ERRORS.object, OBJ_DESC_ERRORS.count_errors, OBJ_ERRORS.count_total FROM
(SELECT `metrics_event`.`description`, `metrics_event`.`object`, COUNT(`metrics_event`.`id`) AS `count_errors` FROM `metrics_event`
INNER JOIN `metrics_session` ON (`metrics_event`.`session_id` = `metrics_session`.`id`)
WHERE (`metrics_session`.`training_id` = 4 AND NOT (`metrics_session`.`completed_at` IS NULL) )
GROUP BY `metrics_event`.`description`, `metrics_event`.`object` ORDER BY `count_errors` DESC ) as OBJ_DESC_ERRORS
JOIN
(SELECT `metrics_event`.`object`, COUNT(`metrics_event`.`id`) AS `count_total` FROM `metrics_event`
INNER JOIN `metrics_session` ON (`metrics_event`.`session_id` = `metrics_session`.`id`)
WHERE (`metrics_session`.`training_id` = 4 AND NOT (`metrics_session`.`completed_at` IS NULL) )
GROUP BY `metrics_event`.`object` ORDER BY `count_total` DESC ) as OBJ_ERRORS
ON OBJ_DESC_ERRORS.object = OBJ_ERRORS.object
which produces the following result:
As you can see I'm basically running the same query twice. The reason for that is that I need to have that count_errors broken down by each aggregation of object + description, but I also need the count_total to be only aggregated by object. This was the way I could think of. Now I'd like to know if this is the best I can do or if it can be optimized even further.
If so I have no clue how. Googling and searching similar topics on this is difficult because the optimization task depends on the query itself, so keywords here didn't help me much.
Get rid of the inner ORDER BYs; they do nothing useful.
Rewrite the query something like this:
SELECT
me.description,
me.object,
SUM(...) AS count_errors,
SUM(...) AS count_total
FROM `metrics_event` AS me
INNER JOIN `metrics_session` AS ms ON (me.`session_id` = ms.`id`)
WHERE ms.`training_id` = 4
ms.`completed_at` IS NOT NULL
GROUP BY me.`description`, me.`object`
ORDER BY `count_total` DESC
Since a boolean expression evaluates as 1 for TRUE, else 0, devise the argument to SUM() to be a boolean expression that provides the desired COUNT.

MySQL find duplicates based on some matching fields and some not

I am trying to create a MySQL query of game discs to find some duplicates based on some values being the same and some not.
I need the fields 'name', 'disc', 'platform', 'region' to be the same.
But I also need the field 'version' to be different.
I have already tried a number of queries to do this such as the one below but none seem to work as desired.
SELECT *
FROM media.amps_2000_box_a
INNER JOIN (SELECT *
FROM media.amps_2000_box_a
GROUP BY name
HAVING COUNT(name) > 1) dup
ON media.amps_2000_box_a.name = dup.name and media.amps_2000_box_a.disk = dup.disk and media.amps_2000_box_a.format = dup.format and media.amps_2000_box_a.region = dup.region and media.amps_2000_box_a.version<> dup.version
order by dup.name;
Would anyone be able to help me fix this query?
Thanks in advance.
slick
Maybe I'm missing something but the solution seems quite trivial:
SELECT DISTINCT
amps1.name,
amps1.disk,
amps1.platform,
amps1.region
FROM media.amps_2000_box_a amps1
JOIN media.amps_2000_box_a amps2
ON amps1.name = amps2.name
AND amps1.disk = amps2.disk
AND amps1.platform = amps2.platform
AND amps1.region = amps2.region
AND amps1.version <> amps2.version
ORDER BY amps1.name;

Query table based on input parameter

I have an input parameter to a query I'm trying to write. Basically, if mostRecentSnapshot == true then I want to select only the most recent records from the process run (basically where max(creationDate)) and if mostRecentSnapshot == false then select creationDate and other columns normally.
To me, it makes sense to do this if statement in the from clause, but I don't think that's possible. Normally I would use a CTE, but I those don't exist in MySQL.
What is the best way to achieve this?
It would be something along the lines of this:
SELECT
CASE mostRecentSnapshot WHEN FALSE THEN
(
processauditheader.creationDate as processCreationDate,
processauditheader.processName,
processauditheader.processType,
processauditheader.processHost,
processauditheader.processDatabase,
processauditheader.tableAudited,
processauditheader.processInvokedByName,
processauditheader.processInvokedByType,
processauditheader.processInvokedByDatabase,
processauditheader.processIntervalValue,
processauditheader.processIntervalField,
processauditheader.auditScenarios,
processaudititerationdetail.creationDate as iterationDate,
processaudititerationdetail.connectionId,
processaudititerationdetail.processDate,
processaudititerationdetail.tableRowCount,
processaudititerationdetail.tableRowCountLastDay,
processaudititerationdetail.previousProcessAuditIterationDetailID,
processauditmetricdetail.creationDate,
processauditmetricdetail.processAuditIterationDetailID,
processauditmetricdetail.auditMetric,
processauditmetricdetail.auditTotal,
processauditmetricdetail.auditExample
)
WHEN TRUE THEN
(
((SELECT MAX(processaudititerationdetail.creationDate) as maxSnapshot,
processaudititerationdetail.id
from reporting_audit.processaudititerationdetail
group by processaudititerationdetail.creationDate) mostRecent
JOIN reporting_audit.processaudititerationdetail ON mostRecent.id = processaudititerationdetail.id)
)
END
FROM reporting_audit.processauditheader
JOIN processaudititerationdetail ON processaudititerationdetail.processAuditHeaderID = processauditheader.id
LEFT JOIN processauditmetricdetail ON processauditmetricdetail.processAuditIterationDetailID = processaudititerationdetail.id
A query can only return a fixed set of columns. Perhaps the following does what you want:
select paid.*
from reporting_audit.processaudititerationdetail paid
where (not v_mostRecentSnapshot) or
paid.creation_date = (select max(paid2.creationDate from reporting_audit.processaudititerationdetail paid2);
It will either select all records from the table or only the record(s) that have the most recent creationDate.

mysql subquery - results do not fulfill both

I have the following SQL query for MySQL:
SELECT SQL_CALC_FOUND_ROWS objects.objects_no
FROM objects
LEFT JOIN finds ON (objects.objects_no = finds.objects_no)
LEFT JOIN ceramics ON (objects.objects_no = ceramics.objects_no)
WHERE 1=1
and (objects.objects_no) in (select DISTINCT objects_no from objects_materials where thesaurus_term_id in (18658))
and (objects.objects_no) in (select DISTINCT objects_no from objects_objects where thesaurus_term_id in (24193))
GROUP BY objects.objects_no
ORDER BY objects.objects_no
Instead of getting results that match both subqueries, I also get results that match one or the other. Does anyone have an idea why that is?
Thanks, Sandro
Try parenthesizing the conditions.
WHERE (
(1=1)
and ((objects.objects_no) in (select DISTINCT objects_no from objects_materials where thesaurus_term_id in (18658)))
and ((objects.objects_no) in (select DISTINCT objects_no from objects_objects where thesaurus_term_id in (24193)))
)
Thanks for all your help. It actually does work just fine. There was a problem within the data inside the thesaurus.
Sorry!!!

How to get two columns of two different tables where id = id and id= 9?

my first query :
SELECT `oc_banner_image_description`.`title`
FROM `oc_banner_image_description`
WHERE `banner_id`=9
my second query:
SELECT `oc_banner_image`.`image` FROM `oc_banner_image` WHERE `banner_id`=9
how to make this two queries into single query using sql joins.
Using standard join syntax would look like this :
SELECT `oc_banner_image_description`.`title`, `oc_banner_image`.`image`
FROM `oc_banner_image_description`
JOIN `oc_banner_image` ON `oc_banner_image_description`.`banner_id` = `oc_banner_image`.`banner_id`
WHERE `oc_banner_image`.`banner_id`=9
Try this (You may need to use the single quotes a bit different than what I have)
SELECT `i`.`image`, `d`.`title`
FROM `oc_banner_image` as `i`, `oc_banner_image_description` as `d`
WHERE `c.banner_id` = `i.banner_id`
and i.`banner_id`=9
If this is not working try this on both tables
select banner_id, count(banner_id)
from oc_banner_image
group by banner_id order desc;
This will tell you if you have multiple banner_id's in the oc_banner_image table.
Try this
SELECT bannerDesc.title , bannerImage.image
FROM oc_banner_image_description bannerDesc join oc_banner_image bannerImage
on bannerDesc.banner_id = bannerImage.banner_id
WHERE bannerImage.banner_id=9