I have an existing query:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
which is defined in a php page. I've been asked to add another parameter which is stored in another table, the problem is, on sds_product can have many "communications" which is basicly like a comment with a date_created. For example, if I wanted a list of communications for a given product, I would do:
select * from sds_product_comms as pc
join sds_comms c on pc.comms_id = c.comms_id
where prod_id = 2546
I wanted to do this directly in SQL, so is it possible to somehow make a sub query to stick these two together, without creating duplicate rows in the initial query.
For example I don't want 5 rows of the same product with the same max date_created.
desc sds_comms
'comms_id', 'int(10) unsigned', 'NO', 'PRI', '', 'auto_increment'
'method', 'int(10) unsigned', 'NO', '', '', ''
'dialogue', 'varchar(200)', 'NO', '', '', ''
'reply_id', 'int(10) unsigned', 'NO', '', '', ''
'comm_to', 'varchar(60)', 'NO', '', '', ''
'comm_from', 'varchar(60)', 'NO', '', '', ''
'man_id', 'int(10) unsigned', 'NO', '', '', ''
'supp_id', 'int(10) unsigned', 'NO', '', '', ''
'user_id', 'int(10) unsigned', 'NO', '', '', ''
'date_created', 'timestamp', 'NO', '', 'CURRENT_TIMESTAMP', ''
Sorry for the detail but its hard to get my head around it!
EDIT:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID
,lastContact
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
left join sds_product_comms pc on pc.prod_id = p.productID
left join (select comms_id, max(date_created) as lastContact from sds_comms group by comms_id ) as c2 on pc.comms_id = c2.comms_id
where productID=555;
would this be a correct way of doing it? With this method I'm getting different lastContact dates for the same productID :(
Try this:
select ProductLinesID, ProductID, ProductName, ProductCatalog, ManufacturerName,
productMSDSStatus, productStatusDesc, productStatusIcon, DATE_FORMAT(dateAdded,'%d/%m/%Y') As dateAdded, DATE_FORMAT(ProductRevision,'%d/%m/%Y') as ProductRevision,
ManufacturerID, SupplierName, ProductID, DATE_FORMAT(dateLatestCheck, '%d/%m/%Y') as dateLatestCheck,s.SupplierID,
c.date_created as lastContact
from sds_productlines pl
right join sds_products p on p.ProductID = pl.productlinesProductID
left join sds_manufacturer m on p.ProductManufacturer = m.ManufacturerID
left join sds_product_status ps on p.productMSDSStatus = ps.productStatusID
left join sds_departments d on pl.ProductLinesDepartmentID = d.DepartmentID
left join sds_hospitals h on h.hospitalID = d.DepartmentHospitalID
left join sds_supplier s on s.SupplierID = pl.SupplierID
left join sds_product_comms pc on pc.prod_id = p.productID
left join comms_id c on c.comms_id = pc.comms_id and c.date_created = (select max(date_created) from comms_id c2 where c2.comms_id = pc.comms_id)
where productID=555;
If I understand you correctly, you want a parameter that is in a table that is on the N end of a 1:N relationship and you want to have only 1 of each.
You can try grouping your data using GROUP BY.
Something like:
SELECT sds_product_comms.*, MAX(sds_comms.created_at) FROM sds_product_comms AS pc
JOIN sds_comms c ON pc.comms_id = c.comms_id
GROUP BY sds_product_comms.prod_id
Related
Please help me to optimize below Query -
SELECT DISTINCT
al.displayName AS 'Brand',
al.locationName AS 'Campus',
pg.groupName AS 'School Phase',
result.programName AS 'Grade',
pc.categoryName AS 'Grade Category',
result.batchName AS 'Intake',
result.periodName AS 'Period',
admission.id AS 'ADmission',
result.stdName AS 'Student Name',
usr.code AS 'Student Id',
result.courseName AS 'Subject',
result.courseVariant AS 'Subject Variant',
cc.categoryName AS 'Subject Category',
fac.printName AS 'Teacher',
result.planPrintName AS 'Scheme',
planRank.marksObtainedFrom AS 'Maximum Marks',
planRank.gradeObtainedFrom AS 'Maximum Grade',
planRank.obtainedMarks AS 'Subject Level Marks',
planRank.grade AS 'Subject Grade',
planRank.obtainedMarks AS 'Percentage',
planRank.status AS 'Result Status',
result.levelOnePrintName AS 'Type',
typeRank.effectiveMarks AS 'Type Marks',
typeRank.grade AS 'Type Grade',
typeRank.status AS 'Type Result Status',
result.levelTwoPrintName AS 'Sub Type',
subTypeRank.effectiveMarks AS 'Sub Type Marks',
subTypeRank.grade AS 'Sub Type Grade',
subTypeRank.status AS 'Sub Type Result Status',
result.levelThreePrintName AS 'Method',
result.effectiveMarks AS 'Method Marks',
result.grade AS 'Method Grade',
result.status AS 'Method Result Status',
CASE
WHEN evntDetail.eventName IS NULL THEN evnt.detailSequenceNumber
WHEN evntDetail.eventName IS NOT NULL THEN evntDetail.eventName
ELSE NULL
END AS 'Event',
eventMarks.effectiveMarks AS 'Event Marks',
eventMarks.finalGrade AS 'Event Grade'
FROM
marksheet AS result
INNER JOIN
admission AS admission ON admission.id = result.admissionId
INNER JOIN
users AS usr ON usr.id = result.studentId
INNER JOIN
academy_location AS al ON al.id = admission.academyLocationId
INNER JOIN
programs AS prgm ON prgm.id = result.programId
LEFT OUTER JOIN
program_group AS pg ON pg.id = prgm.programGroupId
LEFT OUTER JOIN
program_category AS pc ON pc.id = prgm.programCategoryId
LEFT OUTER JOIN
courses AS course ON course.id = result.courseId
LEFT OUTER JOIN
course_category AS cc ON cc.id = course.courseCategoryId
LEFT OUTER JOIN
program_batch_course_param AS param ON result.courseVariantId = param.courseVarientId
AND result.periodId = param.progBatchPeriodConfigId
LEFT OUTER JOIN
prog_batch_course_faculty AS pbcf ON pbcf.progBatchCourseParamId = param.id
LEFT OUTER JOIN
users AS fac ON fac.id = pbcf.facultyId
LEFT OUTER JOIN
evaluation_plan_rank AS planRank ON result.admissionId = planRank.admissionId
AND (result.courseVariantId = planRank.courseVariantId
OR planRank.courseVariantId IS NULL)
AND result.sectionId = planRank.sectionId
AND result.periodId = planRank.periodId
AND result.evaluationPlanId = planRank.evaluationPlanId
LEFT OUTER JOIN
evaluation_plan_level_one_rank AS typeRank ON result.admissionId = typeRank.admissionId
AND (result.courseVariantId = typeRank.courseVariantId
OR typeRank.courseVariantId IS NULL)
AND result.periodId = typeRank.periodId
AND result.sectionId = typeRank.sectionId
AND result.evaluationPlanLevelOneId = typeRank.evaluationPlanLevelOneId
LEFT OUTER JOIN
evaluation_plan_level_two_rank AS subTypeRank ON result.admissionId = subTypeRank.admissionId
AND (result.courseVariantId = subTypeRank.courseVariantId)
AND result.periodId = subTypeRank.periodId
AND result.sectionId = subTypeRank.sectionId
AND result.evaluationPlanLevelTwoId = subTypeRank.evaluationPlanLevelTwoId
INNER JOIN
eval_seq_detail AS evnt ON result.evaluationPlanThreeId = evnt.evalSequenceId
LEFT OUTER JOIN
examination_result AS eventMarks ON result.admissionId = eventMarks.admissionId
AND (result.courseVariantId = eventMarks.courseVariantId
OR eventMarks.courseVariantId IS NULL)
AND result.sectionId = eventMarks.sectionId
AND result.periodId = eventMarks.periodId
AND evnt.id = eventMarks.evaluationDetailSequenceId
LEFT OUTER JOIN
evaluation_type_course typeCourse ON eventMarks.courseVariantId = typeCourse.courseVariantId
AND eventMarks.periodId = typeCourse.periodId
LEFT OUTER JOIN
exam_event_detail evntDetail ON eventMarks.evaluationDetailSequenceId = evntDetail.eventId
AND evntDetail.evaluationTypeCourseId = typeCourse.id
WHERE
eventMarks.examResultStatus IS NOT NULL
AND result.evaluationPlanId IS NOT NULL
AND result.evaluationPlanLevelOneId IS NOT NULL
AND result.evaluationPlanLevelTwoId IS NOT NULL
AND result.evaluationPlanThreeId IS NOT NULL;
In tables marksheet = '740119' and examination_result = '4891575' approx records.
when I execute query then it will take around 10 min and also show time out error, as data-set is large.
I applied indexes on table's for performance but still Query take lots of time.
I applied Explain on Query to check status -
Add the keyword "STRAIGHT_JOIN" to you query. It looks like you have everything in proper logical alignment. You are querying from the main table and joining to all the lookup tables secondary. MySQL sometimes tries to optimize based on table row sizes and will look at a smaller table as a more beneficial path and can choke.
SELECT STRAIGHT_JOIN (rest of query)
Tells MySQL to do the query in the order you provided, don't think for me.
Now, that said, you don't really have a WHERE clause that may be taking advantage of an index. To prevent the need of having to go to every data page for the records, if you have an index on the where clauses, the engine can pre-qualify those records where not null via the index. Assuming that each evaluation plan is an integer (numeric) based "ID" value, I would add an index on
( evaluationPlanId, evaluationPlanLevelOneId, evaluationPlanLevelTwoId, evaluationPlanThreeId )
I would like to condition when to GROUP_CONCAT my results. I can't figure out the way how to separate my 'category' and 'condition' results.
SELECT d.company_name AS 'organisation name',
GROUP_CONCAT(DISTINCT tag.tag) AS 'category',
GROUP_CONCAT(DISTINCT tag.tag) AS 'conditions', d.contact_describtion AS 'description', d.tel, d.tel2, d.mobile, d.email, d.email2, d.web, d.web2, d.address, d.town, d.county, d.post_code AS 'post code', IF(d.state = 1, "published", "unpublished") AS 'status',d.contact_page_notes AS 'contact history', d.last_contacted_date AS 'last contacted', d.last_updated_date AS 'last updated'
FROM jds4a_directory d INNER JOIN
jds4a_tags_resources res
on d.id = res.resource_id INNER JOIN
jds4a_tags tag
on tag.id = res.tag_id
WHERE tag.category = 'condition' OR tag.category = 'category'
GROUP BY res.resource_id
What I want to achieve is to only display category tags under the category and only display condition tags under conditions
Use case. You are also returning way too many columns, I think:
SELECT d.company_name AS organisation_name,
GROUP_CONCAT(DISTINCT (CASE WHEN tag.category = 'condition' THEN tag.tag END)) AS categories,
GROUP_CONCAT(DISTINCT (CASE WHEN tag.category = 'category' THEN tag.tag END)) AS conditions
FROM jds4a_directory d INNER JOIN
jds4a_tags_resources res
on d.id = res.resource_id INNER JOIN
jds4a_tags tag
on tag.id = res.tag_id
WHERE tag.category IN ('condition', 'category')
GROUP BY d.company_name;
Notes:
The SELECT columns should be consistent with the GROUP BY columns. Don't overload with extraneous columns.
GROUP BY should match the unaggregated keys/expressions in the SELECT.
Use IN instead of a bunch of ORs -- easier to maintain, write, and less prone to error.
Use single quotes for string and date constants. Don't use them for column aliases.
You can try below Query:
SELECT d.company_name AS 'organisation name',
GROUP_CONCAT(DISTINCT tag.tag) AS 'category',
GROUP_CONCAT(DISTINCT tag1.tag) AS 'conditions', d.contact_describtion AS 'description', d.tel, d.tel2, d.mobile, d.email, d.email2, d.web, d.web2, d.address, d.town, d.county, d.post_code AS 'post code', IF(d.state = 1, "published", "unpublished") AS 'status',d.contact_page_notes AS 'contact history', d.last_contacted_date AS 'last contacted', d.last_updated_date AS 'last updated'
FROM jds4a_directory d
INNER JOIN jds4a_tags_resources res
on d.id = res.resource_id
LEFT JOIN jds4a_tags tag
on tag.id = res.tag_id AND tag.category = 'category'
LEFT JOIN jds4a_tags tag1
on tag1.id = res.tag_id AND tag1.category = 'condition'
GROUP BY res.resource_id
Have not tried this query. But it should work. Basically you need to join on jds4a_tags table one more time with conditional tag name
I have two tables. 'First' table contains 2 ids of 'second' table. v2 and v3 are second table's IDs.
First:
`id`, `mem`, `v2`, `v3`, `v2_amt`, `v3_amt`
1, 'test', 1, 2, '10', '20'
2, 'test2', 1, 2, '10', ''
Second:
`id`, `name`
1, 'anna'
2, 'teena'
When I'm joining,
SELECT f.mem, s.name
FROM `first` f
JOIN second s
ON f.v2 = s.id
AND f.v2_amt !=""
AND (f.v3 = s.id AND f.v3_amt !='')
WHERE f.id = '1'
GROUP BY s.id
Currenlty it return none.
Is any way to union both tables to achieve output as following..??
`mem`, `name`
test, 'anna'
test, 'teena'
For fetching 2 id of first table.
SELECT f.mem, s.name
FROM `first` f
JOIN second s
ON f.v2 = s.id
AND f.v2_amt !=""
AND (f.v3 = s.id AND f.v3_amt !='')
WHERE f.id = '2'
GROUP BY s.id
It should return as, seems v3_amt is empty.
`mem`, `name`
test, 'anna'
You should empty the v3 column on insert if v3_amt="" similarly on v2 and try this query
Select f.v2,f.v3,f.v2_amt,f.v3_amt,s.name from first as f join second as s on
(f.v2 = s.id OR f.v3 = s.id) and (f.v2_amt!="" OR f.v3_amt!="") where f.id=2
:)
You should use OR.
SELECT f.mem, s.name FROM `first` f JOIN `second` s
ON f.v2 = s.id AND f.v2_amt !="" OR (f.v3 = s.id AND f.v3_amt !='')
WHERE f.id = '1'
you can use left join and OR for this case
select ft.mem, st.name from first_table ft
LEFT JOIN second_table st ON (ft.v2 = st.id AND ft.v2_amt !="") OR (ft.v3 = st.id AND ft.v3_amt !="")
WHERE ft.id = '1'
We have a SQL query that produces a report. We have sucussfully joined our settings table to update the integer values with the correct items, We have also used a union to display our three types of users.
We would like to take this query and order it by the e_job.objId field, however we are finding it really difficult with the multiple joins and unions.
If anyone could help it would be appreciated.
SELECT e_job.objId AS 'Job Number', e_student.Lastname AS 'Last Name', e_student.Name AS 'First Name', e_asset.objId AS 'Asset Number', e_asset.aSerialNumber AS 'Serial Number', si.sLabel AS 'Issue', srt.sLabel AS 'Repair Type', ss.sLabel As 'Status', e_job.note 'Description',FROM_UNIXTIME(e_job.jCreatedAt,'%d/%m/%y') AS 'Date Created'
FROM e_job
INNER JOIN e_student ON e_job.jName = e_student.username
INNER JOIN e_asset ON e_job.jAsset = e_asset.aId
LEFT JOIN e_settings si ON si.sKey = 'job_issue' AND si.sValue = e_job.jIssue
LEFT JOIN e_settings srt ON srt.sKey = 'job_rep_type' AND srt.sValue = e_job.jRepairType
LEFT JOIN e_settings ss ON ss.sKey = 'job_status' AND ss.sValue = e_job.jStatus
WHERE jStatus = 1 && jRepairType = 2
UNION
SELECT e_job.objId AS 'Job Number', e_teachers.Lastname AS 'Last Name', e_teachers.Name AS 'First Name', e_asset.objId AS 'Asset Number', e_asset.aSerialNumber AS 'Serial Number', si.sLabel AS 'Issue', srt.sLabel AS 'Repair Type', ss.sLabel As 'Status', e_job.note 'Description',FROM_UNIXTIME(e_job.jCreatedAt,'%d/%m/%y') AS 'Date Created'
FROM e_job
INNER JOIN e_teachers ON e_job.jName = e_teachers.username
INNER JOIN e_asset ON e_job.jAsset = e_asset.aId
LEFT JOIN e_settings si ON si.sKey = 'job_issue' AND si.sValue = e_job.jIssue
LEFT JOIN e_settings srt ON srt.sKey = 'job_rep_type' AND srt.sValue = e_job.jRepairType
LEFT JOIN e_settings ss ON ss.sKey = 'job_status' AND ss.sValue = e_job.jStatus
WHERE jStatus = 1 && jRepairType = 2
UNION
SELECT e_job.objId AS 'Job Number', e_supportStaff.Lastname AS 'Last Name', e_supportStaff.Name AS 'First Name', e_asset.objId AS 'Asset Number', e_asset.aSerialNumber AS 'Serial Number', si.sLabel AS 'Issue', srt.sLabel AS 'Repair Type', ss.sLabel As 'Status', e_job.note 'Description',FROM_UNIXTIME(e_job.jCreatedAt,'%d/%m/%y') AS 'Date Created'
FROM e_job
INNER JOIN e_supportStaff ON e_job.jName = e_supportStaff.username
INNER JOIN e_asset ON e_job.jAsset = e_asset.aId
LEFT JOIN e_settings si ON si.sKey = 'job_issue' AND si.sValue = e_job.jIssue
LEFT JOIN e_settings srt ON srt.sKey = 'job_rep_type' AND srt.sValue = e_job.jRepairType
LEFT JOIN e_settings ss ON ss.sKey = 'job_status' AND ss.sValue = e_job.jStatus
WHERE jStatus = 1 && jRepairType = 2
Thank you
If you add an ORDER BY clause to the end of the query it should apply to the entire result set. You can try adding this:
ORDER BY `Job Number`
Also, you don't need to specify aliases in union queries other than the first one. The first set of aliases are what stick.
I'm trying to find all the grandchildren for a specific id, but I can't seem to get my joins correct. The below code works, but it I need to get the products associated with it from the products table.
SELECT b.category_id, b.category_name, b.parent, a.parent
FROM categories AS a, categories AS b
WHERE a.category_id = b.parent AND a.parent = 119
When I try to JOIN the products table I keep getting an error:
SELECT *
FROM products p
INNER JOIN products_categories pc
ON p.product_id = pc.product_id
INNER JOIN (
SELECT b.category_id, b.category_name, b.parent, a.parent
FROM categories AS a, categories AS b
WHERE a.category_id = b.parent AND a.parent = 119
)x
My desired result would be to have the following: (NOTE: Check out my SQL Fiddle to see the schema in code view)
(76, 'BR134', 'LEA530664', 'ITEM1234', 1499.99, 'yes', 'This is a nice gun'),
(77, 'mZCXGT', 'LEA471061', 'qwer345', 89.99, 'yes', 'Testing!'),
(78, 'ert', 'LEA023991', 'asdf34', 129.99, 'yes', 'Another test to get this right!'),
(79, 'model test', 'LEA355935', 'item test', 119.99, 'yes', 'This is another test dammit!'),
(80, 'CZV1354', 'LEA741837', 'LI-1234', 1299.99, 'yes', 'This is a hipoint weapon!'),
(81, 'PINK12G', 'LEA008558', 'PINK-SHG', 89.99, 'yes', 'YEP! This is pink!'),
(82, 'BOWTECH', 'LEA762521', 'asdf', 899.99, 'yes', 'This is a test!'),
(83, 'LX32', 'LEA346903', 'MADEUP', 1499.99, 'yes', 'This is Carters gun.');
SQL Fiddle:
http://sqlfiddle.com/#!2/dd66c/2
Here's my schema:
I think you are looking for this (I have added category names for "debuggability"):
SELECT
p.product_id
, p.model
, p.sku
, p.item_number
, p.msrp
, p.availability
, p.description
, grand_child.category_name AS grand_child_category
, child.category_name AS child_category
, parent.category_name AS parent_category
FROM categories parent
INNER JOIN categories child
ON parent.category_id = child.parent
INNER JOIN categories grand_child
ON child.category_id = grand_child.parent
INNER JOIN products_categories pc
ON grand_child.category_id = pc.category_id
INNER JOIN products p
ON p.product_id = pc.product_id
WHERE parent.category_id = 119