Sql GROUP BY conflict with the arrays - mysql

I have this tables:
Projectos: Pid, value, value, value...
Sectores: ID, value, value, value...
Projectos-Sectores: ProjectID(Pid), SectorID(ID)
I am doing this query:
SELECT *
FROM `Projectos`
JOIN `Projectos-Sectores` ON `ProjectID` = `Pid`
JOIN `Sectores` ON `SectorID` = `Sectores`.`ID`
GROUP BY `Pid`
All was correct at the first. Make the joins and group correctly. There aren't 'Pid' duplicate.
The problem came when only show the last coincidence in the table "Projectos-Sectores".
I want that return an array with all coincidence between "Projectos" & "Sectores". Without repeat 'Pid'.
Any idea?

The problem came when i get the result and i want get the "sectores" linkeds to "Projectos". Only show the last coincidence in the table "Projectos-Sectores".
Yes, because you group by Pid.
I want that return an array with all coincidence between "Projectos" & "Sectores". Without repeat 'Pid'.
You could for example order by Pid and then process all lines and group in the code which processes the rows, but you will get every row in the table and multiple Pid - transformation which transforms multiple lines into a different data structure which does not look like a relational database has to be done somewhere else but the database.
SELECT *
FROM `Projectos`
JOIN `Projectos-Sectores` ON `ProjectID` = `Pid`
JOIN `Sectores` ON `SectorID` = `Sectores`.`ID`
ORDER BY `Pid`

Related

Get Conditionally Latest record from each group - without Aggregate functions or Partition

I have been trying to do this in many ways suggested.
Note: we do not want aggregate function or Partition since this is just a small part of whole Stored procedure and this is client requirement to not have it, so not in option and not possible duplicate of other existing answers / questions
I have a messages table, which has a column from and to, a foreign key to the user table, basically which user sends to whom at simplest. I also have other columns which are isSnoozed and snoozeAt for if the message is snoozed.
So the ordering is according to case. If messages is snoozed then consider snoozeAt time to Order or if not then consider sendAt. (right now we can ignore this condition while ordering, But I mentioned this since we cannot take simply MAX(id) )
I need to get recent most message from messages group by from user id
messages table like :
id -- to -- from -- isSnoozed -- snoozedAt -- sendAt ...
What I tried :
select * from ( select * from messages order by sendAt DESC) as TEMP GROUP BY TEMP.from
I tried many similar approaches but none worked.
I wasted many paid hours but can't find an approach which meets my exact requirement
NOTE: Please ignore typo in query if any, since I cant type in exact query table and names, So i typed in directly here
I figured this out by doing something like this, which could be explained in a simplified way:
select * from message where message.id in (
select
( select id from message where message.from = user.id order by CASE isSnoozed WHEN 0 THEN sendAt ELSE snoozeAt END DESC limit 1) as id
from user where user.id in ( select friends.`whoIsAdded` from friends where friends.`whoAdded` = myId)
) order by CASE isSnoozed WHEN 0 THEN sendAt ELSE snoozeAt END DESC
If I understand correctly, you just want the largest value in one of two columns. Assuming the values are never NULL, you can use greatest():
select m.*
from messages m
where greatest(m.sendAt, m.snoozedAt) =
(select max(greatest(m2.sendAt, m2.snoozedAt))
from messages m2
where m2.from = m.from
);
If the columns can be NULL, then you can use coalesce() to give them more reasonable values.

Returning all records from derived table name that also have IN statements

I'm trying to retrieve a single record from my database, BUT I don't know which table name to query until I query another record.
If I knew the table name and ID the end query would look something like this.
SELECT * FROM `materials_sheet_stock` WHERE `id` = 2
But since I do NOT know the table name or the ID in that table I'm trying to break it up a bit.
This query will successfully retrieve the table name for the above query
SELECT tb1.*
FROM (SELECT `tag_table`
FROM `materials_group_tags_mapping`
WHERE `tag_id` IN
(SELECT `materials_group_tags`.`id`
FROM `materials_group_tags`
WHERE `materials_group_tags`.`name` = "frameless_base_side_material_unexposed")) AS tb1
which in this case is materials_sheet_stock
This query will successfully retrieve the ID that I need for the above query
(SELECT `materials_group_tags_mapping`.`tag_value`
FROM `materials_group_tags_mapping`
WHERE `materials_group_tags_mapping`.`tag_id` IN
(SELECT `materials_group_tags`.`id`
FROM `materials_group_tags`
WHERE `materials_group_tags`.`name` = "frameless_base_side_material_unexposed"))
But now when I put them all together in 1 query using IN it keeps throwing errors about not finding columns, or that all tables need an alias. I've tried editing the following code for like an hour with no luck. Hopefully you guys can spot the error. Here's the final code that I am using.
SELECT tb2.*
FROM (SELECT `tag_table`
FROM `materials_group_tags_mapping`
WHERE `tag_id` IN
(SELECT `materials_group_tags`.`id`
FROM `materials_group_tags`
WHERE `materials_group_tags`.`name` = "frameless_base_side_material_unexposed") ) as tb2
WHERE tb2.`id` IN
(SELECT `materials_group_tags_mapping`.`tag_value`
FROM `materials_group_tags_mapping`
WHERE `materials_group_tags_mapping`.`tag_id` IN
(SELECT `materials_group_tags`.`id`
FROM `materials_group_tags`
WHERE `materials_group_tags`.`name` = "frameless_base_side_material_unexposed"))

Use subquery in mysql

