【问题标题】:How to design this table schema (and how to query it)如何设计这个表模式(以及如何查询它)
【发布时间】:2017-09-21 11:10:49
【问题描述】:

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

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

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

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

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

-- 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) 跨越成员加入/离开健身房的时间段?

[[关于 SQL 的注意事项]]

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

【问题讨论】:

  • 我会更改表名并删除第三个表,因为您可以查询该表,并且一旦存储它就会过时。
  • @juergend 按照您的建议删除了第三张表,以澄清问题。关于更改表名 - 您建议使用什么名称?
  • 其实我不知道member和gym_member的区别。也许使用用户和会员。会员有一个更好的词,但我现在想不起来了
  • 您不清楚您的表中有什么或您想要什么查询结果。请完成这些句子:行 (id, name, ...) is in Member when person id has name name i> ... 并在 leave_date 离开或没有离开且 leave_date 为空;当 ... 时,行 (id, ...) 在 Gym_Member 中;行(calendar_dateweight)在查询结果中当某人id ...”。PS如果一个人离开并重新加入怎么办? PPS“基本上”当不在其他地方总结清晰时是一个华夫格词,意思是“不”,当一个人知道或怀疑一个人还没有时,它可以让一个人假装自己已经足够清楚了。
  • @philipxy 具有讽刺意味的是,我也不明白你的意思。能否请您转录以下语句:“基本上”当不在其他地方总结清晰时是一个华夫格词,意思是“不”,当一个人知道或怀疑自己还没有时,它可以让一个人假装自己已经足够清楚了。” 请翻译成英文?

标签: sql database postgresql database-design


【解决方案1】:

只要gym_member 表中的数据与每个成员的加入和离开日期一致(即对于任何成员,gym_member 表不应包含 calendar_date 小于其加入日期或 calendar_date 大于比他的离开日期)

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

【讨论】:

  • 很难理解这个有两个否定的说法:does NOT have rows for days when a person was NOT a member。你想说什么?
  • 我认为这可能是 a 正确的解决方案。我稍后会对其进行测试,如果它适用于我的用例,则接受它。
猜你喜欢
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 2012-07-09
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
相关资源
最近更新 更多