2

我有 2 个 sql 查询,第一个根据 AREA 和 CATEGORY 从数据库中选择产品

它是一家家具店,此查询是针对餐桌的。

SELECT p.id,
   p.product_name,
   p.range_name,
   p.pic_url,
   p.hits,
   p.manufacturer,
   p.standard_price,
   p.sale_price,
   p.offer_price,
   p.discount,
   p.display_manufacturer,
   p.display_price,
   p.visible,
   p.display_model_results,
   p.model,
   p.subcat,
   p.disable_options,
   p.request_price,
   p.corner_flag,
   cf.flag_name,
   cf.flag_url,
   cf.flag_description,
   p.display_model,
   p.offer_status,
   p.disable_options_results,
   p.added_timestamp,
   p.about,
   p.keywords
FROM   products p,
   corner_flags cf
WHERE  ( p.area = 'Dining Room Furniture'
      OR p.additionarea = 'Dining Room Furniture' )
   AND ( p.subcat = 'Dining Tables'
          OR p.additionsubcat = 'Dining Tables' )
   AND p.sale_price = ''
   AND p.visible = '1'
   AND p.corner_flag = cf.flag_id
   AND ( p.sale_price = ''
          OR p.offer_price = '0' )
   AND p.visible = '1'
 ORDER  BY ( p.hits ) DESC  

每次查看产品时,产品表中的“命中”字段都会增加 1。起初这还可以,但现在如果客户决定按受欢迎程度排序结果,新产品总是位于列表的底部。

我们有另一个表来跟踪我们网站上的每次点击,所以我写了一个查询来计算特定产品在过去 2 周内被查看的次数。

SELECT Count(*) AS total,
   vtp.product_id
FROM   visitor_tracking_pages vtp,
   products p
WHERE  vtp.product_id = p.id
   AND p.subcat = 'Dining Tables'
   AND p.visible = '1'
   AND vtp.last_click >= '1380153600'
GROUP  BY vtp.product_id
ORDER  BY total DESC 

此查询提供产品 ID 和过去 2 周内收到的总点击量。

我只需要一种方法将这两个查询合并为一个。显然,并非所有产品都会在过去 2 周内被查看,所以如果这有什么不同,我需要一种返回 0 的方法吗?

我查看了各种 JOINS,但我不熟悉如何编写它们。

非常感谢您的任何帮助!

4

4 回答 4

1

尝试这个

SELECT p.id,
   p.product_name,
   p.range_name,
   p.pic_url,
   p.hits,
   p.manufacturer,
   p.standard_price,
   p.sale_price,
   p.offer_price,
   p.discount,
   p.display_manufacturer,
   p.display_price,
   p.visible,
   p.display_model_results,
   p.model,
   p.subcat,
   p.disable_options,
   p.request_price,
   p.corner_flag,
   cf.flag_name,
   cf.flag_url,
   cf.flag_description,
   p.display_model,
   p.offer_status,
   p.disable_options_results,
   p.added_timestamp,
   p.about,
   p.keywords,
   IFNULL(vtp.last_two_week_hits, 0) as last_two_week_total_hits
FROM corner_flags cf INNER JOIN  products p
     ON cf.flag_id = p.corner_flag
    LEFT JOIN
       (SELECT v.product_id as product_id,Count(*) as last_two_week_hits
            FROM   visitor_tracking_pages v
           WHERE v.last_click >= '1380153600' group by v.product_id 
        ) as vtp ON vtp.product_id = p.id
WHERE  p.visible = '1' AND ( p.area = 'Dining Room Furniture'
      OR p.additionarea = 'Dining Room Furniture' )
   AND ( p.subcat = 'Dining Tables'
          OR p.additionsubcat = 'Dining Tables' )
   AND ( p.sale_price = ''
          OR p.offer_price = '0' )
 ORDER BY last_two_week_total_hits DESC  
于 2013-10-09T18:02:58.173 回答
1

我认为这可以解决您的问题,RIGHT JOIN:

SELECT COUNT(*) AS total, p.id as product_id
FROM visitor_tracking_pages vtp RIGHT JOIN products p ON p.id=vtp.product_id
WHERE p.SUBCAT = 'Dining Tables' AND p.visible = '1' AND (vtp.last_click >= '1380153600' or vtp.last_click IS NULL)
GROUP BY p.id
ORDER BY total DESC

RIGHT(或 LEFT)JOIN 执行标准 JOIN,就像在您编写的查询中一样,然后在右(或左)表中添加与连接不匹配的所有行。

要结合您发布的两个查询,您可以执行此查询

SELECT p.id, p.product_name, p.range_name, p.pic_url, p.hits, p.manufacturer, p.standard_price, p.sale_price, p.offer_price, p.discount, p.display_manufacturer, p.display_price, p.visible, p.display_model_results, p.model, p.SUBCAT, p.disable_options, p.request_price, p.corner_flag, cf.flag_name, cf.flag_url, cf.flag_description, p.display_model, p.offer_status, p.disable_options_results, p.added_timestamp, p.about, p.keywords
FROM products p, corner_flags cf LEFT JOIN visitor_tracking_pages vtp ON vtp.product_id=p.id
WHERE (p.AREA='Dining Room Furniture' OR p.AdditionAREA='Dining Room Furniture') AND (p.SUBCAT='Dining Tables' OR p.AdditionSUBCAT='Dining Tables') AND p.sale_price='' AND p.visible='1' AND p.corner_flag = cf.flag_id AND (p.sale_price= '' OR p.offer_price = '0') AND p.visible='1'
AND (vtp.last_click >= '1380153600' or vtp.last_click IS NULL)
GROUP BY p.id
ORDER BY COUNT(*), p.hits DESC

