2013-02-12 78 views
0

这是运行速度非常慢的MS Access查询。 Results表是主表,而PB,SC表是子表。列组合IndexResultID在所有这些表中都是独一无二的。因此,例如,表C中只能有一行,其中Index为“1”,ResultID为2.我没有使用JOIN,因为MS Access只支持内部连接,而我需要的是外部连接,因为我即使在任何其他表中没有对应的记录,也希望显示表Results中的所有记录。在MS ACCESS查询中优化一堆嵌套SELECTs

SELECT 
    [Results].[Id], 
    [Results].[Name], 
    [Results].[OfferPrice], 
    [Results].[RegPrice], 
    [Results].[ImageFileName], 
    [Results].[Image], 
    [Results].[URL], 
    (SELECT P.P FROM P WHERE P.ResultID = Results.Id AND P.Index = "0") as P0, 
    (SELECT P.P FROM P WHERE P.ResultID = Results.Id AND P.Index = "1") as P1, 
    (SELECT P.P FROM P WHERE P.ResultID = Results.Id AND P.Index = "2") as P2, 
    (SELECT P.P FROM P WHERE P.ResultID = Results.Id AND P.Index = "3") as P3, 
    (SELECT P.P FROM P WHERE P.ResultID = Results.Id AND P.Index = "4") as P4, 
    (SELECT P.P FROM P WHERE P.ResultID = Results.Id AND P.Index = "5") as P5, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "0") as B0, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "1") as B1, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "2") as B2, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "3") as B3, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "4") as B4, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "5") as B5, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "6") as B6, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "7") as B7, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "8") as B8, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "9") as B9, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "10") as B10, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "11") as B11, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "12") as B12, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "13") as B13, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "14") as B14, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "15") as B15, 
    (SELECT B.B FROM B WHERE B.ResultID = Results.Id AND B.Index = "16") as B16, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "1") as S1, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "2") as S2, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "3") as S3, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "4") as S4, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "5") as S5, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "6") as S6, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "7") as S7, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "8") as S8, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "9") as S9, 
    (SELECT S.S FROM S WHERE S.ResultID = Results.Id AND S.Index = "10") as S10, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "0") as C0, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "1") as C1, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "2") as C2, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "3") as C3, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "4") as C4, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "5") as C5, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "6") as C6, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "7") as C7, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "8") as C8, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "9") as C9, 
    (SELECT C.C FROM C WHERE C.ResultID = Results.Id AND C.Index = "10") as C10 
FROM 
    Results 
+2

什么让你相信Access不支持外连接? – Brad 2013-02-12 16:25:29

回答

4

我不知道你在哪里得到如下:

我没有使用JOIN,因为MS Access只支持内部连接和什么我需要的是一个外部联接

MS Access支持OUTER JOIN syntax

您可以用每个表格之间的LEFT JOIN替换您的相关子查询。您的代码将与此类似:

SELECT 
    [Results].[Id], 
    [Results].[Name], 
    [Results].[OfferPrice], 
    [Results].[RegPrice], 
    [Results].[ImageFileName], 
    [Results].[Image], 
    [Results].[URL], 
    max(IIF(P.Index = "0", P.P, null)) as P0, 
    max(IIF(P.Index = "1", P.P, null)) as P1, 
    max(IIF(P.Index = "2", P.P, null)) as P2, 
    max(IIF(P.Index = "3", P.P, null)) as P3, 
    max(IIF(P.Index = "4", P.P, null)) as P4, 
    max(IIF(P.Index = "5", P.P, null)) as P5, 
    max(IIF(B.Index = "0", B.B, null)) as B0, 
    max(IIF(B.Index = "1", B.B, null)) as B1, 
    max(IIF(B.Index = "8", B.B, null)) as B8, 
    max(IIF(S.Index = "2", S.S, null)) as S2, 
    max(IIF(C.Index = "1", C.C, null)) as C1 
FROM Results 
LEFT JOIN P 
    on P.ResultID = Results.Id 
LEFT JOIN B 
    on B.ResultID = Results.Id 
LEFT JOIN S 
    on S.ResultID = Results.Id 
LEFT JOIN C 
    on C.ResultID = Results.Id 
GROUP BY [Results].[Id], 
    [Results].[Name], 
    [Results].[OfferPrice], 
    [Results].[RegPrice], 
    [Results].[ImageFileName], 
    [Results].[Image], 
    [Results].[URL] 

你也应该能够使用TRANSFORM函数的数据,代码将类似于此:

TRANSFORM Max(Src.Value) 
select 
    [Results].[Id], 
    [Results].[Name], 
    [Results].[OfferPrice], 
    [Results].[RegPrice], 
    [Results].[ImageFileName], 
    [Results].[Image], 
    [Results].[URL] 
from results as R 
left join 
(
    select ResultID, P as Value, "P"&Index as col 
    from p 
    union all 
    select ResultID, B as Value, "B"&Index as col 
    from B 
    union all 
    select ResultID, C as Value, "C"&Index as col 
    from C 
    union all 
    select ResultID, S as Value, "S"&Index as col 
    from S 
) as Src 
    on R.id = Src.ResultID 
GROUP BY [Results].[Id], [Results].[Name], 
    [Results].[OfferPrice],[Results].[RegPrice], 
    [Results].[ImageFileName], [Results].[Image], 
    [Results].[URL] 
PIVOT Src.col 
+0

为什么这个组合?我不认为这是必要的。 – 2013-02-12 16:29:43

+2

@ypercube有一个聚合函数 – Taryn 2013-02-12 16:30:24

+0

对不起,没有注意到。如果你把'Index ='0''条件放在'ON'子句中,你就不需要GROUP BY或聚合,对吗? – 2013-02-12 16:31:35

1

如果使连接明确,则查询运行得更快。这里是模板:

SELECT 
    [Results].[Id], 
    [Results].[Name], 
    [Results].[OfferPrice], 
    [Results].[RegPrice], 
    [Results].[ImageFileName], 
    [Results].[Image], 
    [Results].[URL], 
    max(iif(p.index = "0", p.p, "")) as p0, 
    . . . 
FROM results left outer join 
    p 
    on results.id = p.resultid left outer join 
    . . . 
group by [Results].[Id], 
    [Results].[Name], 
    [Results].[OfferPrice], 
    [Results].[RegPrice], 
    [Results].[ImageFileName], 
    [Results].[Image], 
    [Results].[URL] 

的想法是使用left outer join表中,使加入他们在正确的条件和使用聚合收缩他们回到每个结果一行。 SELECT中的逻辑根据您设置的逻辑选择值。

1

这应该蛮运行很快。它看起来像你试图对一个表和多个表的联合之间的连接做一个关键点。下面的unionized表替换您的所有连接。事实上,这是pivoted取代了需要做任何相关的子查询。

TRANSFORM Max(unionized.DataColumn) AS MaxOfDataColumn 
SELECT Results.ResName, Results.OfferPrice, Results.RegPrice, Results.Image, Results.URL 
FROM (
    Select B.ID, B.B as DataColumn, "B"&B.B as tableName from B 
    union all select C.ID, C.C, "C"&C.C from C 
    union all select P.ID, P.P, "P"&P.P from P 
    union all select S.ID, S.S, "S"&S.S from S) AS unionized 
RIGHT JOIN Results ON unionized.ID = Results.ID 
GROUP BY Results.ResName, Results.OfferPrice, Results.RegPrice, Results.Image, Results.URL 
PIVOT unionized.tableName; 

您需要清理一下,因为我假设您使用了示例列,但希望您明白这一点。