MySQL选择查询中的子选择效率

时间:2015-07-21 14:48:20

标签: mysql sql select subquery

我正在尝试从数据库表的集合中生成报告,并且我发现我写的查询速度非常慢。我意识到在select查询中使用多个子选择会增加查询完成所需的时间,因为每行需要多个子查询到数据库,但我该怎么做才能使我的查询更快更有效?

我已经尝试将其包装在准备好的语句中并且效果不大,是否有一种方法可以让我更快地提取所需信息?

SELECT Contractor.id,
Contractor.Unique_ID,
Contractor.FName,
Contractor.SName,
Contractor.MIName,
Contractor.NI_Number,
Contractor.Address,
Contractor.Phone_Main,
Contractor.Phone_Mobile,
Contractor.Email,
Contractor.Bank_Name,
Contractor.Bank_Account_Name,
Contractor.Bank_Account_Sort_Code,
Contractor.Bank_Account_Number,
Contractor.DOB,
Contractors.DateTime_Account_Created,
Contractor.Payment_Frequency,
Contractor.Saving_Tax_Pref,
Contractor.Holiday_Savings_Pref,
Contractor.UTR,
Contractor.DateTime_Last_Logged_In,
Contractor.Leaving_Date,
Agency.Name,
(
    SELECT ROUND(SUM(ContractorSavings.value - ContractorSavings.paidOutValue), 2)
    FROM ContractorSavings
    LEFT JOIN SavingsToPayJunction ON SavingsToPayJunction.SavingsId = ContractorSavings.id
    WHERE fullyPaid = 0
    AND ContractorSavings.type_id = 2
    AND SavingsToPayJunction.ContractorId = Contractor.id
) AS 'Tax_Saving_Balance',
(
    SELECT ROUND(SUM(ContractorSavings.value - ContractorSavings.paidOutValue), 2)
    FROM ContractorSavings
    LEFT JOIN SavingsToPayJunction ON SavingsToPayJunction.SavingsId = ContractorSavings.id
    WHERE fullyPaid = 0
    AND ContractorSavings.type_id = 2
    AND SavingsToPayJunction.ContractorId = Contractor.id
) AS 'Holiday_Saving_Balance',
(
    SELECT ROUND(SUM(Expense_Value),2)
    FROM Contractor_Expenses
    WHERE Contractor_ID = Contractor.id
    AND authorised = 0
)AS 'Expenses_Claimed',
(
    SELECT ROUND(SUM(Expense_Value - amountAllocated),2)
    FROM Contractor_Expenses
    WHERE Contractor_ID = Contractor.id
    AND authorised = 1
    AND fullyAllocated = 0
)AS 'Expenses_Authorised',
(
    SELECT MAX(Contractor_Pay.Date_Earned)
    FROM Contractor_Pay
    WHERE Contractor_Pay.Contractor_ID = Contractor.Unique_ID
)AS 'Last_Pay_Date'
FROM Contractor
LEFT JOIN Agency ON Agency.id = Contractor.Agency_ID

为笨拙的查询转储道歉。我期待着你的回复。

谢谢,

* POST ANSWER EDIT *

对于那些关心时间等的人来说,答案将我的查询时间从超过3分钟缩短到45秒。

1 个答案:

答案 0 :(得分:1)

您可以将每个子选项作为FROM子句中的子选择(使用GROUP BY Contractor_ID)然后加入它们:

SELECT
    Contractor.id,
    Contractor.Unique_ID,
    Contractor.FName,
    Contractor.SName,
    Contractor.MIName,
    Contractor.NI_Number,
    Contractor.Address,
    Contractor.Phone_Main,
    Contractor.Phone_Mobile,
    Contractor.Email,
    Contractor.Bank_Name,
    Contractor.Bank_Account_Name,
    Contractor.Bank_Account_Sort_Code,
    Contractor.Bank_Account_Number,
    Contractor.DOB,
    Contractors.DateTime_Account_Created,
    Contractor.Payment_Frequency,
    Contractor.Saving_Tax_Pref,
    Contractor.Holiday_Savings_Pref,
    Contractor.UTR,
    Contractor.DateTime_Last_Logged_In,
    Contractor.Leaving_Date,
    Agency.Name,
    Tax_Saving_Balance.val as Tax_Saving_Balance,
    Holiday_Saving_Balance.val as Holiday_Saving_Balance,
    Expenses_Claimed.val as Expenses_Claimed,
    Expenses_Authorised.val as Expenses_Authorised,
    Last_Pay_Date.val as Last_Pay_Date
FROM Contractor
LEFT JOIN Agency ON Agency.id = Contractor.Agency_ID
LEFT JOIN (
    SELECT SavingsToPayJunction.ContractorId, ROUND(SUM(ContractorSavings.value - ContractorSavings.paidOutValue), 2) as val,
    FROM ContractorSavings
    LEFT JOIN SavingsToPayJunction ON SavingsToPayJunction.SavingsId = ContractorSavings.id
    WHERE fullyPaid = 0
    AND ContractorSavings.type_id = 2
    GROUP BY SavingsToPayJunction.ContractorId
) as Tax_Saving_Balance ON Tax_Saving_Balance.ContractorId = Contractor.id
LEFT JOIN (
    SELECT SavingsToPayJunction.ContractorId, ROUND(SUM(ContractorSavings.value - ContractorSavings.paidOutValue), 2) as val
    FROM ContractorSavings
    LEFT JOIN SavingsToPayJunction ON SavingsToPayJunction.SavingsId = ContractorSavings.id
    WHERE fullyPaid = 0
    AND ContractorSavings.type_id = 2
    GROUP BY SavingsToPayJunction.ContractorId
) as Holiday_Saving_Balance ON Holiday_Saving_Balance.ContractorId = Contractor.id
LEFT JOIN (
    SELECT Contractor_ID, ROUND(SUM(Expense_Value),2) as val
    FROM Contractor_Expenses
    WHERE authorised = 0
    GROUP BY Contractor_ID
) as Expenses_Claimed ON Expenses_Claimed.Contractor_ID = Contractor.id
LEFT JOIN (
    SELECT Contractor_ID, ROUND(SUM(Expense_Value - amountAllocated),2) as val
    FROM Contractor_Expenses
    WHERE authorised = 1
    AND fullyAllocated = 0
    GROUP BY Contractor_ID
) as Expenses_Authorised ON Expenses_Authorised.Contractor_ID = Contractor.id
LEFT JOIN (
    SELECT Contractor_ID, MAX(Contractor_Pay.Date_Earned)
    FROM Contractor_Pay
    GROUP BY Contractor_ID
) as Last_Pay_Date ON Last_Pay_Date.Contractor_ID = Contractor.Unique_ID