2015-05-29 55 views
0

这里的不同条件和总数计算是一个样表我有SQL查询来找到在同一查询

Logs 
user_id, session_id, search_query, action 
1, 100, dog, A 
1, 100, dog, B 
2, 101, cat, A 
3, 102, ball, A 
3, 102, ball, B 
3, 102, kite, A 
4, 103, ball, A 
5, 104, cat, A 

其中 错过=为同一USER_ID和相同的会话ID,如果动作A其次是行动B,它被称为小姐。
注意:只有在行动A发生后才可能发生行动B.

我能够找到所有用户和会话中每个唯一search_query的未命中数。

SELECT l1.search_query, count(l1.*) as misses 
FROM logs l1 
WHERE NOT EXISTS 
    (SELECT NULL FROM logs l2 
    WHERE l1.user_id = l2.user_id 
    AND l1.session_id = l2.session_id 
    AND l1.session_id != '' 
    AND l2.action = 'B' 
    AND l1.action = 'A') 
AND l1.action='A' 
AND l1.search_query != '' 
GROUP BY v1.search_query 
order by misses desc; 

我想为每个唯一的search_query找到miss_percentage =(失误次数/总行数)* 100的值。我无法弄清楚如何在一个查询中找到一个条件计数并且没有这个条件的计数。任何帮助都会很棒。

expected output: 
cat 100 
kite 100 
ball 50 

回答

0

一种方式来做到这一点是在EXISTS进入计数

SELECT l1.search_query, count(case when NOT EXISTS 
    (SELECT 1 FROM logs l2 
    WHERE l1.user_id = l2.user_id 
    AND l1.session_id = l2.session_id 
    AND l1.search_query = l2.search_query 
    AND l2.action = 'B' 
    AND l1.action = 'A') then 1 else null end 
)*100.0/count(*) as misses 
FROM logs l1 
WHERE l1.action='A' 
AND l1.search_query != '' 
GROUP BY l1.search_query 
order by misses desc; 

这将产生预期的效果,但如果被发现也没有零失误。这可以通过HAVING子句或后处理来删除。

注意我还添加了缺失的子句l1.search_query = l2.search_query,因为否则它会将风筝计数成功,因为在同一个会话中有一行B。

+0

对不起,忘了提及此之前。我在亚马逊红移表中运行此查询。我收到以下错误。 '执行SQL命令时发生错误: SELECT l1.search_query,count(NOT EXISTS时的情况) (SELECT 1 FROM logs l2 WHERE l1.user_id = 1 ... 错误:此类型的相关子查询模式不是支持由于内部错误[SQL状态= XX000]' – srini

-1

你可以总是创建两个查询,并将它们合并为一个连接。然后,您可以在桥接(或加入)SQL语句中执行计算。

在MS-SQL兼容SQL这将是:

SELECT ActiontypeA,countedA,isNull(countedB,0) as countedB, 
    (countedA-isNull(countedB,0))*100/CountedA as missed 
    FROM (SELECT search_query as actionTypeA, count(*) as countedA 
      FROM logs WHERE Action='A' GROUP BY actionType 
     ) as TpA 
    LEFT JOIN 
     (SELECT search_query as actionTypeB, count(*) as countedB 
      FROM logs WHERE Action='B' GROUP BY actionType 
     ) as TpB 
ON TpA.ActionTypeA = TpB.ActiontypeB 

LEFT JOIN需要从“A”的结果选择的所有活动(SEARCH_QUERY),并将其从“B”加入到只有那些结果在B可用。 由于这是非常基本的SQL(并且通过SQL引擎进行了很好的优化),我建议尽可能防止WHERE EXISTSIsNull()函数是一个MS-SQL函数,用于将NULL值强制为可用于计算的int(0)值。

最后,你可以过滤对

WHERE missed>0 

得到最终的结果。

+0

如果问题是关于PostgreSQL,为什么要放一个MSSQL解决方案? – Patrick

+0

SQL跨引擎非常兼容。这个答案有助于跨系统的SQL概念。我只能在MS-SQL上测试解决方案。我对这个问题的投票并不满意...... –

+0

SQL是一种标准,MSSQL因其背离而远近闻名,远远超过PostgreSQL。后者没有用于指定目的的'isNull()'函数,但使用'coalesce()'。而且你的代码有错误,无论你在PostgreSQL或MSSQL中运行它。 downvote是一个不适当的答案。 – Patrick

0

我想你只需要在这里使用case语句。如果我已经正确理解你的问题,那么解决方案将是这样的 -

WITH summary 
AS (
    SELECT user_id 
     ,session_id 
     ,search_query 
     ,count(1) AS total_views 
     ,sum(CASE 
       WHEN action = 'A' 
        THEN 1 
       ELSE 0 
       END) AS action_a 
     ,sum(CASE 
       WHEN action = 'B' 
        THEN 1 
       ELSE 0 
       END) AS action_b 
    FROM logs l 
    GROUP BY user_id 
     ,session_id 
     ,search_query 
    ) 
SELECT search_query 
    ,(sum(action_a - action_b)/sum(action_a)) * 100 AS miss_percentage 
FROM summary 
GROUP BY search_query;