Update With Inner Join Running Too Slow - mysql

Can somebody help optimizing the query below. The tr_marketshare table contains just 84000 records and query is taking 6 minutes and 19 seconds to execute.
UPDATE tr_marketshare
INNER JOIN
(SELECT YEAR, MONTH, Door, Category, Category_Sales,Country
FROM tr_marketshare
WHERE Brand = 'Gucci'
AND Account = 'Wojooh'
AND Category='MU') MS
ON tr_marketshare.Door = MS.Door
AND tr_marketshare.Year = MS.Year
AND tr_marketshare.Month = MS.Month
AND tr_marketshare.Account='Wojooh'
AND tr_marketshare.Country = MS.Country
AND tr_marketshare.Category = 'MU'
AND tr_marketshare.Brand <> 'Gucci'
SET tr_marketshare.Category_Sales = MS.Category_Sales;
The schema information is as below.
ID and Year are Integer.
Category_Sales is float
Rest of the fields are of Varchar type.
Thanks.

Related

MYSQL execution time shows less time as it actually needs to display the data

I have a query in MYSQL as follows. It is to retrieve data to a Codeigniter program with populate a select box.
SELECT
pharmacy_products.id,
pharmacy_products.product_name,
pharmacy_products.product_display_name,
pharmacy_products.pack_size,
pharmacy_products.top_up_level,
pharmacy_products.current_physical_stock,
pharmacy_products.purchasing_status,
pharmacy_products.po_number,
pharmacy_products.added_supplier,
users.user_name,
pharmacy_products.added_to_supplier_time,
pharmacy_products.added_packs,
pharmacy_products.last_pack_purchase_price,
GROUP_CONCAT(
'',
pharmacy_suppliers.suppier_alternate_name,
'' SEPARATOR ''
) AS suppliers
FROM
pharmacy_products
LEFT JOIN pharmacy_product_to_companies ON pharmacy_products.id = pharmacy_product_to_companies.product_id
LEFT JOIN pharmacy_suppliers ON pharmacy_product_to_companies.company_id = pharmacy_suppliers.id
LEFT JOIN users ON pharmacy_products.added_to_supplier_by = users.user_id
WHERE
pharmacy_products.current_physical_stock <= pharmacy_products.re_order_level AND pharmacy_products.active_status = 1 AND pharmacy_products.approval_status = 1
GROUP BY
pharmacy_products.id
At phpmyadmin it says like this
Showing rows 0 - 24 (2877 total, Query took 1.7426 seconds.)
But it took about 5 seconds to display data (in phpmyadmin). And this affects to the program also.
How can I solve this?

MYSQL Query - joining tables and grouping results

I'm after some help with a report I'm designing please.
My report includes results from a booking database where I'd like to show each booking on a single line. However as the booking database has a number of tables my MYSQL query involves JOINS which is resulting in multiple rows per booking. It is the multiple results for "dcea4_eb_field_values.field_value" per booking causing the repeating rows.
This is my query
SELECT
dcea4_eb_events.event_date,
dcea4_eb_events.title,
dcea4_eb_registrants.id,
dcea4_eb_registrants.first_name,
dcea4_eb_registrants.last_name,
dcea4_eb_registrants.email,
dcea4_eb_registrants.register_date,
dcea4_eb_registrants.amount,
dcea4_eb_registrants.comment,
dcea4_eb_field_values.field_id,
dcea4_eb_field_values.field_value
FROM dcea4_eb_events
INNER JOIN dcea4_eb_registrants ON dcea4_eb_registrants.event_id = dcea4_eb_events.id
INNER JOIN dcea4_eb_field_values ON dcea4_eb_field_values.registrant_id = dcea4_eb_registrants.id
WHERE 1=1
AND (dcea4_eb_field_values.field_id = 14 OR dcea4_eb_field_values.field_id = 26 OR dcea4_eb_field_values.field_id = 27 OR dcea4_eb_field_values.field_id = 15)
AND dcea4_eb_registrants.published <> 2
AND dcea4_eb_registrants.published IS NOT NULL
AND (dcea4_eb_registrants.published = 1 OR dcea4_eb_registrants.payment_method = "os_offline")
[ AND (dcea4_eb_registrants.register_date {RegistrationDate} ) ]
[ AND REPLACE(dcea4_eb_events.title,'\'','') in ({Club}) ]
ORDER BY dcea4_eb_registrants.register_date,
dcea4_eb_events.title
This is what the output currently looks like
current result
and this is what I'd like it to look like
desired result
Any help appreciated

SQL Statement running extreamly Slow

