PostgreSQL查询修剪结果不必要

时间:2010-10-14 07:10:21

标签: sql postgresql

我正在使用我们的类'PostgreSQL服务器上的SQL进行第一次作业。示例数据库具有(部分此处)架构:

CREATE TABLE users (
  id int PRIMARY KEY,
  userStatus varchar(100),
  userType varchar(100),
  userName varchar(100),
  email varchar(100),
  age int,
  street varchar(100),
  city varchar(100),
  state varchar(100),
  zip varchar(100),
  CONSTRAINT users_status_fk FOREIGN KEY (userStatus) REFERENCES userStatus(name),
  CONSTRAINT users_types_fk FOREIGN KEY (userType)  REFERENCES userTypes(name)
);

CREATE TABLE events (
  id int primary key,
  title varchar(100),
  edate date,
  etime time,
  location varchar(100),
  user_id int,    -- creator of the event
  CONSTRAINT events_user_fk FOREIGN KEY (user_id) REFERENCES users(id)
);

CREATE TABLE polls (
  id int PRIMARY KEY,
  question varchar(100),
  creationDate date,
  user_id int,  --creator of the poll
  CONSTRAINT polls_user_fk FOREIGN KEY (user_id) REFERENCES users(id)
);

和一堆样本数据(特别是127个样本用户)。

我必须编写一个查询来查找用户在过去一年内创建的民意调查数量,以及过去一年中用户创建的事件数量。诀窍是,如果用户没有这样的民意调查/事件,我应该为两列提供0的行。

我有一个查询似乎返回正确的数据,但只有127个用户中的116个,当WHERE子句只检查poll / event的属性时,我无法理解为什么查询正在修剪这11个用户。以下是我的询问:

SELECT u.id, u.userStatus, u.userType, u.email, -- Return user details
       COUNT(DISTINCT e.id) AS NumEvents, -- Count number of events
       COUNT(DISTINCT p.id) AS NumPolls -- Count number of polls
FROM (users AS u LEFT JOIN events AS e ON u.id = e.user_id) LEFT JOIN polls AS p ON u.id = p.user_id
WHERE (p.creationDate IS NULL OR ((now() - p.creationDate) < INTERVAL '1' YEAR) OR -- Only get polls created within last year
      e.edate IS NULL OR ((now() - e.edate) < INTERVAL '1' YEAR)) -- Only get events that happened during last year
GROUP BY u.id, u.userStatus, u.userType, u.email;

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:1)

使用不同的查询似乎有效。这就是我最终的结果:

SELECT u.id, u.userStatus, u.userType, u.email, COUNT(DISTINCT e.id) AS numevents, COUNT(DISTINCT p.id) AS numpolls
FROM users AS u LEFT OUTER JOIN (SELECT * FROM events WHERE ((now() - edate) < INTERVAL '1' YEAR)) AS e ON u.id = e.user_id
     LEFT OUTER JOIN (SELECT * FROM polls WHERE ((now() - creationDate) < INTERVAL '1' YEAR)) AS p ON u.id = p.user_id
GROUP BY u.id, u.userStatus, u.userType, u.email
;

答案 1 :(得分:0)

例如,尽量避免将DISTINCT用于子查询。