How can optimize the query with join - mysql

I have a query large query which is taking more time to execute.How can i reduce the execution time of the query using Join.Here is myt query.
SELECT mdi.Member_Id,
dp.Payment1_Date AS Duchess_Payment1_Date,
dp.Payment1_Method AS Duchess_Payment1_Method,
dp.Payment1_By AS Duchess_Payment1_By,
dp.Payment1_Amount AS Duchess_Payment1_Amount,
dp.Payment2_Date AS Duchess_Payment2_Date,
dp.Payment2_Method AS Duchess_Payment2_Method,
dp.Payment2_By AS Duchess_Payment2_By,
dp.Payment2_Amount AS Duchess_Payment2_Amount,
mha.First_Name AS Member_First_Name,
mha.Middle_Name AS Member_Middle_Name,
mha.Last_Name AS Member_Last_Name,
mha.Address AS Member_Address,
mha.City AS Member_City,
mha.State AS Member_State,
mha.Zip AS Member_Zip,
mha.Nickname AS Member_Nickname,
mha.Phone AS Member_Phone,
mha.Mobile AS Member_Mobile,
mha.Email AS Member_Email,
mwa.First_Name AS Work_First_Name,
mwa.Middle_Name AS Work_Middle_Name,
mwa.Last_Name AS Work_Last_Name,
mwa.Address AS Work_Adrress,
mwa.City AS Work_City,
mwa.State AS Work_State,
mwa.Zip AS Work_Zip,
mwa.Phone AS Work_Phone,
(CASE WHEN mha.Preferred=0 THEN 'Work Address' WHEN mha.Preferred=1 THEN 'Home Address' END)AS Preferred,
mmt.Admiral_Title,
mmt.Spouse_Title,
mmt.Couple_Title,
mdi.Year AS Duchess_Year,
mdi.College AS Duchess_College,
mdi.Major AS Duchess_Major,
mdi.Sorority AS Duchess_Sorority,
mdi.Parent_Name AS Duchess_Parent_Name,
mdi.Escort_Name AS Duchess_Escort_Name
FROM duchess_payment dp
JOIN member_duchess_info mdi ON mdi.Duchess_Id = dp.Duchess_Id
JOIN member_home_address mha ON mha.Member_Id = mdi.Member_Id
JOIN member_work_address mwa ON mwa.Member_Id = mdi.Member_Id
JOIN member_mailing_title mmt ON mmt.Member_Id = mdi.Member_Id
ORDER BY dp.Duchess_Id;
this is the way Iam using . Is it corrct?.
when i try to executing that query it is still taking more time.
here is the explain of the query

Use indexes on the items on which you are performing joins e.g Duchess_Id, Member_Id etc

Related

Optimization of a large database query

