简体   繁体   中英

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 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 blueprintTypeid s in the subquery. It then joins in the one that matches.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM