I'm looking for a more efficient way to write this query which displays meta values for an order in a single row. I can't think of a solution myself but before I redesign the database I wanted to see if anyone has any ideas to avoid 11 INNER JOINs. Here is my query which currently takes 20 seconds to load a single result (which is obviously not practical):
SELECT
o1.order_id,
o1.order_status AS 'Order Status',
m3.meta_value AS 'UOP Order Status',
m4.meta_value AS 'UOP Registration Date',
m5.meta_value AS 'UOP Banner Registration',
m6.meta_value AS 'UOP Banner Date',
m7.meta_value AS 'Course Completion Date',
m8.meta_value AS 'Course Grade',
m9.meta_value AS 'Grade Submission Date',
m1.meta_value AS 'First Name',
m2.meta_value AS 'Last Name',
o1.order_date AS 'Order Date',
m10.meta_value,
m11.meta_value,
o1.partner_id AS 'Source'
FROM partner_orders o1
INNER JOIN partner_order_meta m1
ON (o1.order_id = m1.order_id)
INNER JOIN partner_order_meta m2
ON (o1.order_id = m2.order_id)
INNER JOIN partner_order_meta m3
ON (o1.order_id = m3.order_id)
INNER JOIN partner_order_meta m4
ON (o1.order_id = m4.order_id)
INNER JOIN partner_order_meta m5
ON (o1.order_id = m5.order_id)
INNER JOIN partner_order_meta m6
ON (o1.order_id = m6.order_id)
INNER JOIN partner_order_meta m7
ON (o1.order_id = m7.order_id)
INNER JOIN partner_order_meta m8
ON (o1.order_id = m8.order_id)
INNER JOIN partner_order_meta m9
ON (o1.order_id = m9.order_id)
INNER JOIN partner_order_meta m10
ON (o1.order_id = m10.order_id)
INNER JOIN partner_order_meta m11
ON (o1.order_id = m11.order_id)
WHERE m1.meta_key = 'First Name' AND m2.meta_key = 'Last Name' AND m3.meta_key = 'uop_order_status' AND m4.meta_key = 'uop_registration_date' AND m5.meta_key = 'uop_banner_registration' AND m6.meta_key = 'uop_banner_registration_date' AND m7.meta_key = 'course_completion_date' AND m8.meta_key = 'course_grade' AND m9.meta_key = 'grade_submission_date' AND m10.meta_key = 'Course Number' AND m11.meta_key = 'Course Title';
Use grouping:
SELECT
o1.order_id,
o1.order_status AS `Order Status`,
MAX(IF(m.meta_key = 'First Name', m.meta_value, NULL)) AS `First Name`,
MAX(IF(m.meta_key = 'Last Name', m.meta_value, NULL)) AS `Last Name`,
...
FROM partner_orders AS o1
JOIN partner_order_meta AS m ON o1.order_id = m.order_id
GROUP BY o1.order_id
Related
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 need help understanding WHERE the completion state of a resource (file) in Moodle is stored.
Please see attached images for more information.
The flag next to the file is marked as completed once the user viewed
This is setup in the Completion settings of this file/resource.
I need to generate a SQL report showing the file and the completion state.
I already have the "difficult part" of the query, I just need to select the completion state from "table-X" and wha-la!
Thank you.
SELECT r.id, r.name, r.course, cmc.userid, cmc.completionstate, cmc.viewed
FROM mdl_course_modules_completion cmc
JOIN mdl_course_modules cm ON cm.id = cmc.coursemoduleid
JOIN mdl_modules m ON m.id = cm.module AND m.name = 'resource'
JOIN mdl_resource r ON r.id = cm.instance
The completionstate and viewed constants are in /lib/completionlib.php
eg:
COMPLETION_INCOMPLETE = 0
COMPLETION_COMPLETE = 1
COMPLETION_COMPLETE_PASS = 2
COMPLETION_COMPLETE_FAIL = 3
COMPLETION_COMPLETE_RPL = 4 // This is used in Totara.
COMPLETION_NOT_VIEWED = 0
COMPLETION_VIEWED = 1
Okay, so I found the table and column.
Table: mdl_course_modules_completion
Column: Viewed
I will post my report code below, hopefully this might help the next guy.
Take Note: I joined all the module types to the query and filter only for type quiz, lesson and resource in the where statement. I did this because I am only interested in these 3 types. I however did not remove the joins because someone else might need the code.
SELECT DISTINCT
u.firstname AS 'Firstname'
,u.lastname AS 'Lastname'
,u.institution AS 'Institution'
,u.department AS 'Department'
,u.city AS 'City/Site'
,cc.name AS 'Course'
,c.fullname AS 'Module'
,CASE
WHEN mf.name IS NOT NULL THEN mf.name
WHEN mb.name IS NOT NULL THEN mb.name
WHEN mr.name IS NOT NULL THEN mr.name
WHEN mu.name IS NOT NULL THEN mu.name
WHEN mq.name IS NOT NULL THEN mq.name
WHEN mp.name IS NOT NULL THEN mp.name
WHEN ml.name IS NOT NULL THEN ml.name
ELSE NULL
END AS activityname
,CASE WHEN mdl.name = 'lesson' THEN CASE WHEN mlg.id IS NOT NULL AND mlg.completed IS NOT NULL THEN 'Complete' ELSE 'Incomplete' END
WHEN mdl.name = 'quiz' THEN CASE WHEN mqg.id IS NOT NULL AND mqg.timemodified IS NOT NULL THEN 'Complete' ELSE 'Incomplete' END
WHEN mdl.name = 'resource' THEN CASE WHEN cmc.viewed = 1 THEN 'Complete' ELSE 'Incomplete' END
END AS Status
FROM
mdl_user u
JOIN mdl_user_enrolments ue ON ue.userid = u.id
JOIN mdl_enrol E on E.id = ue.enrolid
JOIN mdl_course c ON c.id = E.courseid
JOIN mdl_course_categories cc ON c.category = cc.id
JOIN mdl_course_modules cm ON cm.course = c.id
JOIN mdl_course_modules_completion cmc ON cmc.coursemoduleid = cm.id
JOIN mdl_context AS ctx ON ctx.contextlevel = 70 AND ctx.instanceid = cm.id
JOIN mdl_modules AS mdl ON cm.module = mdl.id
LEFT JOIN mdl_forum AS mf ON mdl.name = 'forum' AND cm.instance = mf.id
LEFT JOIN mdl_book AS mb ON mdl.name = 'book' AND cm.instance = mb.id
LEFT JOIN mdl_resource AS mr ON mdl.name = 'resource' AND cm.instance = mr.id
LEFT JOIN mdl_url AS mu ON mdl.name = 'url' AND cm.instance = mu.id
LEFT JOIN mdl_quiz AS mq ON mdl.name = 'quiz' AND cm.instance = mq.id
LEFT JOIN mdl_quiz_grades mqg ON mqg.quiz = mq.id
LEFT JOIN mdl_page AS mp ON mdl.name = 'page' AND cm.instance = mp.id
LEFT JOIN mdl_lesson AS ml ON mdl.name = 'lesson' AND cm.instance = ml.id
LEFT JOIN mdl_lesson_grades mlg ON mlg.lessonid = ml.id
LEFT JOIN mdl_files AS f ON f.contextid = ctx.id
LEFT JOIN mdl_files_reference fr ON fr.id = f.referencefileid
WHERE mdl.name in ('quiz','lesson','resource')
ORDER BY firstname,Lastname,cc.name,c.fullname
My join query is here i want how much % between Sale Price Original Price in MySql query?
SELECT DISTINCT (CASE
WHEN b.method = 'checkmo' THEN 'Check / Money order'
ELSE 'Credit Card (saved)'
END) AS 'Payment Method',a.increment_id as 'Ref-Order Number',a.store_name as 'purchased From (Store)', a.created_at as 'Purchased On',CONCAT (customer_firstname,' ',customer_lastname) as 'Sender-Store Name',CONCAT (customer_firstname,' ',customer_lastname) as 'Attention',c.telephone as 'Phone',c.street as 'Shipping Street',c.city as 'Shipping City',c.region as 'Shipping State',c.postcode as 'Shipping Zip',d.Sku as 'SKU',name as 'Name', round(d.base_price,2) as 'Sale Price', round(e.price,2) as 'Original Price', round(base_grand_total,2) as 'G.T.(Base)',round(grand_total,2) as 'G.T.(Purchased)',round(d.qty_ordered) as 'Product Qty Ordered',status as 'Status',a.coupon_code as 'Coupon Code',a.customer_email as 'Email'
FROM sales_flat_order_item d left outer join sales_flat_order a on d.order_id = a.entity_id left outer join sales_flat_order_payment b on d.order_id = b.entity_id left outer join sales_flat_order_address c on a.customer_id = c.entity_id left outer join catalog_product_index_price
e on d.product_id = e.entity_id where status != 'canceled' and d.base_price > 0 and e.customer_group_id = 0
I solved it by adding round((e.price/d.base_price)*100) as 'Percentage' to the SELECT statement:
SELECT DISTINCT (CASE
WHEN b.method = 'checkmo' THEN 'Check / Money order'
ELSE 'Credit Card (saved)'
END) AS 'Payment Method',a.increment_id as 'Ref-Order Number',a.store_name as 'purchased From (Store)', a.created_at as 'Purchased On',CONCAT (customer_firstname,' ',customer_lastname) as 'Sender-Store Name',CONCAT (customer_firstname,' ',customer_lastname) as 'Attention',c.telephone as 'Phone',c.street as 'Shipping Street',c.city as 'Shipping City',c.region as 'Shipping State',c.postcode as 'Shipping Zip',d.Sku as 'SKU',name as 'Name', round(e.price,2) as 'Original Price', round(d.base_price,2) as 'Sale Price', round((d.base_price/e.price)*100) as 'Percentage', round(base_grand_total,2) as 'G.T.(Base)',round(grand_total,2) as 'G.T.(Purchased)',round(d.qty_ordered) as 'Product Qty Ordered',status as 'Status',a.coupon_code as 'Coupon Code',a.customer_email as 'Email'
FROM sales_flat_order_item d left outer join sales_flat_order a on d.order_id = a.entity_id left outer join sales_flat_order_payment b on d.order_id = b.entity_id left outer join sales_flat_order_address c on a.customer_id = c.entity_id left outer join catalog_product_index_price
e on d.product_id = e.entity_id where status != 'canceled' and d.base_price > 0 and e.customer_group_id = 0
am I doing this SQL code right? The query works, but it takes really long, 161 seconds (with LIMIT 2 set). Is there a way to optimize that?
SELECT p.itemid as `id`,
p.title as `name`,
pb.data_txt as `birthdate`,
pc.data_txt as `growth`,
pd.data_txt as `eyes`,
pe.data_txt as `desc`,
pf.data_txt as `weight`,
pg.data_txt as `sex`,
ph.data_txt as `hair`,
pi.data_txt as `dimensions`,
pj.data_txt as `lang`,
pk.data_txt as `school`,
pl.data_txt as `know`,
p.image as `image`
FROM `jos_sobi2_item` p
INNER JOIN `jos_sobi2_fields_data` AS pb ON pb.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pc ON pc.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pd ON pd.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pe ON pe.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pf ON pf.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pg ON pg.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS ph ON ph.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pi ON pi.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pj ON pj.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pk ON pk.itemid = p.itemid
INNER JOIN `jos_sobi2_fields_data` AS pl ON pl.itemid = p.itemid
WHERE
pb.fieldid = 16 AND
pc.fieldid = 17 AND
pd.fieldid = 21 AND
pe.fieldid = 13 AND
pf.fieldid = 18 AND
pg.fieldid = 19 AND
ph.fieldid = 20 AND
pi.fieldid = 22 AND
pj.fieldid = 25 AND
pk.fieldid = 23 AND
pl.fieldid = 24
LIMIT 2
I think part of the INNER JOIN is bad.
Try using conditional aggregation instead:
SELECT p.itemid as `id`, p.title as `name`,
max(case when fd.fieldid = 16 then data_txt end) as birthdate,
max(case when fd.fieldid = 17 then data_txt end) as growth,
. . .
FROM `jos_sobi2_item` p INNER JOIN
`jos_sobi2_fields_data` fd
ON fd.itemid = p.itemid
GROUP BY p.itemId, p.title;
You can add as many fields as you like, and adding more fields will have little impact on performance.
If you really want this even faster, you can do the limit on the first table:
SELECT p.itemid as `id`, p.title as `name`,
max(case when fd.fieldid = 16 then data_txt end) as birthdate,
max(case when fd.fieldid = 17 then data_txt end) as growth,
. . .
FROM (select p.*
from `jos_sobi2_item` p
limit 2
) p INNER JOIN
`jos_sobi2_fields_data` fd
ON fd.itemid = p.itemid
GROUP BY p.itemId, p.title;
Can anyone see an obvious error in this query?
function getFixtureDetails($league, $date, $status)
{
global $database;
$q = "SELECT g.id, g.home_user, g.home_user2, g.away_user, g.away_user2, g.home_score, g.away_score, hteam.team AS hometeam, ateam,team AS awayteam,
huser.username AS home_username, huser2.username AS home_username2, auser.username AS away_username, auser2.username AS away_username2
FROM ".TBL_FOOT_GAMES." g
INNER JOIN ".TBL_FOOT_TEAMS." hteam ON hteam.id = g.home_team
INNER JOIN ".TBL_FOOT_TEAMS." ateam ON ateam.id = g.away_team
INNER JOIN ".TBL_USERS." huser ON huser.id = g.home_user
LEFT JOIN ".TBL_USERS." huser2 ON huser2.id = g.home_user2
INNER JOIN ".TBL_USERS." auser ON auser.id = g.away_user
LEFT JOIN ".TBL_USERS." auser2 ON auser2.id = g.away_user2
WHERE g.fixture_date = '$date' AND g.leagueid = '$league' AND (g.type = '2' OR g.type = '12' OR g.type = '22' OR g.type = '32') AND g.status = '$status'
ORDER BY g.fixture_date";
return mysql_query($q, $database->myConnection());
}
Thanks
Edit, error message...
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource
ateam.team AS awayteam,
not
ateam,team AS awayteam,