Mysql query with group by and order by involving several tables - mysql

I'm having a problem regarding a query because i don't have all the records and i don't know why
This is the query
SELECT `ebspma_paad_ebspma`.`semana_dias`.`dia`,`ebspma_paad_ebspma`.`req_material_sala`.`sala`, `ebspma_paad_ebspma`.`req_material_tempo`.`inicio`, `ebspma_paad_ebspma`.`sala_ocupacao`.`id_ocup`, `ebspma_paad_ebspma`.`turmas`.`turma`
FROM `ebspma_paad_ebspma`.`sala_ocupacao`
INNER JOIN `ebspma_paad_ebspma`.`semana_dias`
ON (`sala_ocupacao`.`id_dia` = `semana_dias`.`id_dia`)
INNER JOIN `ebspma_paad_ebspma`.`req_material_sala`
ON (`sala_ocupacao`.`id_sala` = `req_material_sala`.`idsala`)
LEFT JOIN `ebspma_paad_ebspma`.`req_material_tempo`
ON (`sala_ocupacao`.`id_tempo` = `req_material_tempo`.`idtempo`)
LEFT JOIN `ebspma_paad_ebspma`.`turmas`
ON (`sala_ocupacao`.`id_turma` = `turmas`.`id_turma`)
where`ebspma_paad_ebspma`.`sala_ocupacao`.`id_turma` = '$turma'
GROUP BY `ebspma_paad_ebspma`.`sala_ocupacao`.`id_dia` , `ebspma_paad_ebspma`.`req_material_tempo`.`inicio` ASC";
Running this query i have almost records but this is a school timetable and when a class is divided in 2 groups i have two classrooms for this class. With this query i have only one group
For exemple the class start at 1 PM in two classrooms (27 and 31), with this query i should have at 1 PM the classroom X is on 27 and 31 classroom, but i have only the first one
Image to check http://postimg.org/image/u24r35fkz/
And my database image http://postimg.org/image/hyvpb1qz1/ce7a7320/
So what's wrong with my query?
Thanks
UPDATE 1
I have simplified my query to
SELECT t2.`dia` , t3.`sala` , t4.`inicio` , t1.`id_ocup` , t5.`turma`
FROM `ebspma_paad_ebspma`.`sala_ocupacao` AS t1
INNER JOIN `ebspma_paad_ebspma`.`semana_dias` AS t2 ON ( t1.`id_dia` = t2.`id_dia` )
INNER JOIN `ebspma_paad_ebspma`.`req_material_sala` AS t3 ON ( t1.`id_sala` = t3.`idsala` )
LEFT JOIN `ebspma_paad_ebspma`.`req_material_tempo` AS t4 ON ( t1.`id_tempo` = t4.`idtempo` )
LEFT JOIN `ebspma_paad_ebspma`.`turmas` AS t5 ON ( t1.`id_turma` = t5.`id_turma` )
WHERE t1.`id_turma` =12
GROUP BY t1.`id_dia` , t3.`idsala` , t4.`inicio`
Now i can see all the classes but not in the right order, the order should be given by t4.inicio and by day (id dia)

You are not grouping by sala so MySQL will behave badly and give you a random row that fits the other requirements. Better functioning database engines would give you an error saying you haven't aggregated or grouped all result columns.
If you add sala to GROUP BY you should see the difference.
For the ordering: you're not asking the database to ORDER BY anything so the rows will be in whatever order they happen to come out. Probably want to add ORDER BY t4.inicio, t1.id_dia to handle that.

Related

Grouping method

I am working on a query with the following format:
I require all the columns from the Database 'A', while I only require the summed amount (sum(amount)) from the Database 'B'.
SELECT A.*, sum(B.CURTRXAM) as 'Current Transaction Amt'
FROM A
LEFT JOIN C
ON A.Schedule_Number = C.Schedule_Number
LEFT JOIN B
ON A.DOCNUMBR = B.DOCNUMBR
ON A.CUSTNMBR = B.CUSTNMBR
GROUP BY A
ORDER BY A.CUSTNMBR
My question is regarding the grouping statement, database A has about 12 columns and to group by each individually is tedious, is there a cleaner way to do this such as:
GROUP BY A
I am not sure if a simpler way exists as I am new to SQL, I have previously investigated GROUPING_ID statements but thats about it.
Any help on lumped methods of grouping would be helpful
Since the docnumber is the primary key - just use the following SQL:
SELECT A.*, sum(B.CURTRXAM) as 'Current Transaction Amt'
FROM A
LEFT JOIN C
ON A.Schedule_Number = C.Schedule_Number
LEFT JOIN B
ON A.DOCNUMBR = B.DOCNUMBR
ORDER BY RM20401.CUSTNMBR
GROUP BY A.DOCNUMBR

Creating a subquery in Access

