Mysql Group By and ABS function Stack - mysql

I have sql code like this, when I execute the code with GROUP BY it just shows record number one and it doesn't use the ABS function. Anyone can help me please?
SELECT *, `tblLifeAgency`.`AgencyName`, `mlp`.`Basic40`, `mlp`.`ADB40`, `mlp`.`CiAccel40`, `mlp`.`Basic50`, `mlp`.`ADB50`, `mlp`.`CiAccel50`, `mlp`.`Basic60`, `mlp`.`ADB60`, `mlp`.`CiAccel60`
FROM (`tblPackage`)
INNER JOIN `tblMatrixLifePackage` mlp ON `mlp`.`PackageID` = `tblPackage`.`PackageID`
INNER JOIN `tblCompany` ON `tblPackage`.`CompanyID` = `tblCompany`.`CompanyID`
INNER JOIN `tblLifeAgency` ON `tblLifeAgency`.`CompanyID` = `tblCompany`.`CompanyID`
AND `tblPackage`.`IsActive` = '1'
WHERE `tblPackage`.`PackageType` = '2'
GROUP BY tblPackage.CompanyID
ORDER BY abs(tblPackage.TotalPremi - 250000)

GROUP BY groups your records. If you have record values, you have to decides which result to show as a summary for a line. For example, you can take all values in one group as positive (ABS) and sum them (SUM). Then try converting this pattern into your case (to understand better):
SELECT
`group`,
ABS(
SUM(`value`)) AS `sum`
FROM my_table
GROUP BY `group`

Related

Using the results of a function multiple times for duplicates - SQL

I am trying to produce a result that shows duplicates in a table. One method I found for getting duplicates and showing them is to run the select statement again through an inner join. However, one of my columns needs to be the result of a function, and the only thing I can think to do is use an alias, however I can't use the alias twice in a SELECT statement.
I am not sure what the best way to run this code for getting the duplicates I need.
My code below
SELECT EXTRACT(YEAR_MONTH FROM date) as 'ndate', a.transponderID
FROM dispondo_prod_disposition.event a
inner JOIN (SELECT EXTRACT(YEAR_MONTH FROM date) as ???,
transponderID, COUNT(*)
FROM dispondo_prod_disposition.event
GROUP BY mdate, transponderID
HAVING count(*) > 1 ) b
ON ndate = ???
AND a.transponderID = b.transponderID
ORDER BY b.transponderID
SELECT b.ndate, transponderID
FROM dispondo_prod_disposition.event a
INNER JOIN ( SELECT EXTRACT(YEAR_MONTH FROM date) as ndate,
transponderID
FROM dispondo_prod_disposition.event
GROUP BY 1, 2
HAVING COUNT(*) > 1 ) b USING (transponderID)
WHERE b.ndate = ??? -- for example, WHERE b.ndate = 202201
ORDER BY transponderID

MySQL Count returns More Rows than it Should

