How to optimize join query with sub query - mysql

How can I optimize this join query? how can I get the latest start_dt in this query? Is any way can make it faster to load and the start_dt is the latest one? If I delete the subquery for this case, I will get the record which the start_dt is not the latest one. Please Help!!
SELECT
matrix.matrix_uuid,
matrix.name AS matrix_name,
courses.courses_uuid,
courses.name AS courses_name,
employees.employees_uuid,
CONCAT(employees.first_name,
' ',
employees.last_name) AS Name,
courses.validity,
courses.duration,
(SELECT
MAX(start_dt)
FROM
courses_schedule C
WHERE
C.courses_schedule_uuid = CS.courses_schedule_uuid) AS start_dt,
COUNT(courses.courses_uuid) AS refresher,
courses.courses_refresher_uuid,
courses_taken.overall_status,
courses_taken.status
FROM
employees
INNER JOIN
courses_taken ON courses_taken.employees_uuid = employees.employees_uuid
LEFT JOIN
courses_schedule CS ON CS.courses_schedule_uuid = courses_taken.courses_schedule_uuid
LEFT JOIN
matrix_courses matrix_courses ON matrix_courses.courses_uuid = CS.courses_uuid
LEFT JOIN
matrix ON matrix.matrix_uuid = matrix_courses.matrix_uuid
LEFT JOIN
courses ON courses.courses_uuid = matrix_courses.courses_uuid
WHERE
CS.start_dt = (SELECT
MAX(start_dt)
FROM
courses_taken CT
LEFT JOIN
courses_schedule ON courses_schedule.courses_schedule_uuid = CT.courses_schedule_uuid
LEFT JOIN
matrix_courses matrix_courses ON matrix_courses.courses_uuid = courses_schedule.courses_uuid
LEFT JOIN
roles_courses ON roles_courses.courses_uuid = matrix_courses.courses_uuid
LEFT JOIN
matrix M ON M.matrix_uuid = matrix_courses.matrix_uuid
LEFT JOIN
courses C ON C.courses_uuid = matrix_courses.courses_uuid
WHERE
C.courses_uuid = courses.courses_uuid
AND M.matrix_uuid = matrix.matrix_uuid
GROUP BY matrix.matrix_uuid , courses.courses_uuid)
AND courses_taken.overall_status = 1
AND employees.status = 2
AND IFNULL(employees.STATUS, 1) != 0
GROUP BY matrix.matrix_uuid , courses.courses_uuid , employees.employees_uuid

Related

mysql creating sort index making queries slow