Okay I have look through several posts about SQL running slow and I didn't see anything similar to this, so my apologies if I missed one. I was asked about a month ago to create a view that would allow the user to report what hasn't been billed yet, and the SQL is joining 4 tables together. One is 1.2 million records ish. the rest are between 80K - 250K. (Please note that this should only return around 100 records after the where statements).
SELECT C.Cltnum + '.' + C.CltEng AS [ClientNum],
C.CPPLname,
w.WSCDesc,
MIN(w.Wdate) AS [FirstTDate],
w.WCodeCat,
w.WCodeSub,
SUM(w.Wbilled) AS [Billed],
SUM(w.Whours * w.Wrate) AS [Billable Wip],
sum(ar.[ARProgress]) AS [Progress],
w.Winvnum,
-- dbo.GetInvoiceAmount(w.Winvnum) AS [InvoiceAmount],
SUM(cb.cinvar) AS [AR Balance]
FROM dbo.WIP AS w
--Never join on a select statement
--join BillingAuditCatagoriesT bac on w.WCodeCat = bac.Catagory and w.WCodeSub = bac.Subcatagory
INNER JOIN dbo.Clients AS C ON w.WCltID = C.ID
JOIN dbo.ClientBuckets AS cb on c.cltnum = cb.cltnum
JOIN dbo.AcctsRec AS ar on ar.arapplyto = w.[Winvnum]
-- WHERE w.wcodecat = '1AUDT'
GROUP BY C.Cltnum, C.CltEng, C.CPPLname, w.WCodeCat, w.Wdate, w.Winvnum, w.WCodeSub, w.WSCDesc
so, where I think there may be a problem is that Category is a varchar it is xat, ACT, BID and there are about 15 different Category. this is the same as SubCat. you will notice that there are 3 functions on this and they are GetJamesProgress Which is = (SELECT sum(Amount) From Progress Where inv = w.invnum) and the same with GetInvoiceAmount and GetJamesARBalance. I know that this is bad to do but when I join by invoice number it takes even longer than with out them.
Please help thanks so much!

MySQL find minimum and maximum date associated with a record in another table

