我在每种类型的所有适当的ID字段上都有索引/原色。我想知道如何让这个更有效率。加载只有15,000行的页面需要一段时间,而且很快就会增长到500k。
$whereSql
变量只有一些主ebay_archive_listing
表的参数。
注意:这都是在一个查询中完成的,因为我对每个子查询值都有ASC / DESC排序。
注意:我已将部分子查询转换为INNER JOIN
的
当我更改所有子查询值以使用如下所示的相同子查询时,我得到以下SQL错误:
Unknown column 'product_master.product_id' in 'on clause
我只能假设这是指提取所有AVG,MIN和MAX的子查询,因为它是我唯一改变的东西。虽然我不确定为什么它现在抛出这个错误而不是它全部分裂成不同的值。
SELECT
product_master.product_id,
(
SELECT
COUNT(listing_id)
FROM ebay_archive_product_listing_assoc '.$listingCountJoin.'
WHERE ebay_archive_product_listing_assoc.product_id = product_master.product_id) as listing_count,
sku,
type_id,
(
SELECT
AVG(ebay_archive_listing.current_price) AS average_bid_price,
AVG(ebay_archive_listing.buy_it_now_price) AS average_buyout_price,
MIN(ebay_archive_listing.current_price) AS lowest_bid_price,
MAX(ebay_archive_listing.current_price) AS highest_bid_price,
MIN(ebay_archive_listing.buy_it_now_price) AS lowest_buyout_price,
MAX(ebay_archive_listing.buy_it_now_price) AS highest_buyout_price
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
),
round(((
SELECT
COUNT(ebay_archive_listing.id)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.status_id = 2
) / (
SELECT
COUNT(listing_id)
FROM ebay_archive_product_listing_assoc '.$listingCountJoin.'
WHERE ebay_archive_product_listing_assoc.product_id = product_master.product_id ) * 100), 1) as sold_percent
FROM product_master
'.$joinSql.'
WHERE product_master.product_id IN (
SELECT
product_id
FROM ebay_archive_product_listing_assoc
INNER JOIN ebay_archive_listing ON (
ebay_archive_listing.id = ebay_archive_product_listing_assoc.listing_id AND
'.$whereSql.'
)
)
=======================以下原文====================== =====================
SELECT
product_master.product_id,
(
SELECT
COUNT(listing_id)
FROM ebay_archive_product_listing_assoc '.$listingCountJoin.'
WHERE ebay_archive_product_listing_assoc.product_id = product_master.product_id) as listing_count,
sku,
type_id,
(
SELECT
AVG(ebay_archive_listing.current_price)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
) as average_bid_price,
(
SELECT
AVG(ebay_archive_listing.buy_it_now_price)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.buy_it_now_price > 0
) as average_buyout_price,
(
SELECT
MIN(ebay_archive_listing.current_price)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
) as lowest_bid_price,
(
SELECT
MAX(ebay_archive_listing.current_price)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
) as highest_bid_price,
(
SELECT
MIN(ebay_archive_listing.buy_it_now_price)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
) as lowest_buyout_price,
(
SELECT
MAX(ebay_archive_listing.buy_it_now_price)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
) as highest_buyout_price,
round(((
SELECT
COUNT(ebay_archive_listing.id)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.status_id = 2
) / (
SELECT
COUNT(listing_id)
FROM ebay_archive_product_listing_assoc '.$listingCountJoin.'
WHERE ebay_archive_product_listing_assoc.product_id = product_master.product_id ) * 100), 1) as sold_percent
FROM product_master
'.$joinSql.'
WHERE product_master.product_id IN (
SELECT
product_id
FROM ebay_archive_product_listing_assoc
INNER JOIN ebay_archive_listing ON (
ebay_archive_listing.id = ebay_archive_product_listing_assoc.listing_id AND
'.$whereSql.'
)
)
答案 0 :(得分:3)
虽然我不确定你的whereSql
可能带来什么,但使用简单连接来做这类事情似乎要容易得多(也更快)。在你真的需要之前不要诉诸子查询。
诀窍是使用CASE
条件排除您不想要的0价格列以返回NULL
(聚合函数将忽略),而不是尝试将该条件放入子查询WHERE
子句:
SELECT
p.product_id, p.sku, p.type_id,
COUNT(l.listing_id) AS listing_count,
AVG(CASE WHEN l.current_price>0 THEN l.current_price ELSE NULL END) AS average_bid_price,
MIN(CASE WHEN l.current_price>0 THEN l.current_price ELSE NULL END) AS lowest_bid_price,
MAX(CASE WHEN l.current_price>0 THEN l.current_price ELSE NULL END) AS highest_bid_price,
AVG(CASE WHEN l.buy_it_now_price>0 THEN l.buy_it_now_price ELSE NULL END) AS average_buyout_price,
MIN(CASE WHEN l.buy_it_now_price>0 THEN l.buy_it_now_price ELSE NULL END) AS lowest_buyout_price,
MAX(CASE WHEN l.buy_it_now_price>0 THEN l.buy_it_now_price ELSE NULL END) AS highest_buyout_price,
AVG(CASE WHEN l.status_id=2 THEN 100 ELSE 0 END) AS sold_percent
FROM product_master AS p
JOIN ebay_archive_product_listing_assoc AS pl ON pl.product_id=p.product_id
JOIN ebay_archive_listing AS l ON l.listing_id=pl.listing_id
GROUP BY p.product_id
WHERE '.$whereSql.'
答案 1 :(得分:1)
我理解您需要更快的查询。但你也应该读到这个:
http://en.wikipedia.org/wiki/SQL_injection
至于你的查询,你至少应该:
尽可能避免相关子查询(取决于数据量,查询选择性,索引和DBMS优化器)
在同一子查询中检索min(),max()和avg()
提供了一个完整的示例,因为没有人知道$ whereSql,$ listingCountJoin和$ joinSql中的内容。
关于这个主题的好书,我建议Refactoring SQL Applications。
答案 2 :(得分:1)
1)摆脱重复的查询。 通过从...中选择MIN(...),MAX(...),AVG(...)两个类别。
答案 3 :(得分:0)
有点像这样的东西更好
SELECT
product_master.product_id,
(
SELECT
COUNT(listing_id)
FROM ebay_archive_product_listing_assoc '.$listingCountJoin.'
WHERE ebay_archive_product_listing_assoc.product_id = product_master.product_id) as listing_count,
sku,
type_id,
average_bid_price,
average_buyout_price,
lowest_bid_price,
highest_bid_price,
lowest_buyout_price,
highest_buyout_price,
round(((
SELECT
COUNT(ebay_archive_listing.id)
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id AND
ebay_archive_product_listing_assoc.product_id = product_master.product_id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.status_id = 2
) / (
SELECT
COUNT(listing_id)
FROM ebay_archive_product_listing_assoc '.$listingCountJoin.'
WHERE ebay_archive_product_listing_assoc.product_id = product_master.product_id ) * 100), 1) as sold_percent
FROM product_master LEFT OUTER JOIN
(
SELECT ebay_archive_product_listing_assoc.product_id ,
AVG(ebay_archive_listing.current_price) average_bid_price,
AVG(ebay_archive_listing.buy_it_now_price) average_buyout_price,
MIN(ebay_archive_listing.current_price) lowest_bid_price,
MAX(ebay_archive_listing.current_price) highest_bid_price,
MIN(ebay_archive_listing.buy_it_now_price) lowest_buyout_price,
MAX(ebay_archive_listing.buy_it_now_price) highest_buyout_price
FROM ebay_archive_listing
INNER JOIN ebay_archive_product_listing_assoc ON (
ebay_archive_product_listing_assoc.listing_id = ebay_archive_listing.id
)
WHERE '.$whereSql.' AND
ebay_archive_listing.current_price > 0
GROUP BY ebay_archive_product_listing_assoc.product_id
) eal ON eal.product_id = product_master.product_id
'.$joinSql.'
WHERE product_master.product_id IN (
SELECT
product_id
FROM ebay_archive_product_listing_assoc
INNER JOIN ebay_archive_listing ON (
ebay_archive_listing.id = ebay_archive_product_listing_assoc.listing_id AND
'.$whereSql.'
)
)
但是还可以做更多的事情,whereSql和joinSql的值是什么?