We have a view table the query for the view is pasted below. The problem is that whenever we try to query items view our database start making sorting index which make the over all time of our response very slow.
CREATE VIEW items_view AS
SELECT item_detail.*, item.name, item.description, item.thumbnail_url, item.large_image_url, item.ios_url, item.android_url, item.vr_url, item.vr_updated_url, item.webgl_url, item.video_url, item.quest_url,
item.is_transferable, item.ip_id, item.brand_id, item.edition_id, item.currency_id, item.category_id, item.rarity_id, item.type_id, item.asset_id, item.artist_id, item.art_collection_id,
IFNULL(item.variation_id, 0) AS variation_id,
item.series_id, item.set_id, item.is_tradable, item.number_minted, ip.name AS ip_name, brand.name As brand_name, brand.value AS brand_image,
edition.name AS edition_name, type.name As type_name, artist.name AS artist_name, art_collection.name AS art_collection_name,
IFNULL(variation.name, '') As variation_name, variation.value AS variation_value, category.name As category_name, asset.name AS asset_name, asset.value AS asset_image,
rarity.name As rarity_name, currency.symbol, currency.code AS currency_code, currency.name AS currency_name, series.name AS series_name, sets.name AS set_name,
CONCAT(users.first_name, ' ' ,users.last_name) as owner_name, users.username AS owner_username, users.is_public_inventory, users.role, users.pub_key,
auctions.id as auction_id, auctions.expire_at as auction_expire_at, max(ab.bid_amount) AS highest_bid_amount, IF(COUNT(auctions.id) > 0 AND !auctions.is_completed AND !auctions.is_deleted
, true, false) AS is_auction, auctions.start_amount AS auction_start_amount, auctions.reserved_amount AS auction_reserved_amount, auctions.buy_now_amount AS auction_buy_now_amount,
auctions.created_at as auction_created_at, auctions.status AS auction_status, auctions.is_extended AS auction_extended, TIMESTAMPDIFF(SECOND, now(), auctions.expire_at) AS auction_expire_seconds FROM item
LEFT JOIN base_lookup AS ip ON item.ip_id = ip.id
LEFT JOIN base_lookup AS brand ON item.brand_id = brand.id
LEFT JOIN base_lookup AS edition ON item.edition_id = edition.id
LEFT JOIN base_lookup AS category ON item.category_id = category.id
LEFT JOIN base_lookup AS type ON item.type_id = type.id
LEFT JOIN base_lookup AS variation ON item.variation_id = variation.id
LEFT JOIN base_lookup AS rarity ON item.rarity_id = rarity.id
LEFT JOIN base_lookup AS series ON item.series_id = series.id
LEFT JOIN base_lookup AS sets ON item.set_id = sets.id
LEFT JOIN base_lookup AS asset ON item.asset_id = asset.id
LEFT JOIN base_lookup AS artist ON item.artist_id = artist.id
LEFT JOIN base_lookup AS art_collection ON item.art_collection_id = art_collection.id
INNER JOIN item_detail ON item.id = item_detail.parent_id
INNER JOIN users ON users.id = item_detail.owner_id
LEFT JOIN currency ON currency.id = item.currency_id
LEFT JOIN auctions on (item_detail.id = auctions.item_detail_id AND auctions.is_deleted = 0 AND auctions.is_completed = 0)
LEFT JOIN auction_bidding ab on auctions.id = ab.auction_id
WHERE item_detail.is_active = 1
group by item_detail.id
order by item_detail.id;
One of the query we are doing on this items_view that is stuck in making sorting index
SELECT
`id`, `code`, `name`, `large_image_url`,
`thumbnail_url`, `medium_thumbnail_url`, `symbol`, `ip_name`, `owner_id`,
`auction_id`, `is_auction`, `highest_bid_amount`, `auction_expire_at`,
`auction_start_amount`, `enable_sale`, `owner_name`, `role`, `amount`,
`auction_expire_seconds`, `rarity_name`, `ip_content`, `asset_content`
FROM `items_view` AS `items_view`
WHERE `items_view`.`transaction_hash` IS NOT NULL AND
`items_view`.`lobby_name` = 'live' AND
`items_view`.`is_tradable` = 1 AND
`items_view`.`is_transferring` = 0 AND
`items_view`.`is_locked` = 0 AND
`items_view`.`enable_sale` = true AND
`items_view`.`is_auction` = 0
ORDER BY `items_view`.`item_order` ASC LIMIT 24, 24;
can any give any suggest what are we doing wrong here!
Edited:
link to explain run against the above query
link to csv

how to limit record in left join

SELECT commerce_product_field_data_commerce_product__field_data_field_products.entity_id, field_products_commerce_product.nid FROM commerce_order o
join commerce_payment_transaction t on o.order_id = t.order_id
join commerce_line_item i on o.order_id = i.order_id
LEFT JOIN field_data_commerce_total s ON i.line_item_id = s.entity_id AND (s.entity_type = 'commerce_line_item' AND s.deleted = '0')
LEFT JOIN field_data_commerce_product field_data_commerce_product ON i.line_item_id = field_data_commerce_product.entity_id AND (field_data_commerce_product.entity_type = 'commerce_line_item' AND field_data_commerce_product.deleted = '0')
INNER JOIN commerce_product commerce_product_field_data_commerce_product ON field_data_commerce_product.commerce_product_product_id = commerce_product_field_data_commerce_product.product_id
LEFT JOIN
(select * from field_data_field_products)
commerce_product_field_data_commerce_product__field_data_field_products ON commerce_product_field_data_commerce_product.product_id = commerce_product_field_data_commerce_product__field_data_field_products.field_products_product_id
LEFT JOIN ( select nid as nid from node order by nid)
field_products_commerce_product
ON commerce_product_field_data_commerce_product__field_data_field_products.entity_id = field_products_commerce_product.nid LEFT JOIN (
select r.entity_id, r.field_ranges_value from field_data_field_ranges r
) r
on r.entity_id = field_products_commerce_product.nid
WHERE t.status = 'success' and i.type = 'product' and o.Uid <> 0
AND o.status IN ('completed') and o.created >= '1483228800' and o.created <= '1483315200' and r.field_ranges_value = 'Tasty Sticks'
Is my sql
It is giving me 5 results. I only need 4
One of the product id's belong to two Drupal nodes and I only want one of them
I tried changing LEFT JOIN ( select nid as nid from node order by nid) to
LEFT JOIN ( select nid as nid from node order by nid limit 1) but then I don't get any records at all. Any idea what needs changing please other than removing one of the duplicate nodes. Thanks