I am trying to write a query to find the number of miles on a bicycle fork. This number is calculated by taking the distance_reading associated with the date that the fork was installed on (the minimum reading_date on or after the Bicycle_Fork.start_date associated with the Bicycle_Fork record) and subtracting that from the date that the fork was removed (the maximum reading_date on or before the Bicycle_Fork.end_date or, if that is null, the reading closest to today's date). I've managed to restrict the range of odometer_readings to the appropriate ones, but I cannot figure out how to find the minimum and maximum date for each odometer that represents when the fork was installed. It was easy when I only had to look at records matching the start_date or end_date, but the user is not required to enter a new odometer reading for each date that a part is changed. I've been working on this query for several hours now, and I can't find a way to use MIN() that doesn't just take the single smallest date out of all of the results.
Question: How can I find the minimum reading_date and the maximum reading_date associated with each odometer_id while maintaining the restrictions created by my WHERE clause?
If this is not possible, I plan to store the values retrieved from the first query in an array in PHP and deal with it from there, but I would like to be able to find a solution solely in MySQL.
Here is an SQL fiddle with the database schema and the current state of the query: http://sqlfiddle.com/#!2/015642/1
SELECT OdometerReadings.distance_reading, OdometerReadings.reading_date,
OdometerReadings.odometer_id, Bicycle_Fork.fork_id
FROM Bicycle_Fork
INNER JOIN (Bicycles, Odometers, OdometerReadings)
ON (Bicycles.bicycle_id = Bicycle_Fork.bicycle_id
AND Odometers.bicycle_id = Bicycles.bicycle_id AND OdometerReadings.odometer_id = Odometers.odometer_id)
WHERE (OdometerReadings.reading_date >= Bicycle_Fork.start_date) AND
((Bicycle_Fork.end_date IS NOT NULL AND OdometerReadings.reading_date<= Bicycle_Fork.end_date) XOR (Bicycle_Fork.end_date IS NULL AND OdometerReadings.reading_date <= CURRENT_DATE()))
This is the old query that didn't take into account the possibility of the database lacking a record that corresponded with the start_date or end_date:
SELECT MaxReadingOdo.distance_reading, MinReadingOdo.distance_reading
FROM
(SELECT OdometerReadings.distance_reading, OdometerReadings.reading_date,
OdometerReadings.odometer_id
FROM Bicycle_Fork
LEFT JOIN (Bicycles, Odometers, OdometerReadings)
ON (Bicycles.bicycle_id = Bicycle_Fork.bicycle_id
AND Odometers.bicycle_id = Bicycles.bicycle_id AND OdometerReadings.odometer_id = Odometers.odometer_id)
WHERE Bicycle_Fork.start_date = OdometerReadings.reading_date) AS MinReadingOdo
INNER JOIN
(SELECT OdometerReadings.distance_reading, OdometerReadings.reading_date,
OdometerReadings.odometer_id
FROM Bicycle_Fork
LEFT JOIN (Bicycles, Odometers, OdometerReadings)
ON (Bicycles.bicycle_id = Bicycle_Fork.bicycle_id AND Odometers.bicycle_id
= Bicycles.bicycle_id AND OdometerReadings.odometer_id = Odometers.odometer_id)
WHERE Bicycle_Fork.end_date = OdometerReadings.reading_date) AS
MaxReadingOdo
ON MinReadingOdo.odometer_id = MaxReadingOdo.odometer_id
I'm trying to get the following to return from the SQL schema:
I will eventually sum these into one number, but I've been working with them separately to make it easier to check the values.
min_distance_reading | max_distance_reading | odometer_id
=============================================================
75.5 | 2580.5 | 1
510.5 | 4078.5 | 2
17.5 | 78.5 | 3
I don't understand the final part of the puzzle, but this seems close...
SELECT MIN(ro.distance_reading) min_val
, MAX(ro.distance_reading) max_val
, ro.odometer_id
FROM OdometerReadings ro
JOIN odometers o
ON o.odometer_id = ro.odometer_id
JOIN Bicycle_Fork bf
ON bf.bicycle_id = o.bicycle_id
AND bf.start_date <= ro.reading_date
GROUP
BY ro.odometer_id;
http://sqlfiddle.com/#!2/015642/8

mySQL: LEFT JOIN where joining needs to be done on different type of data

I have 2 my tables with data and 2 "not mine" tables (in ReferenceDB) where thing ID can be mapped to its name.
One of mine tables is orders with following important columns: charName, stationID, typeID, bid.
Another table has following important columns: transactionDateTime, stationID, typeID, person, transactionType
I started my head braking with idea how to find orders that doesn't have any records for them lately (e.g. given amount of days). But for beginning I set me a task just to find orders that has no records for them at all. For that I figured out LEFT JOIN see biggest query below.
An order for me is a combination of charName/persone + stationID + typeID + transactionType/bid so if actually one of those four changes it is different order then.
Problem is that transactionType can be "yes" or "no" and bid is 0 or not 0. So I cant or DON'T KNOW HOW to JOIN ON different data types. So logically I'd like to join on 4 columns like:
FROM ordersTable LEFT JOIN recordsTable ON ordersTable.typeID = recordsTable.typeID
AND ordersTable.stationID = recordsTable.stationID
AND ordersTable.charName = recordsTable.person
AND ordersTable.bid = recordsTable.transactionType
Clearly last string of above wouldn't work cause of different data types.
So for a moment I thought that I can do such query twice for bid=0 with transactionType="yes" and second time for bid != 0 and transactionType = "no" see my query below for 0/"yes" combination. But seems it doesn't works exactly as I'd like it to. because AND ordersTable.bid IN (0) AND recordsTable.transactionType="yes" in JOIN ON doesn't sem do anything. (As I do get results where bid=1)
SELECT invTypes.typeName, stastations.stationName, main.* FROM referenceDB.invTypes, referenceDB.stastations, (
SELECT ordersTable.charName, ordersTable.stationID, ordersTable.typeID, ordersTable.bid, ordersTable.orderState, ordersTable.volRemaining
FROM ordersTable LEFT JOIN recordsTable ON ordersTable.typeID = recordsTable.typeID
AND ordersTable.stationID = recordsTable.stationID
AND ordersTable.charName = recordsTable.person
AND ordersTable.bid IN (0) AND recordsTable.transactionType="yes"
WHERE recordsTable.typeID IS NULL
AND ordersTable.orderState IN (0) ) as main
WHERE stastations.stationID = main.stationID AND invTypes.typeID = main.typeID;
Questions:
Is it possible to tell mySQL to treat "yes" as 0 or vise versa? If yes how do I do it in my query? If no what would be my work around (to find orders that doesn't have records related to them)?
And possibly some one can suggset a query that will find orders that didn't have records within given amount of days?
Thank you in advance!
One way is to use the explicit comparisons:
((ordersTable.bid = 0 and recordsTable.transactionType = 'No') or
(ordersTable.bid = 1 and recordsTable.transactionType = 'Yes')
)
Another would be to use a case statement:
(case when recordsTable.transactionType = 'No' then 0 else 1 end) = ordersTable.bid
SELECT invTypes.typeName, stastations.stationName, main.* FROM referenceDB.invTypes, referenceDB.stastations, (
SELECT ordersTable.charName, ordersTable.stationID, ordersTable.typeID, ordersTable.bid, ordersTable.orderState, ordersTable.volRemaining
FROM ordersTable LEFT JOIN recordsTable ON ordersTable.typeID = recordsTable.typeID
AND ordersTable.stationID = recordsTable.stationID
AND ordersTable.charName = recordsTable.person
AND ((ordersTable.bid = 0 AND recordsTable.transactionType = 'yes') OR
(ordersTable.bid != 0 AND recordsTable.transactionType = 'no'))
WHERE recordsTable.typeID IS NULL
AND ordersTable.orderState IN (0) ) as main
WHERE stastations.stationID = main.stationID AND invTypes.typeID = main.typeID;