The query below gives me 2 out of the 3 answers I'm looking for. On the sub-query select I get null instead of no
the 3 possible values for column name isCyl could be blank, yes, no
I'm not sure if the sub-query is the best way to go about it, but I don't know how else to re-state the query.
The schedule table has a series of columns to show what tasks must be completed on an assignment. Related tables store the results of the tasks if they were assigned to be completed. So I need to test if a specific task was scheduled. If so, then I need to see if the results of the task have been recorded in the related table. For brevity I am only showing one of the columns here.
SELECT s.`reckey`,
if(s.cylinders="T",
(select
if(c.areckey is not null,
"yes",
"no"
)
from cylinders c where c.areckey = s.reckey limit 1
)
,""
) as isCyl
from schedule s
where s.assignmentDate between 20161015 and 20161016
order by s.reckey
Use a LEFT JOIN, which returns NULL for columns in the child table when there's no match.
SELECT s.reckey, IF(s.cylinders = "T",
IF(c.areckey IS NOT NULL, 'yes', 'no'),
"") AS isCyl
FROM schedule AS s
LEFT JOIN cylinders AS c ON c.areckey = s.reckey
WHERE s.assignmentDate between 20161015 and 20161016
ORDER BY s.reckey
If there can be multiple rows in cylinders with the same areckey, change it to:
LEFT JOIN (select distinct areckey FROM cylinders) AS c on c.areckey = s.reckey
or use SELECT DISTINCT in the main query.

mysql query works with some particular records only not with all of the data

first image of student_detail table,second is image of payment_detail table when i fire the query like
SELECT `student_detail`.`id`,
`student_detail`.`first_name`,
`student_detail`.`last_name`,
`student_detail`.`course`,
`payment_detail`.`id`,
`student_id`,
`inst_paid_date`,
`next_inst_date`,
`paid_installment`,
`next_installment_amount`
FROM `student_detail`,`payment_detail`
WHERE MONTH(`next_inst_date`)=MONTH(now())
AND `inst_paid_date`<`next_inst_date`
AND `student_detail`.`id`=`student_id`
AND `student_id`='10'
AND `inst_paid_date` in(select max(`inst_paid_date`) from `payment_detail`)
it do not give any result when records are present like second table but if i delete student id 8 and 9 it gives the result other wise not i cant get how it is conflict with other records when perticularly set the where condition with student_id=10. thanks in advanced
The reason is that you limit your inst_paid_date to the maximum value across the entire payment_detail table. Since this maximum value is for student id 9 when it is present, this conflicts with your filter on student id 10.
Try to add the same filter to your subquery like this:
WHERE
...
AND `student_id`='10'
AND `inst_paid_date` in (select max(`inst_paid_date`)
from `payment_detail`
where `student_id` = '10')
A more generic solution would be to turn the subquery into a correlated subquery. This requires an alias on the outer reference to the payment_detail table:
...
FROM `student_detail`,`payment_detail` as `PD`
WHERE MONTH(`next_inst_date`)=MONTH(now())
AND `inst_paid_date`<`next_inst_date`
AND `student_detail`.`id`=`student_id`
AND `PD`.`student_id`='10'
AND `inst_paid_date` in(select max(`inst_paid_date`)
from `payment_detail`
where `student_id` = `PD`.`student_id`)

Need Help Speeding up an Aggregate SQLite Query

I have a table defined like the following...
CREATE table actions (
id INTEGER PRIMARY KEY AUTO_INCREMENT,
end BOOLEAN,
type VARCHAR(15) NOT NULL,
subtype_a VARCHAR(15),
subtype_b VARCHAR(15),
);
I'm trying to query for the last end action of some type to happen on each unique (subtype_a, subtype_b) pair, similar to a group by (except SQLite doesn't say what row is guaranteed to be returned by a group by).
On an SQLite database of about 1MB, the query I have now can take upwards of two seconds, but I need to speed it up to take under a second (since this will be called frequently).
example query:
SELECT * FROM actions a_out
WHERE id =
(SELECT MAX(a_in.id) FROM actions a_in
WHERE a_out.subtype_a = a_in.subtype_a
AND a_out.subtype_b = a_in.subtype_b
AND a_in.status IS NOT NULL
AND a_in.type = "some_type");
If it helps, I know all the unique possibilities for a (subtype_a,subtype_b)
eg:
(a,1)
(a,2)
(b,3)
(b,4)
(b,5)
(b,6)
Beginning with version 3.7.11, SQLite guarantees which record is returned in a group:
Queries of the form: "SELECT max(x), y FROM table" returns the value of y on the same row that contains the maximum x value.
So greatest-n-per-group can be implemented in a much simpler way:
SELECT *, max(id)
FROM actions
WHERE type = 'some_type'
GROUP BY subtype_a, subtype_b
Is this any faster?
select * from actions where id in (select max(id) from actions where type="some_type" group by subtype_a, subtype_b);
This is the greatest-in-per-group problem that comes up frequently on StackOverflow.
Here's how I solve it:
SELECT a_out.* FROM actions a_out
LEFT OUTER JOIN actions a_in ON a_out.subtype_a = a_in.subtype_a
AND a_out.subtype_b = a_in.subtype_b
AND a_out.id < a_in.id
WHERE a_out.type = "some type" AND a_in.id IS NULL
If you have an index on (type, subtype_a, subtype_b, id) this should run very fast.
See also my answers to similar SQL questions:
Fetch the row which has the Max value for a column
Retrieving the last record in each group
SQL join: selecting the last records in a one-to-many relationship
Or this brilliant article by Jan Kneschke: Groupwise Max.