mysql where not in to left outer join

I have the following query and would like to convert it to using a left outer join instead of a not in to see if it would run faster that way. It's currently taking this query about 40 seconds to run on our database. I'm not familiar enough with using outer joins for this type of thing to convert it myself.
select
c.contact_id as contact_id,
c.orgid as organization_id,
c.first_name as first_name,
c.last_name as last_name,
a.address_state as state
from cnx_contact as c
inner join cnx_address as a on c.home_address_uid = a.address_uid
where a.address_state = 'OH'
and (c.orgid = 45 or c.orgid = 55)
and c.contact_id NOT IN (
select pc.contact_id
from cnx_contact as c
inner join cnx_address as a on c.home_address_uid = a.address_uid
inner join cnx_contact_group_participant as gp on c.contact_id = gp.contact_id
inner join cnx_contact_participant_role as cr on gp.participant_role_uid = cr.participant_role_uid
inner join cnx_contact_group as cg on gp.group_uid = cg.group_uid
inner join cnx_contact_group_participant as pgp on cg.primary_participant_uid = pgp.participant_uid
inner join cnx_contact as pc on pgp.contact_id = pc.contact_id
where (c.orgid = 45 or c.orgid = 55)
and cr.name = 'Applicant'
);
select
c.columns
from cnx_contact as c
inner join cnx_address as a on c.home_address_uid = a.address_uid
LEFT JOIN
(Subquery goes here) x
ON x.contact _id = c.contact_id
where a.participant_state = 'OH'
and c.orgid IN(45,55)
and x.contact_id IS NULL;

How do I get number of results (rows) in MySQL?

Normally the query below gives me only one result (row).
SELECT
`s`.`FIRMA_UNVANI` AS `FIRMA_UNVANI`,
`s`.`RECNO` AS `RECNO`,
`s`.`BOLGE` AS `BOLGE`,
`s`.`BOLGE_NO` AS `BOLGE_NO`,
`s`.`DURUM` AS `DURUM`,
l.ILCE,
IL.SEHIR,
count(i.recno) AS NUMBER_OF_WORKS
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
WHERE
1 = 1
GROUP BY
s.BOLGE
ORDER BY
IS_SAYISI
LIMIT 0,
15
I get only one result
+----------------+-------+------+---------+------+-----+----------+-----------------+
|FIRMA_UNVANI |RECNO |BOLGE |BOLGE_NO |DURUM |ILCE | SEHIR | NUMBER_OF_WORKS |
+----------------+-------+------+---------+------+-----+----------+-----------------+
|Pirana |2501 |Tekkt |58 |-1 |NT |Istanbul |1428 |
+----------------+-------+------+---------+------+-----+----------+-----------------+
Here the key is RECNO.
I want to count the results:
SELECT
count(0) AS _count
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
WHERE
1 = 1
GROUP BY
s.BOLGE
And I get this wired result:
1428
It was supposed to be 1. Isn't it?
The result is perfectly fine, since you are just counting a 0 for every row instead of i.recno, therefore both resulting in 1428.
To count the number of results, you could wrap your whole query like this to get a resultcount:
SELECT count(*) AS resultcount FROM (
SELECT
`s`.`FIRMA_UNVANI` AS `FIRMA_UNVANI`,
`s`.`RECNO` AS `RECNO`,
`s`.`BOLGE` AS `BOLGE`,
`s`.`BOLGE_NO` AS `BOLGE_NO`,
`s`.`DURUM` AS `DURUM`,
l.ILCE,
IL.SEHIR,
count(i.recno) AS NUMBER_OF_WORKS
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
GROUP BY
s.BOLGE
ORDER BY
IS_SAYISI
LIMIT 0, 15) AS temp
Also note, that WHERE 1=1 is not necessary.
You have used GROUP BY in your query so you will get each group count in result, For example if there 3 group then you will get 3 count result..
If you need to get count of result rows then please use sub query see below
SELECT count(0) AS _count FROM(
SELECT
*
FROM
`SERVISLER` `s`
LEFT JOIN KULLANICI k ON (s.BOLGE = k.KULLANICI)
LEFT JOIN kullanici_cihaz kc ON (k.RECNO = kc.KUL_RECNO)
LEFT JOIN servisler_ilceler c ON (s.RECNO = c.SER_RECNO)
INNER JOIN ILCE l ON (l.RECNO = c.ILCE_RECNO)
INNER JOIN IL ON (IL.ID = l.ILID)
LEFT JOIN ISEMRI i ON (
i.bolge = s.bolge_no
AND i.`SERVIS_DURUMU` = 1
)
WHERE
1 = 1
GROUP BY
s.BOLGE
) AS Temp;

