Sql查询以在同一查询中查找条件不同的计数和总计数

Sql查询以在同一查询中查找条件不同的计数和总计数,sql,postgresql,amazon-redshift,postgresql-8.4,Sql,Postgresql,Amazon Redshift,Postgresql 8.4,这是我的样品表 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 在哪里 未命中=对于相同的用户id和相同的会话id,如果操作A后面没有操作B,则称为未命中。 注意:动作B只能在动作A发生后发生 我能够找

这是我的样品表

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
在哪里 未命中=对于相同的用户id和相同的会话id,如果操作A后面没有操作B,则称为未命中。 注意:动作B只能在动作A发生后发生

我能够找到所有用户和会话中每个唯一搜索查询的未命中计数

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;
对于每个唯一的搜索查询,我试图查找未命中百分比=未命中数/总行数*100的值。我不知道如何在同一个查询中找到带条件的计数和不带条件的计数。任何帮助都会很好

expected output:
cat 100
kite 100
ball 50 

一种方法是将EXISTS移到count中

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\u query=l2.search\u query子句,因为在同一会话中有一行包含B,所以它被视为已成功。

您可以始终创建两个查询,并使用联接将它们合并为一个查询。然后可以在桥接或连接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
需要使用左联接从“A”结果中选择所有活动搜索查询,并仅将其联接到“B”结果中有“B”可用的活动。 因为这是非常基本的SQL,并且经过SQL引擎的优化,所以我建议尽可能地防止WHERE的存在。IsNull函数是一个MS-SQL函数,用于将NULL值强制转换为可用于计算的int0值

最后你可以过滤了

WHERE missed>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;

如果问题是关于PostgreSQL的,为什么要使用MSSQL解决方案呢?SQL在不同引擎之间非常兼容。这个答案有助于跨系统使用SQL的概念。我只能在MS-SQL上测试解决方案。我对这一点的否决票不太满意……SQL是一个标准,MSSQL以偏离它而闻名,远远超过PostgreSQL。后者没有用于指定目的的isNull函数,但使用coalesce。无论是在PostgreSQL还是MSSQL中运行,您的代码中都有错误。否决票是因为回答不充分。对不起,以前忘了提这个。我正在amazon红移表中运行此查询。我得到以下错误。执行SQL命令时出错:SELECT l1.search\U query,countcase当不存在时从日志l2中选择1,其中l1.user\U id=l。。。错误:由于内部错误[SQL State=XX000],不支持这种类型的相关子查询模式