I would like to ask if there is any way to optimize the following query:
SELECT SQL_BIG_RESULT DISTINCT u.spy_tech,
u.computer_tech,
u.military_tech,
u.defence_tech,
u.shield_tech,
u.energy_tech,
u.hyperspace_tech,
u.combustion_tech,
u.impulse_motor_tech,
u.hyperspace_motor_tech,
u.laser_tech,
u.ionic_tech,
u.buster_tech,
u.intergalactic_tech,
u.expedition_tech,
u.metal_proc_tech,
u.crystal_proc_tech,
u.deuterium_proc_tech,
u.technologia_bankowa,
u.technologia_kolonizacyjna,
u.technologia_optymalizacji,
u.technologia_otchlani,
u.graviton_tech,
SUM(p.small_ship_cargo) as small_ship_cargo,
SUM(p.big_ship_cargo) as big_ship_cargo,
SUM(p.light_hunter) as light_hunter,
SUM(p.heavy_hunter) as heavy_hunter,
SUM(p.crusher) as crusher,
SUM(p.battle_ship) as battle_ship,
SUM(p.colonizer) as colonizer,
SUM(p.recycler) as recycler,
SUM(p.spy_sonde) as spy_sonde,
SUM(p.bomber_ship) as bomber_ship,
SUM(p.solar_satelit) as solar_satelit,
SUM(p.destructor) as destructor,
SUM(p.dearth_star) as dearth_star,
SUM(p.battleship) as battleship,
SUM(p.lune_noir) as lune_noir,
SUM(p.ev_transporter) as ev_transporter,
SUM(p.star_crasher) as star_crasher,
SUM(p.giga_recykler) as giga_recykler,
SUM(p.dm_ship) as dm_ship,
SUM(p.apocalypse) as apocalypse,
SUM(p.annihilator) as annihilator,
SUM(p.devastator) as devastator,
SUM(p.fleet_save) as fleet_save,
u.r_badawczy,
u.r_budowlany,
u.r_militarny,
u.r_obrony,
u.r_paliwowy,
u.r_gospodarczy,
u.r_planetarny,
u.r_magazynowy,
u.r_energetyczny,
u.r_ekonomiczny,
u.r_odkrywczy,
u.r_max,
u.r_speed,
u.r_moon,
u.r_dm,
u.r_terra,
SUM(p.misil_launcher) as misil_launcher,
SUM(p.small_laser) as small_laser,
SUM(p.big_laser) as big_laser,
SUM(p.gauss_canyon) as gauss_canyon,
SUM(p.ionic_canyon) as ionic_canyon,
SUM(p.buster_canyon) as buster_canyon,
SUM(p.small_protection_shield) as small_protection_shield,
SUM(p.big_protection_shield) as big_protection_shield,
SUM(p.planet_protector) as planet_protector,
SUM(p.graviton_canyon) as graviton_canyon,
SUM(p.orbital_station) as orbital_station,
SUM(p.dzialo_pulsacyjne) as dzialo_pulsacyjne,
SUM(p.dzialo_fotonowe) as dzialo_fotonowe,
SUM(p.interceptor_misil) as interceptor_misil,
SUM(p.interplanetary_misil) as interplanetary_misil,
u.id,
u.ally_id,
u.onlinetime,
s.tech_rank AS old_tech_rank,
s.build_rank AS old_build_rank,
s.defs_rank AS old_defs_rank,
s.fleet_rank AS old_fleet_rank,
s.total_rank AS old_total_rank,
s.total_points_old AS total_points_old,
s.fleet_points_old AS fleet_points_old,
s.defs_points_old AS defs_points_old,
s.build_points_old AS build_points_old,
s.tech_points_old AS tech_points_old
FROM test_users as u
LEFT JOIN test_statpoints as s ON s.stat_type = 1 AND s.id_owner = u.id
LEFT JOIN test_planets as p ON u.id = p.id_owner
WHERE u.user_lastip != "127.0.0.1"
AND u.bana = "0"
AND u.authlevel = "0"
AND u.universe = "1"
GROUP BY s.id_owner, u.id
On my VPS, the query takes 8 seconds and the result is about 10,000 results. Although I improved the machine twice, to 8x2,4CPU, 16gb RAM, the query time has not changed.
So I thought to optimize the above-mentioned query or work on VPS configuration and find a bottleneck that can generate such time.
Table STATPOINTS:
Table USERS:
I do not know if I have given you an insight into the tables, when it comes to something else I would ask for guidance.
Explain:
Your query can run faster if you add the following indexes:
create index ix1 on user (bana, authlevel, universe);
create index ix2 on test_statpoints (stat_type, id_owner);
create index ix3 on test_planets (id_owner);
They include the access columns according to the join predicates.

SQL is intermittently returning no data in response to a LEFT JOIN

