两列中的唯一性

时间:2018-04-03 08:08:15

标签: sql postgresql ddl

以下是关于足球的简单数据集:表格 plotOptions: { series: { cursor: 'pointer', point: { events: { click: function () { alert('Category: ' + this.category + ', value: ' + this.y); } } } } }, "series": [ { "name": "Requests", "colorByPoint": true, "data": [ { "name": "Pending", "y": 62, "drilldown": "Pending" }, { "name": "Completed", "y": 20, "drilldown": "Completed" }, { "name": "Rejected", "y": 18, "drilldown": "Rejected" }, ] } ], "drilldown": { "series": [ { "name": "Requests", "id": "Pending", "data": [ [ "New Version", 21 ], [ "HotFixes", 13 ], ], }, 和表格team

match

每个比赛日,每支球队最多只能参加一次外国球队或外国球队。每场比赛必须有2支球队,每支球队只有2支球队。 是否有设计确保团队每个比赛日最多播放一次?

6 个答案:

答案 0 :(得分:3)

// Read from datastore
PCollection<Entity> entities =
        pipeline.apply("ReadFromDatastore",
                DatastoreIO.v1().read().withProjectId(options.getProject())
                        .withQuery(query).withNamespace(options.getNamespace()));

// Apply processing to convert it to BigQuery TableRow
PCollection<TableRow> tableRow =
        entities.apply("ConvertToTableRow", ParDo.of(new ProcessEntityFn()));

// Apply timestamp to TableRow element, and then apply windowing of one day on that
PCollection<TableRow> tableRowWindowTemp =
        tableRow.apply("tableAddTimestamp", ParDo.of(new ApplyTimestampFn())).apply(
                "tableApplyWindow",
                Window.<TableRow> into(CalendarWindows.days(1).withTimeZone(
                        DateTimeZone.forID(options.getTimeZone()))));

// Apply reshuffle with void key to avoid fusion
PCollection<TableRow> tableRowWindow =
        tableRowWindowTemp.apply("Add void key", WithKeys.<Void, TableRow> of((Void) null))
                .apply("Reshuffle", Reshuffle.<Void, TableRow> of())
                .apply("Drop key", Values.<TableRow> create());

// Write windowed output to BigQuery partitions
tableRowWindow.apply(
        "WriteTableToBQ",
        BigQueryIO
                .writeTableRows()
                .withSchema(BigqueryHelper.getSchema())
                .to(TableRefPartition.perDay(options.getProject(),
                        options.getBigQueryDataset(), options.getTableName()))
                .withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_TRUNCATE));

这样可以防止插入匹配匹配日且重叠[home_team_id,foreign_team_id]数组的行。

答案 1 :(得分:2)

听起来像一个独特的约束符合条例草案:

ALTER TABLE match ADD UNIQUE (matchday, home_team_id);
ALTER TABLE match ADD UNIQUE (matchday, foreign_team_id);

如果一个团队可以成为主队外国团队,事情会变得更加复杂,并且您需要这些扩展:

CREATE EXTENSION intarray SCHEMA public;    -- for the "gist__int_ops" opclass
CREATE EXTENSION btree_gist SCHEMA public;  -- for the "gist_int4_ops" opclass

然后您可以创建一个排除约束:

ALTER TABLE soccer.match ADD EXCLUDE USING gist (
   matchday gist_int4_ops WITH OPERATOR(pg_catalog.=),
   (ARRAY[home_team_id, foreign_team_id]) gist__int_ops WITH OPERATOR(public.&&)
);

基本上,如果matchday s相等且由home_team_idforeign_team_id组成的数组具有共同元素,则会将两行计为“相等”。

答案 2 :(得分:2)

一个团队每个比赛日不能玩多次,所以有一个列出比赛日和球队的表格。结合比赛的数字和HOME或AWAY的指示器,您将获得所需的所有数据。例如:

             Table « soccer.match »
+-----------------------------------------------+
¦      Column        ¦   Type   ¦ Modifiers     ¦
+--------------------+----------+---------------¦
¦ matchday           ¦ integer  ¦ not NULL      ¦
¦ matchnum           ¦ integer  ¦ not NULL      ¦
¦ team_id            ¦ integer  ¦ not NULL      ¦
¦ teamtype           ¦ varchar  ¦ not NULL      ¦
¦ score              ¦ smallint ¦ not NULL      ¦
+-----------------------------------------------+
Check constraints:
    "match_teamtype_check" CHECK (teamtype IN ('HOME','AWAY'))
    "match_score_check" CHECK (score >= 0)
Indexes:
    "match_pkey" PRIMARY KEY, btree (matchday, match_no, team_id, teamtype)
    "match_team_once_per_day" UNIQUE KEY, btree (matchday, team_id)
    "match_two_teams_only" UNIQUE KEY, btree (matchday, matchnum, teamtype)

答案 3 :(得分:1)

如果您有以下表格,则可以在matchdayteam_id上放置唯一约束或多列主键:

team_match表:

┌────────────────────┬──────────┬───────────────┐
│      Column        │   Type   │ Modifiers     │
├────────────────────┼──────────┼───────────────┤
│ matchday           │ integer  │ not NULL      │
│ team_id            │ integer  │ not NULL      │
│ is_home_team       │ integer  │ not NULL      │
│ match_id           │ integer  │ not NULL      │
│ score              │ integer  │ not NULL      │
└────────────────────┴──────────┴───────────────┘

match表:

┌────────────────────┬──────────┬───────────────┐
│      Column        │   Type   │ Modifiers     │
├────────────────────┼──────────┼───────────────┤
│ match_id           │ integer  │ not NULL      │
└────────────────────┴──────────┴───────────────┘

答案 4 :(得分:0)

你可以在这里使用两位数的比较技巧,例如:

create unique index ui on soccer.match (matchday, greatest(home_team_id,foreign_team_id), least(home_team_id,foreign_team_id))

答案 5 :(得分:0)

你的桌子设计看起来很好。但是你是对的,它不能保证每个比赛日一支球队只能打一次。你需要另一张桌子。您可以做的是将此另一个表添加到您现有的设计中,并用触发器填充它。

             Table « soccer.match_team »
+-----------------------------------------------+
¦      Column        ¦   Type   ¦ Modifiers     ¦
+--------------------+----------+---------------¦
¦ matchday           ¦ integer  ¦ not NULL      ¦
¦ team_id            ¦ integer  ¦ not NULL      ¦
+-----------------------------------------------+
Index:
    "match_team_pkey" PRIMARY KEY, btree (matchday, team_id)

现在编写一个触发器,只要写入match记录就会写入两条记录。 (如果您想允许这些内容,您可能还需要为更新和删除编写代码。)