在巨型桌子上快速加入3张桌子

时间:2013-10-18 12:58:28

标签: mysql sql select

我的查询是这样的:

SELECT    insanlyBigTable.description_short, 
          insanlyBigTable.id AS insanlyBigTable, 
          insanlyBigTable.type AS insanlyBigTableLol, 
          catalogpartner.id AS catalogpartner_id
FROM insanlyBigTable
INNER JOIN smallerTable ON smallerTable.id = insanlyBigTable.catalog_id
INNER JOIN smallerTable1 ON smallerTable1.catalog_id = smallerTable.id 
  AND smallerTable1.buyer_id = 'xxx'
WHERE smallerTable1.cont = 'Y' AND insanlyBigTable.type IN ('111','222','33') 
GROUP BY smallerTable.id;

现在,当我第一次运行查询时,它将巨型表复制到临时表中......我想知道如何防止这种情况?我正在考虑嵌套查询,甚至反转连接(不确定效果会跑得更快),但这很好,不好。还有其他建议吗?

1 个答案:

答案 0 :(得分:1)

为了弄清楚如何优化您的查询,我们首先要确切地了解它所选择的内容,这样我们就可以在改变时保留这些信息。

您的查询

所以,看起来我们需要以下

  • GROUP BY子句将结果限制为每catalog_id
  • 最多一行
  • smallerTable1.cont = 'Y'insanelyBigTable.type IN ('111','222','33')buyer_id = 'xxx'似乎是查询的过滤器。
  • 我们想要insanlyBigTable和...... catalogpartner的数据?由于catalogpartner idsmallerTable链接到其他表的catalog_id,我猜测buyer_id是smallTable1。

我不确定在ON子句中包含ON过滤器的目的是什么,但除非你以不同的方式告诉我,否则我会假设它在{ {1}}子句并不重要。

查询点

我不确定查询的意图,基于GROUP BY语句。您将catalog_id中的每insanelyBigTable只获得一行,但您似乎并不关心它是哪个行。实际上,您可以运行此查询的事实是由于special non-standard feature in MySQL允许您选择未出现在GROUP BY语句中的列...但是,您无法选择WHICH列。这意味着您可以为每个选定项目提供4个不同行的信息。

根据列名,我最好的猜测是,您试图将与目标买方购买的物品列在同一目录中的物品列表,但每个目录不超过一个物品。此外,您希望通过catalogpartner表格id将某些内容连接回该目录中的已购买商品。

所以,有些东西可能类似于亚马逊的“你可能喜欢这些物品,因为你购买了这些其他物品”功能。

新查询

我们希望每个insanlyBigTable.catalog_id有1行,基于过滤后smallTable1中存在的catalog_id。

SELECT 
    ibt.description_short, 
    ibt.id AS insanlyBigTable, 
    ibt.type AS insanlyBigTableLol, 
    (
        SELECT smallerTable1.id FROM smallerTable1 st
        WHERE st.buyer_id = 'xxx' 
        AND st.cont = 'Y'
        AND st.catalog_id = ibt.catalog_id
        LIMIT 1
    ) AS catalogpartner_id
FROM insanlyBigTable ibt
WHERE ibt.id IN (
    SELECT (
        SELECT ibt.id AS ibt_id
        FROM insanlyBigTable ibt
        WHERE ibt.catalog_id = sti.catalog_id
        LIMIT 1
    ) AS ibt_id
    FROM (
        SELECT DISTINCT(catalog_id) FROM smallerTable1 st
        WHERE st.buyer_id = 'xxx'
        AND st.cont = 'Y'
        AND EXISTS (
            SELECT * FROM insanlyBigTable ibt
            WHERE ibt.type IN ('111','222','33')
            AND ibt.catalog_id = st.catalog_id
        )
    ) AS sti
)

此查询应该生成与原始查询相同的结果,但它会将内容分解为较小的查询,以避免在insanlyBigTable上使用(和滥用)GROUP BY子句。

尝试一下,如果遇到问题请告诉我。