list count with count aggregation function

时间:2017-02-24 22:33:29

标签: sql postgresql postgresql-9.1

想象一下这些表结构

组织表

 ===================== 
| id |      name      |
-----+----------------+
| 1  | Organization 1 |
 =====================

放置表格

 ================================= 
| id |   name   | organization_id |
-----+----------+-----------------+
| 1  | Place 1  |        1        |
-----+----------+-----------------+
| 2  | Place 2  |        1        |
-----+----------+-----------------+
| 3  | Place 3  |        1        |
 =================================

个人资料表

 ============= 
|  username   |
--------------
| 111@xxx.com |
--------------
| 222@xxx.com |
 =============

访问目录表

 ================================================ 
| id | place_id | profile_username | visiteddate |
-----+----------+---------------- -+-------------+
| 1  |     1    |   111@xxx.com    | 2017-01-01  |
-----+----------+------------------+-------------+
| 2  |     2    |   111@xxx.com    | 2017-02-01  |
-----+----------+------------------+-------------+
| 3  |     1    |   111@xxx.com    | 2017-01-15  |
 ================================================

接下来是用于创建表格和向其中插入数据的sql语句

-- ----------------------------
-- Table structure for organization
-- ----------------------------
DROP TABLE IF EXISTS "organization";
CREATE TABLE "organization" (
"id" int4 NOT NULL,
"name" varchar(255) COLLATE "default" NOT NULL
) WITH (OIDS=FALSE);
-- ----------------------------
-- Records of organization
-- ----------------------------
BEGIN;
INSERT INTO "organization" VALUES ('1', 'Organization 1');
COMMIT;
-- ----------------------------
-- Table structure for place
-- ----------------------------
DROP TABLE IF EXISTS "place";
CREATE TABLE "place" (
"id" int4 NOT NULL,
"name" varchar(255) COLLATE "default" NOT NULL,
"organization_id" int4 NOT NULL
)WITH (OIDS=FALSE);
-- ----------------------------
-- Records of place
-- ----------------------------
BEGIN;
INSERT INTO "place" VALUES ('1', 'Place 1', '1');
INSERT INTO "place" VALUES ('2', 'Place 2', '1');
INSERT INTO "place" VALUES ('3', 'Place 3', '1');
COMMIT;
-- ----------------------------
-- Table structure for profile
-- ----------------------------
DROP TABLE IF EXISTS "profile";
CREATE TABLE "profile" (
"username" varchar(255) COLLATE "default" NOT NULL
)WITH (OIDS=FALSE);
-- ----------------------------
-- Records of profile
-- ----------------------------
BEGIN;
INSERT INTO "profile" VALUES ('111@xxx.com');
INSERT INTO "profile" VALUES ('222@xx.com');
COMMIT;
-- ----------------------------
-- Table structure for visitedplace
-- ----------------------------
DROP TABLE IF EXISTS "visitedplace";
CREATE TABLE "visitedplace" (
"id" int4 NOT NULL,
"place_id" int4 NOT NULL,
"profile_username" varchar(255) COLLATE "default" NOT NULL,
"visiteddate" date NOT NULL
)WITH (OIDS=FALSE);
-- ----------------------------
-- Records of visitedplace
-- ----------------------------
BEGIN;
INSERT INTO "visitedplace" VALUES ('1', '1', '111@xxx.com', '2017-02-24');
COMMIT;
-- ----------------------------
-- Alter Sequences Owned By 
-- ----------------------------
-- ----------------------------
-- Primary Key structure for table organization
-- ----------------------------
ALTER TABLE "organization" ADD PRIMARY KEY ("id");
-- ----------------------------
-- Primary Key structure for table place
-- ----------------------------
ALTER TABLE "place" ADD PRIMARY KEY ("id");
-- ----------------------------
-- Primary Key structure for table profile
-- ----------------------------
ALTER TABLE "profile" ADD PRIMARY KEY ("username");
-- ----------------------------
-- Primary Key structure for table visitedplace
-- ----------------------------
ALTER TABLE "visitedplace" ADD PRIMARY KEY ("id");
-- ----------------------------
-- Foreign Key structure for table "place"
-- ----------------------------
ALTER TABLE "place" ADD FOREIGN KEY ("organization_id") REFERENCES
"organization" ("id") ON DELETE CASCADE ON UPDATE CASCADE;
------------------------------
-- Foreign Key structure for table "visitedplace"
-- ----------------------------
ALTER TABLE "visitedplace" ADD FOREIGN KEY ("profile_username") REFERENCES    "profile" ("username") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "visitedplace" ADD FOREIGN KEY ("place_id") REFERENCES "place" ("id

") ON DELETE CASCADE ON UPDATE CASCADE;

我的问题是

当我运行下一个查询时

select profile.username, count(distinct place.id)
    from profile profile 
    left outer join visitedplace visitedplace on profile.username=visitedplace.profile_username 
    inner join place place on visitedplace.place_id=place.id
    where place.organization_id=1
    group by profile.username

返回下一个结果

 ===================== 
|  username   | count |
 -------------+-------
| 111@xxx.com |   2   |
 =====================

但我期待下一个结果

 ===================== 
|  username   | count |
 -------------+-------
| 111@xxx.com |   2   |
 -------------+-------
| 222@xxx.com |   0   |
 =====================

那么我怎样才能使查询返回我期待的内容?

我正在使用Postgres

1 个答案:

答案 0 :(得分:1)

使用正在使用left join。因此,所有连接都应该是外连接(在第一个连接之后)。并且,您必须小心where子句:

select p.username, count(distinct place.id)
from profile p left outer join
     visitedplace vp
     on p.username = vp.profile_username left join
     place pl
     on vp.place_id = pl.id and pl.organization_id = 1
group by p.username;

如果您不小心,那么外部联接将变为inner join