I am attempting to count the number of rows from a given query. But count returns more rows than it should. What is happening?
This query returns only 1 row.
select *
from `opportunities`
inner join `companies` on `opportunities`.`company_id` = `companies`.`id`
left join `opportunityTags` on `opportunities`.`id` = `opportunityTags`.`opportunity_id`
where `opportunities`.`isPublished` = '1' and `opportunities`.`Company_id` = '1'
group by `opportunities`.`id` ;
This query returns that there are 3 rows.
select count(*) as aggregate
from `opportunities`
inner join `companies` on `opportunities`.`company_id` = `companies`.`id`
left join `opportunityTags` on `opportunities`.`id` = `opportunityTags`.`opportunity_id`
where `opportunities`.`isPublished` = '1' and `opportunities`.`Company_id` = '1'
group by `opportunities`.`id`;
When you select count(*) it is counting before the group by. You can probably (unfortunately my realm is SQL Server and I don't have a mySQL instance to test) fix this by using the over() function.
For example:
select count(*) over (partition by `opportunities`.`id`)
EDIT: Actually doesn't look like this is available in mySQL, my bad. How about just wrapping the whole thing in a new select statement? It's not the most elegant solution, but will give you the figure you're after.

subquery with from subquery mysql unknown column

I have the following query
SELECT
a.*, count(
(SELECT matches.id FROM (
SELECT
p.id,
IF ( p.verdeelbaar = '1', MIN(s.minopp), SUM(s.minopp) ) AS min,
SUM( s.maxopp ) AS max,
samenstelling_type_id,
samenstelling_type_absolute_parent(samenstelling_type_id) AS top_type
FROM
app_pand AS p
LEFT JOIN
app_samenstelling AS s
ON
p.id = s.pand_id
WHERE
s.samenstelling_beschikbaarheid_id NOT IN (12,13)
AND
s.actief = 1
AND
IF(a.hk!='te huur/te koop',hk = a.hk,TRUE)
GROUP BY
pand_id, top_type
HAVING
CASE top_type
WHEN #kantoor THEN
min < a.kantoor_max AND max > a.kantoor_min
WHEN #magazijn THEN
min < a.magazijn_max AND max > a.magazijn_min
WHEN #terrein THEN
min < a.terrein_max AND max > a.terrein_min
END
) AS matches
GROUP BY matches.id )
) AS m
FROM
app_aanvragen AS a
WHERE a.id = #aanvraag;
Whit this query I want to the calculate number of matches for one aanvraag (the dutch word for a request).
The problem is that in the most inner query, the FROM from matches does not know about the a records (a.hk, a.kantoor, a.magazijn..).
I know many solutions on this problem say that you must join both tables, and that way reach the arecords, but I don't see how to join them, because they have no join condition.
Is this query possible in the first place, and if so, how should I do it? And if not, does anybody sees another solution for this problem?
Thanx in advance!

MySQL Inner Join with where clause sorting and limit, subquery?

Everything in the following query results in one line for each invBlueprintTypes row with the correct information. But I'm trying to add something to it. See below the codeblock.
Select
blueprintType.typeID,
blueprintType.typeName Blueprint,
productType.typeID,
productType.typeName Item,
productType.portionSize,
blueprintType.basePrice * 0.9 As bpoPrice,
productGroup.groupName ItemGroup,
productCategory.categoryName ItemCategory,
blueprints.productionTime,
blueprints.techLevel,
blueprints.researchProductivityTime,
blueprints.researchMaterialTime,
blueprints.researchCopyTime,
blueprints.researchTechTime,
blueprints.productivityModifier,
blueprints.materialModifier,
blueprints.wasteFactor,
blueprints.maxProductionLimit,
blueprints.blueprintTypeID
From
invBlueprintTypes As blueprints
Inner Join invTypes As blueprintType On blueprints.blueprintTypeID = blueprintType.typeID
Inner Join invTypes As productType On blueprints.productTypeID = productType.typeID
Inner Join invGroups As productGroup On productType.groupID = productGroup.groupID
Inner Join invCategories As productCategory On productGroup.categoryID = productCategory.categoryID
Where
blueprints.techLevel = 1 And
blueprintType.published = 1 And
productType.marketGroupID Is Not Null And
blueprintType.basePrice > 0
So what I need to get in here is the following table with the columns below it so I can use the values timestamp and sort the entire result by profitHour
tablename: invBlueprintTypesPrices
columns: blueprintTypeID, timestamp, profitHour
I need this information with the following select in mind. Using a select to show my intention of the JOIN/in-query select or whatever that can do this.
SELECT * FROM invBlueprintTypesPrices
WHERE blueprintTypeID = blueprintType.typeID
ORDER BY timestamp DESC LIMIT 1
And I need the main row from table invBlueprintTypes to still show even if there is no result from the invBlueprintTypesPrices. The LIMIT 1 is because I want the newest row possible, but deleting the older data is not a option since history is needed.
If I've understood correctly I think I need a subquery select, but how to do that? I've tired adding the exact query that is above with a AS blueprintPrices after the query's closing ), but did not work with a error with the
WHERE blueprintTypeID = blueprintType.typeID
part being the focus of the error. I have no idea why. Anyone who can solve this?
You'll need to use a LEFT JOIN to check for NULL values in invBlueprintTypesPrices. To mimic the LIMIT 1 per TypeId, you can use the MAX() or to truly make sure you only return a single record, use a row number -- this depends on whether you can have multiple max time stamps for each type id. Assuming not, then this should be close:
Select
...
From
invBlueprintTypes As blueprints
Inner Join invTypes As blueprintType On blueprints.blueprintTypeID = blueprintType.typeID
Inner Join invTypes As productType On blueprints.productTypeID = productType.typeID
Inner Join invGroups As productGroup On productType.groupID = productGroup.groupID
Inner Join invCategories As productCategory On productGroup.categoryID = productCategory.categoryID
Left Join (
SELECT MAX(TimeStamp) MaxTime, TypeId
FROM invBlueprintTypesPrices
GROUP BY TypeId
) blueprintTypePrice On blueprints.blueprintTypeID = blueprintTypePrice.typeID
Left Join invBlueprintTypesPrices blueprintTypePrices On
blueprintTypePrice.TypeId = blueprintTypePrices.TypeId AND
blueprintTypePrice.MaxTime = blueprintTypePrices.TimeStamp
Where
blueprints.techLevel = 1 And
blueprintType.published = 1 And
productType.marketGroupID Is Not Null And
blueprintType.basePrice > 0
Order By
blueprintTypePrices.profitHour
Assuming you might have the same max time stamp with 2 different records, replace the 2 left joins above with something similar to this getting the row number:
Left Join (
SELECT #rn:=IF(#prevTypeId=TypeId,#rn+1,1) rn,
TimeStamp,
TypeId,
profitHour,
#prevTypeId:=TypeId
FROM (SELECT *
FROM invBlueprintTypesPrices
ORDER BY TypeId, TimeStamp DESC) t
JOIN (SELECT #rn:=0) t2
) blueprintTypePrices On blueprints.blueprintTypeID = blueprintTypePrices.typeID AND blueprintTypePrices.rn=1
You don't say where you are putting the subquery. If in the select clause, then you have a problem because you are returning more than one value.
You can't put this into the from clause directly, because you have a correlated subquery (not allowed).
Instead, you can put it in like this:
from . . .
(select *
from invBLueprintTypesPrices ibptp
where ibtp.timestamp = (select ibptp2.timestamp
from invBLueprintTypesPrices ibptp2
where ibptp.blueprintTypeId = ibptp2.blueprintTypeId
order by timestamp desc
limit 1
)
) ibptp
on ibptp.blueprintTypeId = blueprintType.TypeID
This identifies the most recent records for all the blueprintTypeids in the subquery. It then joins in the one that matches.

optimize Mysql: get latest status of the sale

In the following query, I show the latest status of the sale (by stage, in this case the number 3). The query is based on a subquery in the status history of the sale:
SELECT v.id_sale,
IFNULL((
SELECT (CASE WHEN IFNULL( vec.description, '' ) = ''
THEN ve.name
ELSE vec.description
END)
FROM t_record veh
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign
INNER JOIN t_state ve ON ve.id_state = vec.id_state
WHERE veh.id_sale = v.id_sale
AND vec.id_stage = 3
ORDER BY veh.id_record DESC
LIMIT 1
), 'x') sale_state_3
FROM t_sale v
INNER JOIN t_quarters sd ON v.id_quarters = sd.id_quarters
WHERE 1 =1
AND v.flag =1
AND v.id_quarters =4
AND EXISTS (
SELECT '1'
FROM t_record
WHERE id_sale = v.id_sale
LIMIT 1
)
the query delay 0.0057seg and show 1011 records.
Because I have to filter the sales by the name of the state as it would have to repeat the subquery in a where clause, I have decided to change the same query using joins. In this case, I'm using the MAX function to obtain the latest status:
SELECT
v.id_sale,
IFNULL(veh3.State3,'x') AS sale_state_3
FROM t_sale v
INNER JOIN t_quarters sd ON v.id_quarters = sd.id_quarters
LEFT JOIN (
SELECT veh.id_sale,
(CASE WHEN IFNULL(vec.description,'') = ''
THEN ve.name
ELSE vec.description END) AS State3
FROM t_record veh
INNER JOIN (
SELECT id_sale, MAX(id_record) AS max_rating
FROM(
SELECT veh.id_sale, id_record
FROM t_record veh
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign AND vec.id_stage = 3
) m
GROUP BY id_sale
) x ON x.max_rating = veh.id_record
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign
INNER JOIN t_state ve ON ve.id_state = vec.id_state
) veh3 ON veh3.id_sale = v.id_sale
WHERE v.flag = 1
AND v.id_quarters = 4
This query shows the same results (1011). But the problem is it takes 0.0753 sec
Reviewing the possibilities I have found the factor that makes the difference in the speed of the query:
AND EXISTS (
SELECT '1'
FROM t_record
WHERE id_sale = v.id_sale
LIMIT 1
)
If I remove this clause, both queries the same time delay... Why it works better? Is there any way to use this clause in the joins? I hope your help.
EDIT
I will show the results of EXPLAIN for each query respectively:
q1:
q2:
Interesting, so that little statement basically determines if there is a match between t_record.id_sale and t_sale.id_sale.
Why is this making your query run faster? Because Where statements applied prior to subSelects in the select statement, so if there is no record to go with the sale, then it doesn't bother processing the subSelect. Which is netting you some time. So that's why it works better.
Is it going to work in your join syntax? I don't really know without having your tables to test against but you can always just apply it to the end and find out. Add the keyword EXPLAIN to the beginning of your query and you will get a plan of execution which will help you optimize things. Probably the best way to get better results in your join syntax is to add some indexes to your tables.
But I ask you, is this even necessary? You have a query returning in <8 hundredths of a second. Unless this query is getting ran thousands of times an hour, this is not really taxing your DB at all and your time is probably better spent making improvements elsewhere in your application.