我知道这不是完美的方法,因为规范地,字段列表中允许的唯一字段是 GROUP BY 子句中提到的字段,但它有效,您可以在 ORDER BY 子句中使用 COUNT(*)。

做你需要的另一种方法是使用我编写的第一个查询创建一个视图,例如 *view_order* 然后使用它作为一个数字来避免使用 GROUP BY 的各种问题,使用这个查询:

SELECT p.id, p.product_name, p.range_name, p.pic_url, p.hits, p.manufacturer, p.standard_price, p.sale_price, p.offer_price, p.discount, p.display_manufacturer, p.display_price, p.visible, p.display_model_results, p.model, p.SUBCAT, p.disable_options, p.request_price, p.corner_flag, cf.flag_name, cf.flag_url, cf.flag_description, p.display_model, p.offer_status, p.disable_options_results, p.added_timestamp, p.about, p.keywords
FROM products p, corner_flags cf JOIN view_order vtp ON vtp.product_id=p.id
WHERE (p.AREA='Dining Room Furniture' OR p.AdditionAREA='Dining Room Furniture') AND (p.SUBCAT='Dining Tables' OR p.AdditionSUBCAT='Dining Tables') AND p.sale_price='' AND p.visible='1' AND p.corner_flag = cf.flag_id AND (p.sale_price= '' OR p.offer_price = '0') AND p.visible='1'
ORDER BY vtp.totale, p.hits DESC
于 2013-10-09T17:21:03.190 回答
0

感谢所有的帮助!

Ravi - 您的优化有效,但由于某种原因,它停止返回过去 14 天内未查看的产品。

最后,我终于想出了一个可行的解决方案。

如果您看到任何进一步的改进,请告诉我:)

我创建了一个名为 Popular_products 的新表,并编写了一个脚本来每天(通过 cron 作业)使用来自查询 visitor_tracking_pages 表的新命中计数来填充此表。

TRUNCATE TABLE 在添加新结果之前删除前几天的结果。

$timestamp = strtotime("-2 week");

mysql_query("TRUNCATE TABLE  `popular_products`");

$result = mysql_query("SELECT COUNT(*) AS total, product_id 
FROM visitor_tracking_pages vtp 
WHERE  vtp.product_id != '' AND vtp.last_click >= '$timestamp' 
GROUP BY product_id");

while($row = mysql_fetch_array($result)){

mysql_query("INSERT INTO popular_products (product_id, total_views) 
VALUES ('$row[1]','$row[0]')");

}

然后,这使我可以将其添加到结果中,而无需即时运行查询。

在过去 2 周内未查看的产品返回为 NULL,这很好。

SELECT p.id, 
   p.product_name, 
   p.range_name, 
   p.pic_url, 
   p.hits, 
   p.manufacturer, 
   p.standard_price, 
   p.sale_price, 
   p.offer_price, 
   p.discount, 
   p.display_manufacturer, 
   p.display_price, 
   p.visible, 
   p.display_model_results, 
   p.model, 
   p.subcat, 
   p.disable_options, 
   p.request_price, 
   p.corner_flag, 
   cf.flag_name, 
   cf.flag_url, 
   cf.flag_description, 
   p.display_model, 
   p.offer_status, 
   p.disable_options_results, 
   p.added_timestamp, 
   p.about, 
   p.keywords, 
   (SELECT pp.total_views 
       FROM popular_products pp 
       WHERE pp.product_id = p.id 
   ) AS total_views 
FROM products p, corner_flags cf 
WHERE p.visible='1' 
   AND (p.AREA='Dining Room Furniture' OR p.AdditionAREA='Dining Room Furniture') 
   AND (p.SUBCAT='Dining Tables' OR p.AdditionSUBCAT='Dining Tables') 
   AND p.corner_flag = cf.flag_id 
   AND p.sale_price= '' 
ORDER BY ABS(total_views) DESC
于 2013-10-10T17:08:25.073 回答
0

有什么办法可以进一步过滤命中数?... 基本上,一些访问者在产品之间来回滑动多次,这表明该产品获得了更多实际拥有的浏览量。

在visitor_tracking_pages 表中查询一个产品显示它总共被查看了7 次,但实际上它只被5 个唯一访问者查看。

SELECT ip_address, product_id
FROM  `visitor_tracking_pages` 
WHERE  `product_id` =  '1562805'
AND  `last_click` >=  '1380153600'

| ip_address   | product_id |
-----------------------------
| 192.168.0.1  | 1562805    |
| 192.168.0.1  | 1562805    |
| 192.168.0.2  | 1562805    |
| 192.168.0.3  | 1562805    |
| 192.168.0.4  | 1562805    |
| 192.168.0.1  | 1562805    |
| 192.168.0.5  | 1562805    |
-----------------------------
于 2013-10-11T12:17:54.227 回答