2012-03-01 62 views
0

我真的希望有人能帮助我。我有许多产品属性类型,用户可以从中进行选择以优化屏幕上返回的产品。我想要做的是,对于每种产品属性类型,我想列出与所选类别或搜索词相关的所有属性,然后一旦他们做出选择,我仍然想要显示每个属性与类别或搜索词相关,但只显示可点击的链接(如果该特定属性的产品数大于1),对于那些产品数为零的链接,我想列出它们,但使它们不可点击。我试图实现的一个例子可以在ASOS网站上找到,在左侧菜单中 http://www.asos.com/Women/Dresses/Cat/pgecategory.aspx?cid=8799#state=Rf961%3D3340%2C3341%40Rf-200%3D20&parentID=Rf-300&pge=0&pgeSize=20&sort=-1临时表和左连接没有按预期显示结果

最初我尝试只用连接来实现这一点,但我无法成功完成。因此,我决定为每个属性类型创建一个临时表,其中包含与主查询相关的所有属性的列表,然后使用左连接创建精炼的查询。这里是我的代码:

CREATE TEMPORARY TABLE temp_table 
    SELECT su_types.id, type AS item FROM su_types 
    INNER JOIN su_typerefs ON su_types.id=su_typerefs.id 
    INNER JOIN su_pref ON su_typerefs.mykey = su_pref.mykey 
WHERE wp_category_id =40 GROUP BY su_typerefs.id 

$sudb->query($query); 

if ($sudb->affected_rows > 0) {  

SELECT temp_table.id,item,COUNT(su_typerefs.mykey) AS product_count FROM temp_table 
    LEFT JOIN su_typerefs ON temp_table.id=su_typerefs.id 
    LEFT JOIN su_pref ON su_typerefs.mykey = su_pref.mykey 
    LEFT JOIN su_stylerefs ON su_pref.mykey = su_stylerefs.mykey 
    LEFT JOIN su_productrefs ON su_pref.mykey = su_productrefs.mykey 
WHERE wp_category_id =40 AND su_stylerefs.id in (91) AND su_productrefs.id in (54) AND su_typerefs.id in (159) GROUP BY su_typerefs.id 

if ($itemresults = $sudb->query($query)) { 

    while($itemresult = $itemresults->fetch_array(MYSQLI_ASSOC)) { 
    $id=$itemresult['id']; 
    $item=$itemresult['item']; 
    $product_count=$itemresult['product_count']; 


     build_link($list_type, $item, $product_count, $id); 
    } 
} 

在上面的例子中,第一查询选择涉及特定类别的所有产品类型,说衣服。第二个查询基于用户对该类别的改进,在本例中,这是产品,产品类型和样式。用户还可以通过颜色,适合度,面料和设计来细化他们的搜索。

有几个问题与此:

1)结果的数量在第二个查询返回不匹配的第一个结果。以上述为例,我希望列出与所选类别相关的所有产品,然后使用第二个查询返回上述每种产品的产品数量。所以,如果临时桌返回,裤子,牛仔裤和裙子。我期望这三个项目根据第二个查询中应用的条件显示在屏幕上,但是如果在第二个查询中没有裙子匹配,我的结果可能只会显示裤子和牛仔裤。我认为使用左连接意味着将显示临时表的所有结果。

2)此外,我不知道如果我这样做是最有效的方式。我总共有8个属性组,因此需要做上述8次。如果用户选择使用全部8个属性组来优化结果,那么除了临时表连接之外,每种类型总共会有9个连接。执行需要一段时间,是否有更好的方法来执行此操作?表格中大约有一千五百万个产品,一旦我的网站上线,这可能会是这个的五倍。

我真的希望我写的都有道理,我会很感激的计算器社会这方面的帮助,如果任何人都可以提供帮助。我为这篇短文道歉;)。在此先感谢

回答

0

要回答你的第一个问题;是的,LEFT JOIN确实会保留初始表中的所有数据。但是,这不是问题。

为什么你失去了空的类别,是最有可能的原因(我这样说是因为我不完全知道你的数据库结构),因为那里的条件筛选出基于连接表数据中的所有结果。 如果对于某个类别,所有项目都被滤除(可能包括NULL连接的值),则不会再从该查询中取回该类别。此外,GROUP BY是在连接的列上完成的,也可能会有效地清除其他类别。

至于第二个问题,你已经说出它采取长;所以如果你希望事情能够快速运行,这可能不会成为现实;)(好吧,明显的答案,低悬的水果等)。您可能想要做的是首先从可筛选类别中获取一组键,然后使用该数据选择项目。

这可以防止你也来加入你的整个产品表中临时表(至少,这就是我认为你正在做的),当然,这将需要很长的条目的给定数。从给定的属性中选择一个匹配的ID列表也可以让你更好地使用你的索引(更多),而临时表可能不会有。如果这是可能和可行的,主要取决于你的模式结构;但我希望它会导致你的方向你想要去:)

+0

嗨Yhn,感谢您的回复,临时表不会检索表中的所有属性,但只涉及到所选类别的那些。我之前构建了第二个查询,作为通过每个我想要计数的键的循环。这很好,但花费了相同的时间,如果不是更多。目前需要大约30秒才能加载整个页面,这是不可接受的吗? – Amara 2012-03-01 15:41:30

+0

30秒,只是一些计数统计并听起来像它应该能够更好地工作......你可以尝试同时检查查询的时序(只是为了确认这两者实际上是造成问题)。之后,您可以尝试使用EXPLAIN [query]的输出来查看索引是否正确用于连接和位置。也许它可以在没有临时表的情况下工作得更快(因为这可能没有索引;而实际的表有)。 – Yhn 2012-03-01 15:49:36

+0

我试图做一个关于临时表查询的解释,但我无法做到。但是sedond查询的解释看起来很好。如果我不使用临时表,然后我会创建通过第一循环,而不是加入第二查询到临时表和一个返回所有结果第二次查询击中 – Amara 2012-03-01 16:45:39