Only getting one result from sub select in inner join in mysql

Hi I have run into a dilemma, I am doing this query:
SELECT GROUP_CONCAT(DISTINCT(ca.category_name) SEPARATOR ', ') AS categories, pr.promo_name, pr.add_value_text, c.contract_id, c.cmeal_plan, c.cmin_markup, c.civa, c.tax_include, c.hotel_id, hi.hname, hi.hstars, im.image_file, pl.plan_name, ra.price
FROM contracts AS c
INNER JOIN hotel_info AS hi ON hi.hotel_id = c.hotel_id AND hi.destination_id = '6460'
INNER JOIN images AS im ON im.foreign_id = hi.hotel_id
INNER JOIN meal_plan AS pl ON pl.plan_code = c.cmeal_plan AND pl.lang = '1'
INNER JOIN hotel_categories AS hc ON hc.hotel_id = hi.hotel_id
INNER JOIN categories AS ca ON ca.category_code = hc.category_code AND ca.lang = '1'
LEFT JOIN
(SELECT
r.hotel_id, AVG(r.double) AS price
FROM
rates AS r ) AS ra
ON ra.hotel_id = hi.hotel_id
LEFT JOIN promotions AS pr ON pr.hotel_id = hi.hotel_id AND FIND_IN_SET(c.contract_id, pr.contract_id) > 0 AND pr.book_start <= '2012-11-01' AND pr.book_end >= '2012-11-02' AND travel_start <= '2012-11-23' AND travel_end >= '2012-11-30' AND pr.lang = '1'
WHERE c.cstart <= '2012-11-01' AND c.cend >= '2012-11-01'
AND hi.status = '1'
AND im.type ='1'
GROUP BY hi.hotel_id
I am getting all the desired results except for the sub select query.. each hotel has a price but it is only giving me back one result and the rest are all null. Is there an error in my query? If any additional information is needed please let me know and thank you in advance for any help!
You are missing the GROUP BY in your subquery, so MySQL will only return one-value. If you want all hotel_id's then you need to GROUP BY that field:
SELECT GROUP_CONCAT(DISTINCT(ca.category_name) SEPARATOR ', ') AS categories,
pr.promo_name,
pr.add_value_text,
c.contract_id,
c.cmeal_plan,
c.cmin_markup,
c.civa,
c.tax_include,
c.hotel_id,
hi.hname,
hi.hstars,
im.image_file,
pl.plan_name,
ra.price
FROM contracts AS c
INNER JOIN hotel_info AS hi
ON hi.hotel_id = c.hotel_id
AND hi.destination_id = '6460'
INNER JOIN images AS im
ON im.foreign_id = hi.hotel_id
INNER JOIN meal_plan AS pl
ON pl.plan_code = c.cmeal_plan
AND pl.lang = '1'
INNER JOIN hotel_categories AS hc
ON hc.hotel_id = hi.hotel_id
INNER JOIN categories AS ca
ON ca.category_code = hc.category_code
AND ca.lang = '1'
LEFT JOIN
(
SELECT r.hotel_id, AVG(r.double) AS price
FROM rates AS r
GROUP BY r.hotel_id <-- add a GROUP BY hotel_id then you will get avg() for each hotel
) AS ra
ON ra.hotel_id = hi.hotel_id
LEFT JOIN promotions AS pr
ON pr.hotel_id = hi.hotel_id
AND FIND_IN_SET(c.contract_id, pr.contract_id) > 0
AND pr.book_start <= '2012-11-01'
AND pr.book_end >= '2012-11-02'
AND travel_start <= '2012-11-23'
AND travel_end >= '2012-11-30'
AND pr.lang = '1'
WHERE c.cstart <= '2012-11-01'
AND c.cend >= '2012-11-01'
AND hi.status = '1'
AND im.type ='1'
GROUP BY hi.hotel_id