有没有更有效的方法来编写此SQL查询?

时间:2015-05-30 22:26:32

标签: sql sql-server tsql azure-sql-database

我有一个包含几百万条记录的表,它通过SessionGUID(访问者)存储产品视图,表结构为:

ID(PK) SessionGUID(uniqueidentifier) ProductID(int) DateTime(日期时间)

查询的目的是返回由查看特定产品ID的相同人员查看的产品ID列表(即,查看X的客户也查看了Y)

我正在使用的查询如下:

SELECT
A.ProductID
FROM
VISITOR_SESSIONS_PRODUCTVIEWS A
WHERE
A.SessionGUID IN (SELECT DISTINCT SessionGUID FROM VISITOR_SESSIONS_PRODUCTVIEWS WHERE ProductID = @ProductID)
GROUP BY
A.ProductID
ORDER BY
COUNT(A.ProductID) DESC

是否有更有效的方法使用GROUP BY / HAVING / PARTITON或其他更优化的方法来获取数据,这是我需要的方式?

我在我的开发服务器上运行SQL 2008,但它将在SQL Azure上线时运行。

3 个答案:

答案 0 :(得分:2)

EXISTS通常比IN更有效:

SELECT A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
WHERE EXISTS (SELECT 1
              FROM VISITOR_SESSIONS_PRODUCTVIEWS B
              WHERE B.ProductID = @ProductID AND
                    A.SessionGUID = B.SessionGUID
             )
GROUP BY A.ProductID
ORDER BY COUNT(A.ProductID) DESC;

为了获得最佳效果,您需要VISITOR_SESSIONS_PRODUCTVIEWS(SessionGUID, ProductId)上的索引,也许还需要VISITOR_SESSIONS_PRODUCTVIEWS(ProductId)

编辑:

你可以尝试使用窗口函数来编写它,但我不确定性能会更好:

select productid
from (select pv.*,
             sum(case when productid = @productid then 1 else 0 end) over (partition by SessionGUID) as cnt
      from visitor_sessions_productviews 
     ) pv
where cnt > 0
group by productid
order by count(*) desc;

我不确定性能会比EXISTS方法更好。

答案 1 :(得分:0)

有几种方法可以用不同的方式写出可能表现更好的方法:

  • 会话临时表,然后使用这些会话加入VISITOR_SESSIONS_PRODUCTVIEWS
  • 加入VISITOR_SESSIONS_PRODUCTVIEWS与产品的会话,然后与这些会话重新加入VISITOR_SESSIONS_PRODUCTVIEWS
  • EXISTS代替DISTINCT查询该用户会话中存在的产品

这是临时表解决方案:

SELECT DISTINCT SessionGUID 
INTO #sessionsWithProduct
FROM VISITOR_SESSIONS_PRODUCTVIEWS
WHERE ProductID = @ProductID;

SELECT
    A.ProductID
FROM VISITOR_SESSIONS_PRODUCTVIEWS A
    INNER JOIN #sessionsWithProduct S ON s.SessionGUID = A.SessionGUID
GROUP BY A.ProductID
ORDER BY COUNT(A.ProductID) DESC;

DROP TABLE #sessionsWithProduct;

非常重要的是确保此表在ProductID和SessionGUID(每个上一个)上至少索引

答案 2 :(得分:0)

SELECT A.ProductID
  FROM VISITOR_SESSIONS_PRODUCTVIEWS A
  JOIN VISITOR_SESSIONS_PRODUCTVIEWS S
    ON A.SessionGUID = S.SessionGUID 
   AND S.ProductID = @ProductID 
 GROUP B A.ProductID
 ORDER BY COUNT(DISTINCT(A.ProductID)) DESC