Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 哪种查询更有效?内部连接与子查询?求和与拥有_Sql_Database_Postgresql_Query Optimization - Fatal编程技术网

Sql 哪种查询更有效?内部连接与子查询?求和与拥有

Sql 哪种查询更有效?内部连接与子查询?求和与拥有,sql,database,postgresql,query-optimization,Sql,Database,Postgresql,Query Optimization,我正在使用PostgreSql 9。我有一个简单的问题。 哪种查询更有效 SELECT users_sessions.session_id, users_sessions.series FROM users_sessions WHERE users_sessions.user_id = 8 AND users_sessions.session_id IN ( SELECT session_id FROM sessions_history GROUP BY ses

我正在使用PostgreSql 9。我有一个简单的问题。 哪种查询更有效

SELECT users_sessions.session_id, users_sessions.series 
FROM users_sessions 
WHERE users_sessions.user_id = 8 
AND users_sessions.session_id IN (
    SELECT session_id 
    FROM sessions_history 
    GROUP BY sessions_history.session_id 
    HAVING SUM(CASE WHEN sessions_history.action = 2 THEN 1 END) = 0
) 
VS

您的第二个查询在语法上无效。不能从HAVING子句中的SELECT list输出列引用列别名

无论如何,这两个查询都不好。如果确实要查找不存在的用户id和操作的组合,请尝试:

SELECT t.*, 0 AS s
FROM  (SELECT 8 AS user_id, 2 AS action) t
LEFT  JOIN (
            users_sessions  us
       JOIN session_history sh USING (session_id)
           ) USING (user_id, action)
WHERE  sh.session_id IS NULL;
我在子查询t中引入了一个具有单行的派生表,并将其左连接到两个基表的组合中。如果组合不存在,则仅返回一行。 假设列名称user_id和action在两个表中只出现一次。否则,请对第二个联接使用更明确的条件:

ON t.user_id = us.user_id AND t.action = sh.action
详情:

可供替代的 可能更快,但:

SELECT t.*, 0 AS s
FROM  (SELECT 8 AS user_id, 2 AS action) t
LEFT   JOIN users_sessions  us USING (user_id)
LEFT   JOIN session_history sh USING (action, session_id)
WHERE  sh.session_id IS NULL;

在本例中,无论采用哪种方式,使用构造都是安全的。

另一个解决方案使用的是NOT EXISTS,这是您所问问题的精确翻译:

请提供不存在操作2的会话:

SELECT session_id, series 
FROM users_sessions as us
WHERE users_sessions.user_id = 8 
AND NOT EXISTS
 (  SELECT * 
    FROM sessions_history as sh
    WHERE action = 2
    AND us.session_id = sh.session_id 
 ) 

你觉得这个怎么样

SELECT US8.session_id,Us8.series

FROM

( SELECT us.session_id as S_ID, us.series 
        FROM users_sessions as US
        WHERE US.user_id = 8 ) AS US8
INNER JOIN
(SELECT SH.session_id as SH_ID
        FROM session_history as SH
        WHERE SH.action <> 2) AS SH2    
ON US8.session_id = SH2.session_id 
我的一便士价值

我可以用两种不同的方式来解释你的意图,并且对每种情况都有不同的解决方案,我的首选解决方案在每种情况下都是第一位的

至少有一个历史记录的会话,其中操作2 不管有多少历史记录,行动=2


检查explain analyze的输出,verboseWell,你试过了吗?第二条似乎都不正确。测试他们,写下所有的结果,然后问一个好问题。你对博士后的看法?9不是有效的版本。“9.2或9.3是……我认为第二个查询是不好的。”KamilJ——纯粹是对欧文观点的评论;正确的语法应该是让SUM1=0重复HAVING子句中SELECT子句的逻辑,或者如果您不想重复自己的话;选择*作为聚合,其中s=0。你真的喜欢使用?当您的查询还包括范围查找等时,它不是真的变得不整洁吗?@MatBailie:我对简短、简洁的代码有一个偏爱。对于持久化查询,更安全的做法是使用显式表单,以减少以后对基础表的架构更改的影响。不过,示例中的第一个USING子句是安全的。会话\u id是否可能在会话\u历史记录中没有对应的行?如果是这样,根据这里的其他答案,您需要左外部联接或不存在类型的查找。这里有很多要点。会话\u id在会话\u历史记录中是否可能有多个对应的行?如果是这样,SH2子查询应该有一个独特的or GROUP BY,以防止结果重复。
SELECT US8.session_id,Us8.series

FROM

( SELECT us.session_id as S_ID, us.series 
        FROM users_sessions as US
        WHERE US.user_id = 8 ) AS US8
INNER JOIN
(SELECT SH.session_id as SH_ID
        FROM session_history as SH
        WHERE SH.action <> 2) AS SH2    
ON US8.session_id = SH2.session_id 
SELECT
    us.session_id,
    us.series
FROM
    users_sessions   AS us
INNER JOIN
    session_history  AS sh
        ON  sh.session_id  = us.session_id
        AND sh.action     <> 2
WHERE
    us.user_id = 8
GROUP BY
    us.session_id,
    us.series
SELECT
    us.session_id,
    us.series
FROM
    users_sessions   AS us
WHERE
        us.user_id = 8
    AND EXISTS (SELECT *
                  FROM session_history  AS sh
                 WHERE sh.session_id  = us.session_id
                   AND sh.action     <> 2
               )
SELECT
    us.session_id,
    us.series
FROM
    users_sessions   AS us
INNER JOIN
(
    SELECT
        session_id
    FROM
        session_history
    WHERE
        sh.action <> 2
    GROUP BY
        session_id
)
    AS sh
        ON  sh.session_id  = us.session_id
WHERE
    us.user_id = 8
SELECT
    us.session_id,
    us.series
FROM
    users_sessions   AS us
LEFT JOIN
    session_history  AS sh
        ON  sh.session_id = us.session_id
        AND sh.action     = 2
WHERE
        us.user_id     = 8
    AND sh.session_id IS NULL

-- No GROUP BY needed this time
SELECT
    us.session_id,
    us.series
FROM
    users_sessions   AS us
WHERE
        us.user_id = 8
    AND NOT EXISTS (SELECT *
                     FROM session_history  AS sh
                     WHERE sh.session_id = us.session_id
                       AND sh.action     = 2
                   )