I am trying to hunt down a bug in a SQL query but can't seem to get to the bottom of it. The query looks like this:
SELECT
DATE(BT.DateCheckedIn) AS X,
DAYOFWEEK(BT.DateCheckedIn) AS DayX,
SUM(IR.QtyCheckedIn) AS C,
AU.AdminUsername,
AU.AdminFirstName,
AU.AdminLastName,
IF(BTE.ProdLogID IS NULL, 'No', 'Yes') AS Exclude
FROM
buying_issuesreceived IR
JOIN buying_transactions BT ON IR.TransactionID = BT.TransactionID
JOIN adminusers AU ON BT.CheckedInByAdminUserID = AU.AdminUserID
LEFT JOIN log_production_bt BTE
ON DATE(BT.DateCheckedIn) = DATE(BTE.ProductionDate)
AND BTE.ProductionSection = 'wtransactions'
AND AU.AdminUsername = BTE.ProductionUsername
WHERE
DATE(BT.DateCheckedIn) BETWEEN DATE '2018-09-24' AND DATE '2018-09-30'
GROUP BY
DATE(BT.DateCheckedIn),
AU.AdminUsername
When this query is run, it has about a 50/50 chance of returning the correct data or returning nothing at all. There is no error message. I know, or rather should say, am pretty certain, that the LEFT JOIN is the culprit because when I delete it from the code I stop getting empty tables, but can't, for the life of me, figure out why this query would return inconsistent results in the first place.
This sounds like a MySQL bug. As a workaround, you can use EXISTS with a correlated subquery.
SELECT
DATE(BT.DateCheckedIn) AS X,
DAYOFWEEK(BT.DateCheckedIn) AS DayX,
SUM(IR.QtyCheckedIn) AS C,
AU.AdminUsername,
AU.AdminFirstName,
AU.AdminLastName,
IF(EXISTS(
SELECT 1
FROM log_production_bt BTE
WHERE
DATE(BT.DateCheckedIn) = DATE(BTE.ProductionDate)
AND BTE.ProductionSection = 'wtransactions'
AND AU.AdminUsername = BTE.ProductionUsername), 'NO', 'YES') AS Exclude
FROM
buying_issuesreceived IR
JOIN buying_transactions BT ON IR.TransactionID = BT.TransactionID
JOIN adminusers AU ON BT.CheckedInByAdminUserID = AU.AdminUserID
WHERE
DATE(BT.DateCheckedIn) BETWEEN DATE '2018-09-24' AND DATE '2018-09-30'
GROUP BY
DATE(BT.DateCheckedIn),
AU.AdminUsername

how to perform count using nested select in a select statement

So here is the issue. I'm trying to write a new fillrate report because the one built in is not good enough... I'm trying to run a single select statement to return both, a count of how many times an item was ordered for a specific month, and then also a count of how many times it was invoiced/shipped in full.
This code is obviously wrong, I also currently have it restricted to only look at AUG of 2015, but that is just to simplify results during testing.
I can't figure out how to do the 2nd count... This is what I was trying (brain stuck on old for each loop logic):
select inv_mast.item_id,
inv_mast.item_desc,
"YEAR" = year(oe_line.required_date),
"MONTH" = month(oe_line.required_date),
"ORDERS" = count(1),
"HITS" = (
select count(1)
from invoice_line
where invoice_line.order_no = oe_line.order_no
and invoice_line.oe_line_number = oe_line.line_no
and invoice_line.qty_shipped = oe_line.qty_ordered
)
from oe_line,
inv_mast,
inv_loc
where inv_mast.inv_mast_uid = oe_line.inv_mast_uid
and inv_mast.delete_flag = 'N'
and inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
and inv_loc.location_id = '101'
and year(oe_line.required_date) = '2015'
and month(oe_line.required_date) = '8'
group by inv_mast.item_id,
inv_mast.item_desc,
year(oe_line.required_date),
month(oe_line.required_date)
order by inv_mast.item_id
To me it would seem like you could rewrite the query to use a left join on the invoice_line table instead. Without any proper test data I can't guarantee it is correct, but I think it should be.
Besides the left join I also changed to explicit joins and moved the aliases as I don't think MySQL supports the alias = column syntax.
select inv_mast.item_id,
inv_mast.item_desc,
year(o.required_date) as "YEAR",
month(o.required_date) as "MONTH",
count(1) as "ORDERS",
count(invoice_line.order_no) as "HITS"
from oe_line o
join inv_mast on inv_mast.inv_mast_uid = o.inv_mast_uid
join inv_loc on inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
left join invoice_line on invoice_line.order_no = o.order_no
and invoice_line.oe_line_number = o.line_no
and invoice_line.qty_shipped = o.qty_ordered
where inv_mast.delete_flag = 'N'
and inv_loc.location_id = '101'
and year(o.required_date) = '2015'
and month(o.required_date) = '8'
group by inv_mast.item_id,
inv_mast.item_desc,
year(o.required_date),
month(o.required_date)
order by inv_mast.item_id;

Excluding a value from the return result of MySQL

