2010-10-14 56 views
0

我正在使用我们班的PostgreSQL服务器上的SQL进行我的第一个任务。样品数据库具有(部分在这里)模式:PostgreSQL不必要的查询修剪结果

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。

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

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; 

任何帮助将不胜感激。

+1

用少量的用户测试了你的模式 - 查询工作正常。检查为错过的用户插入的数据。 – 2010-10-14 08:28:23

+0

当你忽略“COUNT”聚合列时会发生什么?你会得到那些你认为它们是空的行吗? – Pointy 2010-10-14 14:22:09

回答

0

尽量避免在子查询中使用DISTINCT。

+0

从COUNT集合中删除DISTINCT关键字并没有改变任何东西,看起来(除了输出是按ID排序的,现在是未排序的)。 – Ganon11 2010-10-14 08:21:58

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 
;