sql - 使用 NOT IN 展平​​ WHERE 子句中的嵌套查询

标签 sql postgresql

假设我有这两个表,为了解决问题而进行了简化:

CREATE TABLE merchandises
(
  id BIGSERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  price INT NOT NULL
)

CREATE TABLE gifts
(
  id BIGSERIAL NOT NULL PRIMARY KEY,
  from_user VARCHAR(255) REFERENCES users(id),
  to_user VARCHAR(255) REFERENCES users(id),
  with_merchandise BIGINT REFERENCES merchandises(id)
)

商品 表列出了可用的商品。 gifts 表显示用户将商品作为礼物发送给另一个用户的记录(有适当的索引以避免重复)。

我想查询的是一个用户可以发送给另一个用户的商品列表,前提是这些商品之前不应该被赠送。

这是一个可行的查询,但我希望能找到一个没有嵌套查询的查询,认为由于 POSTGRESQL 的优化器,它可能会提供更好的性能。

SELECT DISTINCT ON (m.id) m.id, m.name, m.description
FROM merchandises m
WHERE m.id NOT IN (
    SELECT g.with_merchandise
    FROM gifts g
    WHERE g.from_user = 'some_user_id' AND g.to_user = 'some_other_user_id'
)
ORDER BY m.id ASC
LIMIT 20 OFFSET 0

在之前的尝试中,我有过这样的查询,但我发现它不起作用:

SELECT DISTINCT ON (m.id) m.id, m.name, m.description
FROM merchandises m
LEFT JOIN gifts g
ON m.id = g.with_merchandise
WHERE g.id IS NULL 
OR g.from_user <> 'some_user_id' AND g.to_user <> 'some_other_user_id'
ORDER BY m.id ASC
LIMIT 20 OFFSET 0

此查询不起作用,因为即使 WHERE 子句过滤掉两个特定用户的礼物条目,其他两个用户也可能使用相同的商品(相同的 Mercury_id)赠送了礼物。

最佳答案

即使您要求删除子查询,使用 not contains 子查询可能会比 not in 运行得更快,尤其是在 not in 查询的情况下返回很多值:

SELECT m.id, m.name, m.description
FROM merchandises m
WHERE NOT EXISTS (
    SELECT 1
    FROM gifts g
    WHERE g.with_merchandise = m.id
    AND g.from_user = 'some_user_id'
    AND g.to_user = 'some_other_user_id'
)

此查询可以利用 gifts(with_merchandise,from_user,to_user)

上的复合键

如果您仍然倾向于使用 left join,则将 from_userto_user 的条件从 where 移走到 on 子句

SELECT m.id, m.name, m.description
FROM merchandises m
LEFT JOIN gifts g ON m.id = g.with_merchandise
  AND g.from_user = 'some_user_id' AND g.to_user = 'some_other_user_id' 
WHERE g.id IS NULL 
ORDER BY m.id ASC
LIMIT 20 OFFSET 0

关于sql - 使用 NOT IN 展平​​ WHERE 子句中的嵌套查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33447891/

相关文章:

mysql - SQL根据日期和另一列减去两行

sql - 从 GROUP BY 操作中选择最大计数

entity-framework - 将自定义数据源添加到 visual studio 2015

python - aiohttp.web + aiopg + sqlalchemy : random "cursor.execute() called while another coroutine is already waiting for incoming data" under load

javascript - Sails.js - 如何避免 Sails JS 在数据库表上查找 Id(因为该表没有 id 列)

sql - 带有 PostgreSQL 的 Rails 3 应用程序 - 获取按对话分组的消息列表

mysql - 如何使用 SQL 查询连接数据库中具有相似名称的一组表?

sql - 如何使用存储过程从行中选择数据并将其显示为列?

sql - Postgres/Rails Active Record——查询四舍五入的浮点值

postgresql - 时间戳变量和时间变量的区别