I'm facing a problem and I'm not finding the answer. I'm querying a MySql table during my java process and I would like to exclude some rows from the return of my query.
Here is the query:
SELECT
o.offer_id,
o.external_cat,
o.cat,
o.shop,
o.item_id,
oa.value
FROM
offer AS o,
offerattributes AS oa
WHERE
o.offer_id = oa.offer_id
AND (cat = 1200000 OR cat = 12050200
OR cat = 13020304
OR cat = 3041400
OR cat = 3041402)
AND (oa.attribute_id = 'status_live_unattached_pregen'
OR oa.attribute_id = 'status_live_attached_pregen'
OR oa.attribute_id = 'status_dead_offer_getter'
OR oa.attribute_id = 'most_recent_status')
AND (oa.value = 'OK'
OR oa.value='status_live_unattached_pregen'
OR oa.value='status_live_attached_pregen'
OR oa.value='status_dead_offer_getter')
The trick here is that I need the value to be 'OK' in order to continue my process but I don't need mysql to return it in its response, I only need the other values to be returned, for the moment its returning two rows by query, one with the 'OK' value and another with one of the other values.
I would like the return value to be like this:
'000005261383370', '10020578', '1200000', '562', '1000000_157795705', 'status_live_attached_pregen'
for my query, but it returns:
'000005261383370', '10020578', '1200000', '562', '1000000_157795705', 'OK'
'000005261383370', '10020578', '1200000', '562', '1000000_157795705', 'status_live_attached_pregen'
Some help would really be appreciated.
Thank you !
You can solve this with an INNER JOIN on the self I think:
SELECT o.offer_id
,o.external_cat
,o.cat
,o.shop
,o.item_id
,oa.value
FROM offer AS o
INNER JOIN offerattributes AS oa
ON o.offer_id = oa.offer_id
INNER JOIN offerattributes AS oaOK
ON oaOK.offer_id = oa.offer_id
AND oaOK.value = 'OK'
WHERE o.cat IN (1200000,12050200,13020304,3041400,3041402)
AND oa.attribute_id IN ('status_live_unattached_pregen','status_live_attached_pregen','status_dead_offer_getter','most_recent_status')
AND oa.value IN ('status_live_unattached_pregen','status_live_attached_pregen','status_dead_offer_getter');
By doing a self-JOIN with the restriction of value OK, it will limit the result set to offer_ids that have an OK response, but the WHERE clause will still retrieve the values you need. Based on your description, I think this is what you were looking for.
I also converted your implicit cross JOIN to an explicit INNER JOIN, as well as changed your ORs to IN, should be more performant this way.

sql query speed. Time response to long

I have problem with my mysl query. Response time is to long. My query:
SELECT SQL_CALC_FOUND_ROWS
t.id,
l.id_produkt_lista,
z.nr_zam,
k.nazwa_fv,
p.nazwa,
p.opis,
p.data_realizacji,
CONCAT(t.d_graf,'</br>', IF(t.D_d_graf IS NOT NULL,
DATE_FORMAT(t.D_d_graf, "%d-%m-%Y"),"")),
CONCAT(t.d_druk,'</br>', IF(t.D_d_druk IS NOT NULL,
DATE_FORMAT(t.D_d_druk, "%d-%m-%Y"),"")),
CONCAT(t.d_zgrz,'</br>', IF(t.D_d_zgrz IS NOT NULL,
DATE_FORMAT(t.D_d_zgrz, "%d-%m-%Y"),""))
FROM zamowienie_produkt_lista l
JOIN zamowienia_zamowienie z ON (l.id_zamowienie = z.id_zamowienie)
JOIN zamowienia_produkt p ON (l.id_produkt = p.id_produkt)
JOIN zamowienia_prac_tmp t ON (l.id_produkt = t.id_produkt)
JOIN zamowienia_klient k ON (z.id_klient = k.id_klient)
WHERE TRUE
AND id_typ_produkt = '1'
AND z.archiwum = 0
ORDER BY t.id
When I use it in phpmyadmin I have to wait about 10 second
Assuming that id_typ_produkt belongs to table zamowienie_produkt_lista, creating following indexes should help:
CREATE INDEX p_1_idx ON zamowienie_produkt_lista
(id_produkt, id_typ_produkt);
CREATE INDEX z_1_idx ON zamowienia_zamowienie
(id_zamowienie, archiwum);
You should also make sure that indexes on all *_id fields for all other joined tables exist.