如何设计此表架构(以及如何查询它)

时间:2017-09-21 11:10:49

标签: sql database postgresql database-design

我有一个存储成员列表的表 - 为了简单起见,我将使用一个简单的真实案例来模拟我的用例。

让我们使用体育俱乐部或健身房的类比。

健身房的会员资格每三个月更换一次(例如) - 一些老会员离职,一些新会员加入,一些会员保持不变。

我想在桌面上运行一个查询 - 跨越多个时段并返回俱乐部中所有成员的平均权重。

这些是我到目前为止提出的表格:

-- A table containing all members the gym has ever had
-- current members have their leave_date field left at NULL
-- departed members have their leave_date field set to the days they left the gym
CREATE TABLE IF NOT EXISTS member (
                   id              PRIMARY KEY NOT NULL,
                   name            TEXT NOT NULL,
                   join_date       DATE NOT NULL,

                   -- set to NULL if user has not left yet
                   leave_date      DATE DEFAULT NULL
        );


-- A table of members weights. 
-- This table is populated DAILY,after the weights of CURRENT members
-- has been recorded
CREATE TABLE IF NOT EXISTS current_member_weight (
                   id              PRIMARY KEY NOT NULL,
                   calendar_date   DATE NOT NULL,
                   member_id       INTEGER REFERENCES member(id) NOT NULL,
                   weight          REAL NOT NULL
       );


-- I want to write a query that returns the AVERAGE daily weight of
-- CURRENT members of the gym. The query should take a starting_date
-- and an ending_date between which to calculate the daily 
-- averages. The aver

-- PSEUDO SQL BELOW!
SELECT calendar_date, AVG(weight) 
FROM member, current_member_weight
WHERE calendar_date BETWEEN(starting_date, ending_date);

我有两个问题:

  1. 可以改进上面的架构 - 如果是,请说明
  2. 如何编写SQL *查询以返回在指定时间段(t1,t2)内为健身房中所有成员计算的平均权重,其中(t1,t2)跨越成员已加入/离开健身房的时间段?
  3. [[关于SQL的注释]]

    最好,显示的任何SQL都是数据库无关的,但是如果要使用特定的SQL风格,我更喜欢PostgreSQL,因为这是我正在使用的数据库。

1 个答案:

答案 0 :(得分:0)

只要gym_member表中的数据与每个成员的加入和离开日期一致(即对于任何成员,gym_member表不应该具有calendar_date减去其加入日期或者calendar_date更大的行),SQL下面的工作就会起作用。比他的离开日期)

SELECT
    gm.calendar_date,
    AVG(gm.weight) avg_weight
FROM
    member m,
    gym_member gm
WHERE
        m.id = gm.member_id
    AND
        gm.calendar_date >= '1-Jan-2017'
    AND
        gm.calendar_date <= '31-Dec-2017'
GROUP BY
    gm.calendar_date