I am attempting to create a subquery in Access but I am receiving an error stating that one record can be returned by this subquery. I am wanting to find the top 10 companies that have the most pets then I want to know the name of those pets. I have never created a subquery before so I am not sure where I am going wrong. Here is what I have:
SELECT TOP 10 dbo_tGovenrnmentRegulatoryAgency.GovernmentRegulatoryAgency
(SELECT dbo_tPet.Pet
FROM dbo_tPet)
FROM dbo_tPet INNER JOIN dbo_tGovenrnmentRegulatoryAgency ON
dbo_tPet.GovernmentRegulatoryAgencyID =
dbo_tGovenrnmentRegulatoryAgency.GovernmentRegulatoryAgencyID
GROUP BY dbo_tGovenrnmentRegulatoryAgency.GovernmentRegulatoryAgency
ORDER BY Count(dbo_tPet.PetID) DESC;
Consider this solution, requiring a subquery in the WHERE IN () clause:
SELECT t1.GovernmentRegulatoryAgency, dbo_tPet.Pet,
FROM dbo_tPet
INNER JOIN dbo_tGovenrnmentRegulatoryAgency t1 ON
dbo_tPet.GovernmentRegulatoryAgencyID = t1.GovernmentRegulatoryAgencyID
WHERE t1.GovernmentRegulatoryAgency IN
(SELECT TOP 10 t2.GovernmentRegulatoryAgency
FROM dbo_tPet
INNER JOIN dbo_tGovenrnmentRegulatoryAgency t2 ON
dbo_tPet.GovernmentRegulatoryAgencyID = t2.GovernmentRegulatoryAgencyID
GROUP BY t2.GovernmentRegulatoryAgency
ORDER BY Count(dbo_tPet.Pet) DESC);
Table aliases are not needed but I include them for demonstration.
This should hopefully do it:
SELECT a.GovernmentRegulatoryAgency, t.NumOfPets
FROM dbo_tGovenrnmentRegulatoryAgency a
INNER JOIN (
SELECT TOP 10 p.GovernmentRegulatoryAgencyID, COUNT(p.PetID) AS NumOfPets
FROM dbo_tPet p
GROUP BY p.GovernmentRegulatoryAgencyID
ORDER BY COUNT(p.PetID) DESC
) t
ON a.GovernmentRegulatoryAgencyID = t.GovernmentRegulatoryAgencyID
In a nutshell, first get the nested query sorted, identifying what the relevant agencies are, then inner join back to the agency table to get the detail of the agencies so picked.

MySQL group by twice and COUNT

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.

MySQL - Trying to show results for rows that have 0 records...across 3 columns

There's a lot of Q&A out there for how to make MySQL show results for rows that have 0 records, but they all involve 1-2 tables/fields at most.
I'm trying to achieve the same ends, but across 3 fields, and I just can't seem to get it.
Here's what I've hacked together:
SELECT circuit.circuit_name, county.county_name, result.adr_result, count( result.adr_result ) AS num_results
FROM
(
SELECT cases.case_id, cases.county_id, cases.result_id
FROM cases
WHERE cases.status_id <> "2"
) q1
RIGHT JOIN county ON q1.county_id = county.county_id
RIGHT JOIN circuit ON county.circuit_id = circuit.circuit_id
RIGHT JOIN result ON q1.result_id = result.result_id
GROUP BY adr_result, circuit_name, county_name
ORDER BY circuit_name, county_name, adr_result
What I need to see is a list of ALL circuits in the first column, a list of ALL counties per circuit in the second column, a list of ALL possible adr_result entries for each county (they're the same for every county) in the third column, and then the respective count for the circuit/county/result combination-- even if it is 0. I've tried every combination of left, right and inner join (I know inner is definitely not the solution, but I'm frustrated) and just can't see where I'm going wrong.
Any help would be appreciated!
Here is a start. I can't follow your problem statement completely. For instance, what is the purposes of the cases table? None the less, when you say "ALL" records for each of those tables, I interpret it as a Cartesian product - which is implemented through the derived table in the FROM clause (notice the lack of the JOIN in that clause)
SELECT everthingjoin.circuit_name
, everthingjoin.county_name
, everthingjoin.adr_result
, COUNT(result.adr_result) AS num_results
FROM
(SELECT circuit.circuit_name, county.county_name, result.adr_result,
FROM circuit
JOIN county
JOIN result) AS everthingjoin
LEFT JOIN cases
ON cases.status_id <> "2"
AND cases.county_id = everthingjoin.county_id
LEFT JOIN circuit
ON everthingjoin.circuit_id = circuit.circuit_id
LEFT JOIN result
ON cases.result_id = result.result_id
GROUP BY adr_result, circuit_name, county_name
ORDER BY circuit_name, county_name, adr_result
try this, see if it provides some ideas:
SELECT
circuit.circuit_name
, county.county_name
, result.adr_result
, ISNULL(COUNT(result.*)) AS num_results
, COUNT(DISTINCT result.adr_result) AS num_distinct_results
FROM cases
LEFT JOIN county
ON cases.county_id = county.county_id
LEFT JOIN circuit
ON county.circuit_id = circuit.circuit_id
LEFT JOIN result
ON cases.result_id = result.result_id
WHERE cases.status_id <> "2"
GROUP BY
circuit.circuit_name
, county.county_name
, result.adr_result
ORDER BY
circuit_name, county_name, adr_result

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.