精华内容
下载资源
问答
  • 针对数据库数据质量评价问题,给出了一个属性粒度的质量评价模型,定义了正确性评价指标。分析量化前后属性错误率的基础上,给出了两种错误率之间的关系。还研究了关系代数选择运算键属性条件下的质量传播关系,得出...
  • 该算法是以道路交叉口为研究对象,根据指路标志指引信息与路网拓扑的关系,将指路标志指引信息分成连接性标志和方向性标志两种,定义了基于道路指示等级的方向性标志选择规则,并设计了生成方向性标志的算法模型。...
  • Django 对各种数据库提供很好的支持,...对象关系映射(Object Relational Mapping,简称 ORM )用于实现面向对象编程语言里不同类型系统的数据之间的转换。 ORM 业务逻辑层和数据库层之间充当桥梁的作用。 ORM

    Django 对各种数据库提供了很好的支持,包括:PostgreSQL、MySQL、SQLite、Oracle。

    Django 为这些数据库提供了统一的调用API。 我们可以根据自己业务需求选择不同的数据库。

    MySQL 是 Web 应用中最常用的数据库。

    Django 模型使用自带的 ORM。

    对象关系映射(Object Relational Mapping,简称 ORM )用于实现面向对象编程语言里不同类型系统的数据之间的转换。

    ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。

    ORM 是通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。

    作用:根据对象的类型生成表结构,将对象、列表的操作转换为sql语句,将sql语句查询到的结果转换为对象、列表,极大的减轻了开发人员的工作量,不需要面对因数据库的变更而修改代码。

    ORM 解析过程:

    • 1、ORM 会将 Python 代码转成为 SQL 语句。
    • 2、SQL 语句通过 pymysql 传送到数据库服务端。
    • 3、在数据库中执行 SQL 语句并将结果返回。

    ORM 对应关系表:


    定义模型:参考https://www.runoob.com/django/django-model.html


    由于django的查询方式,不允许使用连续的下划线。

    定义属性时,需要字段类型,字段类型被定义在```django.db.models.fields```目录下,为了方便使用,被导入到```django.db.models```中,定义模型时先导入```from django.db import models```,通过models.Field创建字段类型的对象,赋值给属性。

    注意:对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False


    模型间关系:一对一关系 : OneToOneField、一对多关系 : ForeignKey、

    多对多关系 : ManyToManyField

    关联管理器(对象调用):

    前提:

    • 多对多(双向均有关联管理器)
    • 一对多(只有多的那个类的对象有关联管理器,即反向才有)

    语法格式:

    正向:属性名

    反向:小写表名_set

    一对多关系 : ForeignKey

    class Student(models.Model):

              name = models.CharField()

              grade = ForeignKey(Grade)

    class Grade(models.Model):

              gname = models.CharField()

     

    stu = Student()

    grade = Grade() 

    stu.grade # 正向查询,通过学生查询班级名

    grade.student_set # 反向查询,通过班级名查询学生

    多对多关系 : ManyToManyField

    class Student(models.Model):

              name = models.CharField()

              course = ManyToManyField(Course)

    class Curse(models.Model):

              cname = models.CharField()

     

    stu = Student()

    course = Course() 

    stu.course_set # 正向 查询学生选修的课程

    course.student_set # 反向 查询选修课程的学生名

    表与表之间的关系可分为以下三种:

    • 一对一: 一个人对应一个身份证号码,数据字段设置 unique
    • 一对多: 一个家庭有多个人,一般通过外键来实现。
    • 多对多: 一个学生有多门课程,一个课程有很多学生,一般通过第三个表来实现关联。

    创建模型:

    接下来我们来看下多表多实例:

    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        pub_date = models.DateField()
        publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
        authors = models.ManyToManyField("Author")


    class Publish(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=64)
        email = models.EmailField()


    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.SmallIntegerField()
        au_detail = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE)


    class AuthorDetail(models.Model):
        gender_choices = (
            (0, "女"),
            (1, "男"),
            (2, "保密"),
        )
        gender = models.SmallIntegerField(choices=gender_choices)
        tel = models.CharField(max_length=32)
        addr = models.CharField(max_length=64)
        birthday = models.DateField()

    说明:

    1、EmailField 数据类型是邮箱格式,底层继承 CharField,进行了封装,相当于 MySQL 中的 varchar。

    2、Django1.1 版本不需要联级删除:on_delete=models.CASCADE,Django2.2 需要。

    3、一般不需要设置联级更新.

    4、外键在一对多的多中设置:models.ForeignKey("关联类名", on_delete=models.CASCADE)。

    5、OneToOneField = ForeignKey(...,unique=True)设置一对一。

    6、若有模型类存在外键,创建数据时,要先创建外键关联的模型类的数据,不然创建包含外键的模型类的数据时,外键的关联模型类的数据会找不到。

    表结构:

    书籍表 Book:title 、 price 、 pub_date 、 publish(外键,多对一) authors(多对多)

    出版社表 Publish:name 、 city 、 email

    作者表 Author:name 、 age 、 au_detail(一对一)

    作者详情表 AuthorDetail:gender 、 tel 、 addr 、 birthday

    以下是表格关联说明:


    插入数据:

    在 MySQL 中执行以下 SQL 插入操作:

    insert into app01_publish(name,city,email) values ("华山出版社", "华山", "hs@163.com"), ("明教出版社", "黑木崖", "mj@163.com")

    # 先插入 authordetail 表中多数据

    insert into app01_authordetail(gender,tel,addr,birthday) values (1,13432335433,"华山","1994-5-23"), (1,13943454554,"黑木崖","1961-8-13"), (0,13878934322,"黑木崖","1996-5-20")

    # 再将数据插入 author,这样 author 才能找到 authordetail

    insert into app01_author(name,age,au_detail_id) values ("令狐冲",25,1), ("任我行",58,2), ("任盈盈",23,3)

    ORM - 添加数据

    一对多(外键 ForeignKey)

    方式一: 传对象的形式,返回值的数据类型是对象,书籍对象。

    步骤:

    a. 获取出版社对象

    b. 给书籍的出版社属性 pulish 传出版社对象

    def add_book(request):
        #  获取出版社对象
        pub_obj = models.Publish.objects.filter(pk=1).first()
        #  给书籍的出版社属性publish传出版社对象
        book = models.Book.objects.create(title="菜鸟教程", price=200, pub_date="2010-10-10", publish=pub_obj)
        print(book, type(book))

    方式二: 传对象 id 的形式(由于传过来的数据一般是 id,所以传对象 id 是常用的)。

    一对多中,设置外键属性的类(多的表)中,MySQL 中显示的字段名是:外键属性名_id

    返回值的数据类型是对象,书籍对象。

    步骤:

    a. 获取出版社对象的 id

    b. 给书籍的关联出版社字段 pulish_id 传出版社对象的 id

    def add_book(request):
        #  获取出版社对象
        pub_obj = models.Publish.objects.filter(pk=1).first()
        #  获取出版社对象的id
        pk = pub_obj.pk
        #  给书籍的关联出版社字段 publish_id 传出版社对象的id
        book = models.Book.objects.create(title="冲灵剑法", price=100, pub_date="2004-04-04", publish_id=pk)
        print(book, type(book))

    多对多(ManyToManyField):在第三张关系表中新增数据

    方式一: 传对象形式,无返回值。

    步骤:

    a. 获取作者对象

    b. 获取书籍对象

    c. 给书籍对象的 authors 属性用 add 方法传作者对象

    def add_book(request):
        #  获取作者对象
        chong = models.Author.objects.filter(name="令狐冲").first()
        ying = models.Author.objects.filter(name="任盈盈").first()
        #  获取书籍对象
        book = models.Book.objects.filter(title="菜鸟教程").first()  # 返回查询集中的第一个对象
        #  给书籍对象的 authors 属性用 add 方法传作者对象
        book.authors.add(chong, ying)


    关联管理器(对象调用)

    前提:

    • 多对多(双向均有关联管理器)
    • 一对多(只有多的那个类的对象有关联管理器,即反向才有)

    语法格式:

    正向:属性名
    反向:小写类名加_set

    注意:一对多只能反向

    常用方法:

    add():用于多对多,把指定的模型对象添加到关联对象集(关系表)中。

    注意:add() 在一对多(即外键)中,只能传对象( *QuerySet数据类型),不能传 id(*[id表])。

    *[ ] 的使用:

    # 方式一:传对象

    book_obj = models.Book.objects.get(id=10)
    author_list = models.Author.objects.filter(id__gt=2)  # 查询id大于2作者
    book_obj.authors.add(*author_list)  # 将 id 大于2的作者对象添加到这本书的作者集合中
    # 方式二:传对象 id
    book_obj.authors.add(*[1,3]) # 将 id=1 和 id=3 的作者对象添加到这本书的作者集合中

    反向:小写表名_set

    多(作者Author)对多(书Book:authors = models.ManyToManyField("Author"))

    ying = models.Author.objects.filter(name="任盈盈").first()
    book = models.Book.objects.filter(title="冲灵剑法").first()
    ying.book_set.add(book)


    create():创建一个新的对象,并同时将它添加到关联对象集之中。

    返回新创建的对象。

    pub = models.Publish.objects.filter(name="明教出版社").first()
    wo = models.Author.objects.filter(name="任我行").first()
    book = wo.book_set.create(title="吸星大法", price=300, pub_date="1999-9-19", publish=pub)
    print(book, type(book))


    remove():从关联对象集中移除执行的模型对象。

    对于 ForeignKey 对象,这个方法仅在 null=True(可以为空)时存在,无返回值。

    author_obj =models. Author.objects.get(id=1)
    book_obj = models.Book.objects.get(id=11)
    author_obj.book_set.remove(book_obj)


    clear():从关联对象集中移除一切对象,删除关联,不会删除对象。

    对于 ForeignKey 对象,这个方法仅在 null=True(可以为空)时存在。

    无返回值。

    #  清空独孤九剑关联的所有作者
    book = models.Book.objects.filter(title="菜鸟教程").first()
    book.authors.clear()


    ORM 查询

    基于对象的跨表查询。

    正向:属性名称

    反向:小写类名_set

    一对多

    查询主键为 10 的书籍的出版社所在的城市(正向)。

    book = models.Book.objects.filter(pk=10).first()
    res = book.publish.city
    print(res, type(res))


    查询明教出版社出版的书籍名(反向)。

    反向:对象.小写类名_set(pub.book_set) 可以跳转到关联的表(书籍表)。

    pub.book_set.all():取出书籍表的所有书籍对象,在一个 QuerySet 里,遍历取出一个个书籍对象。

    pub = models.Publish.objects.filter(name="明教出版社").first()
    res = pub.book_set.all()
    for i in res:
        print(i.title)


    一对一

    查询令狐冲的电话(正向)

    正向:对象.属性 (author.au_detail) 可以跳转到关联的表(作者详情表)

    author = models.Author.objects.filter(name="令狐冲").first()
    res = author.au_detail.tel
    print(res, type(res))


    查询所有住址在黑木崖作者的姓名(反向)。

    一对一的反向,用 对象.小写类名 即可,不用加 _set。

    反向:对象.小写类名(addr.author)可以跳转到关联的表(作者表)。

    addr = models.AuthorDetail.objects.filter(addr="黑木崖").first()
    res = addr.author.name
    print(res, type(res))


    多对多

    菜鸟教程所有作者的名字以及手机号(正向)。

    正向:对象.属性(book.authors)可以跳转到关联的表(作者表)。

    作者表里没有作者电话,因此再次通过对象.属性(i.au_detail)跳转到关联的表(作者详情表)。

    book = models.Book.objects.filter(title="菜鸟教程").first()
    res = book.authors.all()
    for i in res:
        print(i.name, i.au_detail.tel)


    查询任我行出过的所有书籍的名字(反向)。

    author = models.Author.objects.filter(name="任我行").first()
    res = author.book_set.all()
    for i in res:
        print(i.title)


    基于双下划线的跨表查询

    正向:属性名称__跨表的属性名称

    反向:小写类名__跨表的属性名称

    一对多

    查询菜鸟出版社出版过的所有书籍的名字与价格。

    res = models.Book.objects.filter(publish__name="菜鸟出版社").values_list("title", "price")


    反向:通过 小写类名__跨表的属性名称(book__title,book__price) 跨表获取数据。

    res = models.Publish.objects.filter(name="菜鸟出版社").values_list("book__title","book__price")


    多对多

    查询任我行出过的所有书籍的名字。

    正向:通过 属性名称__跨表的属性名称(authors__name) 跨表获取数据:

    res = models.Book.objects.filter(authors__name="任我行").values_list("title")

    反向:通过 小写类名__跨表的属性名称(book__title) 跨表获取数据:

    res = models.Author.objects.filter(name="任我行").values_list("book__title")


    一对一

    查询任我行的手机号。

    正向:通过 属性名称__跨表的属性名称(au_detail__tel) 跨表获取数据。

    res = models.Author.objects.filter(name="任我行").values_list("au_detail__tel")


    反向:通过 小写类名__跨表的属性名称(author__name) 跨表获取数据。

    res = models.AuthorDetail.objects.filter(author__name="任我行").values_list("tel")


     

     

    展开全文
  • 根据特征的冗余和冲突关系定义人和策略集;用信息熵和互信息构建支付函数,并计算出模型的支付矩阵;再利用极大化极小原理求解博弈均衡点,从而得到最佳策略组合。使用模型选出的最佳策略进行步态融合,以得到较...
  • 本文主要讲解machine learning中模型选择、评估的方法,重点在于诊断模型欠拟合或过拟合时用到的偏离bias和方差variance的概念,及其与正则化项的关系。 原楼主文中为了解释诊断偏离bias和方差variance的区别,...

    本文转自这里

    本文主要讲解了machine learning中模型选择、评估的方法,重点在于诊断模型欠拟合或过拟合时用到的偏离bias和方差variance的概念,及其与正则化项的关系。

    这部分是machine learning中非常有用的,对于训练、诊断、选择模型非常有帮助。

    原楼主在文中为了解释诊断偏离bias和方差variance的区别,定义并举例说明了二者的概念,深入浅出,值得学习。


    总的来说,同样的正则化参数,使得不同的训练数据训练出不同的模型。那么如果想评估正则化参数的好坏,应该怎么做呢?这就要求:

    第一,这组正则化参数,在不同训练数据下训练出的模型,我们希望这些模型的均值越接近实际模型越好,即bias越小越好;

    第二,这组模型,本身的方差不要太大。也就是不同训练数据训练的模型之间,不要差别太大,即variance越小越好。

    bias:估计的均值模型与实际模型之间的距离

    variance:不同模型与估计的均值模型之间的平均距离



    本栏目(Machine learning)包括单参数的线性回归、多参数的线性回归、Octave Tutorial、Logistic Regression、Regularization、神经网络、机器学习系统设计、SVM(Support Vector Machines 支持向量机)、聚类、降维、异常检测、大规模机器学习等章节。所有内容均来自Standford公开课machine learning中Andrew老师的讲解。(https://class.coursera.org/ml/class/index


    第六讲. 怎样选择机器学习方法——Advice for applying machine learning

    ===============================

    候选机器学习方法

    评价方法假设

    模型选择和训练、验证实验数据

    区别诊断偏离bias和偏差variance

    规则化 和 bias/variance

    Learning Curve:什么时候增加训练数据training set才是有效的?


    ===============================

    候选机器学习方法——Deciding what to try next


    还用房价的prediction举例,假设我们已经实现了用规则化的线性回归方法预测房价:


    但发现该预测应用于一个新的训练数据上时有很大误差(error),这时应采取一些解决方案:

    Get more training examples
    Try smaller sets of features
    Try getting additional features
    Try adding polynomial features (e.g.  x1^2, x2^2, x1x2...)
    Try decreasing λ
    Try increasing λ

    Machine Learning 方法的诊断:

    什么是诊断Dignostic呢?诊断就是能够判断一种学习算法能不能work,并且改善该算法性能的一个测试。

    Diagnostic: A test that you can run to gain insight what is/isn't working with a learning algorithm, and gain guidance as to how best to improve its performance.

    -诊断的效果:Diagnostics can take time to implement, but doing so can be a very good use of your time.





    ===============================

    评价方法假设——Evaluating a hypothesis

    首先呢,我们将所有数据分为两个集合,一个Trainning set和一个Testing set,用Training set得到参数向量,用Testing set进行测试(比如分类)。


    这时,将test set的error分为线性回归linear regression和逻辑回归logistic regression两类:

    -线性回归的error:


    -逻辑回归的error:




    ===============================

    模型选择和训练、验证实验数据


    面对模型选择问题,如何才能得到一个just fit的模型而不会导致underfit 或者overfit呢?我们引入一类数据集,叫做cross validation set,即交叉验证数据集。将所有数据按<6,2,2>分为training set , cross validation set , testing set三类,如下图所示:


    其error计算公式如下,其实三类计算方法大同小异,相同的公式只是换了数据及而已:



    进行模型选择的方法其实很简单,对应下图大家来看:

    -首先,建立d个model 假设(图中有10个,d表示其id),分别在training set 上求使其training error最小的θ向量,那么得到d个θ

    -然后,对这d个model假设,带入θ,在cross validation set上计算J(cv),即cv set error最小的一个model 作为 hypothesis,如下图中J(cv)在第4组中最小,便取d=4的假设。

    PS: 其实d表示dimension,也就是维度,表示该hypothesis的最大polynomial项是d维的。

    PS': 一般地,J(cv)是大于等于J(train)的


    ===============================

    区别诊断偏离bias和偏差variance

    前面的课程中我们曾讲过相同数据不同回归情况:




    这一节中,我们给大家区分两个概念:bias vs. variance

    如下图所示为error随不同dimensionmodel变化图,可以想见,随d上升是一个由underfit到overfit的过程,这个过程中,training set的error逐渐下降,而cv set的error先降后升。




    这里就产生了bias和variance的概念:

    bias:J(train)大,J(cv)大,J(train)≈J(cv),bias产生于d小,underfit阶段;

    variance:J(train)小,J(cv)大,J(train)<<J(cv),variance产生于d大,overfit阶段;

    如下图所示:



    来来,做道题:




    -------------------------------------------------------------


    好,有了初步概念,现在我们来看bias和variance的由来及具体定义:

    给定数据及D(比如一个点集吧),对于这些数据集上的点我们可以计算每个index下点的平均值(即期望)t(x) = E(y|x),则我们有mean square error:


    MSE = 1/n * Σ(f(x)-t(x))^2



    MSE(mean square error) = Bias2 + Variance +noise



    定义上是这么讲的:

    Variance: measures the extent to which the solutions for individual data sets vary around their average, hence this measures the extent to which the function f(x) is sensitive to theparticular choice of data set.

    Bias: represents the extent to which the average prediction over all data sets differs from the desired regression function.

    Our goal is to minimize the expected loss, which we havedecomposed into the sum of a (squared) bias, a variance, and a constant noiseterm. As we shall see, there is a trade-off between bias and variance, with very flexible models(overfit) having low bias and high variance, and relatively rigid models(underfit) having high bias and low variance



    总结一下:

    variance:估计本身的方差。

    bias:估计的期望和样本数据样本希望得到的回归函数之间的差别。


    具体来讲,我有一个统计量D(比如统计某大学研一学生身高在[0.5-1],[1,1.1],[1.1,1.2]……[1.9,2]之间的人数),这样可以形成一些离散点。然后呢,本校研一有20个班,每个班就都可以拟合成一条估计曲线f(x),这20条曲线呢,有一个平均值,也就是估计期望(均值)曲线E(f(x,D))。


    variance是指,这20条估计曲线与最后估计期望(均值)之间的距离,也就是估计曲线本身的方差,是不可能为0的。

    bias是指,20条估计曲线的均值与实际最佳拟合情况之间的距离。


    这样一来呢,对于regularization项中的λ,


    λ小 , d大 -> overfit(flexible) -> 

    对于不同的训练数据集(不同班级的数据)的拟合结果抖动很大 -> variance大 

    bias是估计均值与实际值期望的偏差 -> bias小

    下图中,左图为拟合的20条曲线;右图红线为20条曲线的期望,绿色为实际数据期望所得的拟合曲线。




    λ大 , d小 -> underfit(stable) -> 

    对于不同的训练数据集(不同班级的数据)的拟合结果抖动较小 -> variance小

    bias是估计均值与实际值期望的偏差 ,不能很好地进行回归-> bias大

    下图中,左图为拟合的20条曲线;右图红线为20条曲线的期望,绿色为实际数据期望所得的拟合曲线。




    下图所示为λ与bias, variance, error之间的关系:




    我们希望的数据的variance和bias都不要大:



    那么着就是一个variance和bias之间的tradeoff 了~







    ===============================

    规则化 和 bias/variance


    上面一节中讲了bias和variance的诞生,那么这一节中偶们就将他们应用于regularization中。

    大家还记的什么是regularization么?regularization就是为了防止overfit而在cost function中引入的一个分量。

    还不清楚?看下图吧,regularization项就是cost function J(θ)中的最后一项,其中λ太大导致underfit,λ太小导致overfit……




    将λ从0,0.01,一直往上每次乘以2,那么到10.24总共可以试12次λ。

    这12个λ会得到12个model的 cost function,每个对应有J(θ)和 Jcv(θ).

    和模型选择的方法相同,首先选出每个cost function下令J(θ)最小的θ,然后取出令Jcv(θ)最小的一组定为最终的λ



    来来,看看你做的对不:



    图画出来就是这个样子滴:



    λ太小导致overfit,产生variance,J(train)<<J(cv)

    λ太大导致underfit,产生bias,J(train) ≈ J(cv)

    能明白我的意思么?



    ===============================

    Learning Curve:什么时候增加训练数据training set才是有效的?



    这一小节想要讲讲训练数据个数m和error之间的关系。从上面这幅图中我们可知(不知的话用极限思维想想),训练数据越少(如果只有一个),J(train)越小,J(cv)越大;m越大,J(train)越大(因为越难perfectly拟合),J(cv)越小(因为越精确),懂我的意思吧?


    那么我们分别就High Bias 和 High Variance来看看增加training set个数,即m,是否有意义?


    Underfit 的 High bias: 增加m无济于事!



    Overfit的 High Variance: 增加m使得J(train)和J(cv)之间gap减小,有助于performance提高!



    来来,做道题:



    由图中可见,增加训练数据的个数对于过拟合是有用的,对于underfit是徒劳

    下面总结一下,重温最初的解决方案列表:




    针对underfit和overfit,分别是什么情况呢?见下图:




    这章非常有用,讲了选择最佳拟合model的问题,是machine learning的常见问题,希望能对大家选择ml 模型有所帮助。



    展开全文
  • 关系数据库是指基于关系模型的数据库。关系模型由关系数据结构、...关系模型中定义了三种完整性约束:实体完整性、参照完整性以及用户定义完整性。 SQL是一种面向集合的编程语言,对于 SQL 而言,一切都是关系(表)。

    《SQL 从入门到精通》专栏目录


    在上一篇中,我们回顾了数据库领域以及 SQL 的最新发展趋势。

    本篇我们将会介绍 SQL 的基本特性以及最重要的一个编程思想:一切都是关系。让我们先来回顾一下关系数据库的几个基本概念。

    关系数据库

    关系数据库(Relational database)是指基于关系模型的数据库。关系模型由关系数据结构、关系操作集合、关系完整性约束三部分组成。

    数据结构

    在关系模型中,用于存储数据的逻辑结构称为关系(Relation);对于使用者而言,关系就是二维表(Table)。

    以下是一个员工信息表,它和 Excel 表格非常类似,由行(Row)和列(Column)组成。

    avatar

    在不同的场景下,大家可能会听到关于同一个概念的不同说法。在此,我们列出了关系数据库中的一些常见概念:

    • 关系,也称为,用于表示现实世界中的实体(Entity)或者实体之间的联系(Relationship)。举例来说,一个公司的员工、部门和职位都是实体,分别对应员工信息表、部门信息表和职位信息表;销售的产品和订单都是实体,同时它们之间存在联系,对应订单明细表。
    • ,也称为记录(Record),代表了关系中的单个实体。上图中工号为 4 的数据行存储了“诸葛亮”的相关信息。关系(表)可以看作是由行组成的集合。
    • ,也称为字段(Field),表示实体的某个属性。上图中的第二列包含了员工的姓名。表中的每个列都有一个对应的数据类型,常见的数据类型包括字符类型、数字类型、日期时间类型等。

    有了关系结构之后,就需要定义基于关系的数据操作。

    操作集合

    常见的数据操作包括增加(Create)、查询(Retrieve)、更新(Update)以及删除(Delete),或者统称为增删改查(CRUD)。

    其中,使用最多、也最复杂的操作就是查询,具体来说包括选择(Selection)、投影(Projection)、并集(Union)、交集(Intersection)、差集(exception)以及笛卡儿积(Cartesian product)等。我们将会介绍如何使用 SQL 语句完成以上各种数据操作。

    为了维护数据的完整性或者满足业务需求,关系模型还定义了完整性约束。

    完整性约束

    关系模型中定义了三种完整性约束:实体完整性参照完整性以及用户定义完整性

    • 实体完整性是指表的主键字段不能为空。现实中的每个实体都具有唯一性,比如每个人都有唯一的身份证号;在关系数据库中,这种唯一标识每一行数据的字段称为主键(Primary Key),主键字段不能为空。每个表可以有且只能有一个主键。
    • 参照完整性是指外键参照的完整性。外键(Foreign Key)代表了两个表之间的关联关系,比如员工属于某个部门;因此员工表中存在部门编号字段,引用了部门表中的部门编号字段。对于外键引用,被引用的数据必须存在,员工不可能属于一个不存在的部门;删除某个部门之前,也需要对部门中的员工进行相应的处理。
    • 用户定义完整性是指基于业务需要自定义的约束。非空约束(NOT NULL)确保了相应的字段不会出现空值,例如员工一定要有姓名;唯一约束(UNIQUE)用于确保字段中的值不会重复,每个员工的电子邮箱必须唯一;检查约束(CHECK)可以定义更多的业务规则。例如,薪水必须大于 0 ,字符必须大写等;默认值(DEFAULT)用于向字段中插入默认的数据。

    本专栏涉及的 4 种数据库对于这些完整性约束的支持情况如下:

    数据库 非空约束 唯一约束 主键约束 外键约束 检查约束 默认值
    Oracle 支持 支持 支持 支持 支持 支持
    MySQL 支持 支持 支持 支持* 支持* 支持
    SQL Server 支持 支持 支持 支持 支持 支持
    PostgreSQL 支持 支持 支持 支持 支持 支持

    * MySQL 中只有 InnoDB 存储引擎支持外键约束;MySQL 8.0.16 增加了对检查约束的支持。

    存储引擎(Storage Engine)是 MySQL 中用于管理、访问和修改物理数据的组件,不同的存储引擎提供了不同的功能和特性。从 MySQL 5.5 开始默认使用 InnoDB 存储引擎,支持事务处理(ACID)、行级锁定、故障恢复、多版本并发控制(MVCC)以及外键约束等。

    关系数据库使用 SQL 作为访问和操作数据的标准语言。现在,让我们来直观感受一下 SQL 语句的特点。

    SQL:一种面向集合的编程语言

    本节会出现几个示例,我们还没有正式开始学习 SQL 语句,可以暂时不必理会细节。

    语法特性

    SQL 是一种声明性的编程语言,语法接近于自然语言(英语)。通过几个简单的英文单词,例如 SELECT、INSERT、UPDATE、CREATE、DROP 等,完成大部分的数据库操作。以下是一个简单的查询示例:

    SELECT emp_id, emp_name, salary
      FROM employee
     WHERE salary > 10000
     ORDER BY emp_id;
    

    即使没有学过 SQL 语句,但只要知道几个单词的意思,就能明白该语句的作用。它查询员工表(employee)中月薪(salary)大于 10000 的员工,返回工号、姓名以及月薪,并且按照工号进行排序。可以看出,SQL 语句非常简单直观。

    以上查询中的 SELECT、FROM 等称为关键字(也称为子句),一般大写;表名、列名等内容一般小写;分号(;)表示语句的结束。SQL 语句不区分大小写,但是遵循一定的规则可以让代码更容易阅读。

    SQL 是一种声明式的语言,声明式语言的主要思想是告诉计算机想要什么结果(what),但不指定具体怎么做。这类语言还包括 HTML、正则表达式以及函数式编程等。

    面向集合

    对于 SQL 语句而言,它所操作的对象是一个集合(表),操作的结果也是一个集合(表)。例如以下查询:

    SELECT emp_id, emp_name, salary
      FROM employee;
    

    其中 employee 是一个表,它是该语句查询的对象;同时,查询的结果也是一个表。所以,我们可以继续扩展该查询:

    SELECT emp_id, emp_name, salary
      FROM (
           SELECT emp_id, emp_name, salary
             FROM employee
           ) dt;
    

    我们将括号中的查询结果(取名为 dt)作为输入值,传递给了外面的查询;最终整个语句的结果仍然是一个表。在第 17 篇中,我们将会介绍这种嵌套在其他语句中的查询就是子查询(Subquery)。

    SQL 中的查询可以完成各种数据操作,例如过滤转换、分组汇总、排序显示等;但是它们本质上都是针对表的操作,结果也是表。

    avatar

    不仅仅是查询语句,SQL 中的插入、更新和删除都以集合为操作对象。我们再看一个插入数据的示例:

    CREATE TABLE t(id INTEGER);
    
    -- 适用于 MySQL、SQL Server 以及 PostgreSQL
    INSERT INTO t(id)
    VALUES (1), (2), (3);
    

    我们首先使用 CREATE TABLE 语句创建了一个表,然后使用 INSERT INTO 语句插入数据。在执行插入操作之前,会在内存中创建一个包含 3 条数据的临时集合(表),然后将该集合插入目标表中。由于我们通常一次插入一条数据,以为是按照数据行进行插入;实际上,一条数据也是一个集合,只不过它只有一个元素而已。

    Oracle 不支持以上插入多行数据的语法,可以使用下面的插入语句:

    -- 适用于 Oracle
    INSERT INTO t(id)
    SELECT 1 FROM DUAL
     UNION ALL
    SELECT 2 FROM DUAL
     UNION ALL
    SELECT 3 FROM DUAL;
    

    UNION ALL 是 SQL 中的并集运算,用于将两个集合组成一个更大的集合。此外,SQL 还支持交集运算(INTERSECT)、差集运算(EXCEPT)以及笛卡儿积(Cartesian product)。我们会在第 18 篇中介绍这些内容,它们也都是以集合为对象的操作。

    我们已经介绍了 SQL 语言的声明性和面向集合的编程思想。在正式学习编写 SQL 语句之前,还需要进行一些准备工作,主要就是安装示例数据库。

    示例数据库

    在本专栏的学习过程中,我们主要使用一个虚构的公司数据模型。该示例数据库包含 3 个表:员工表(employee)、部门表(department)和职位表(job)。以下是它们的结构图,也称为实体-关系图(Entity-Relational Diagram):

    avatar

    • 部门表(department),包含部门编号(deptid)和部门名称(deptname)字段,主键为部门编号。该表共计 6 条数据。
    • 职位表(job),包含职位编号(jobid)和职位名称(jobtitle)字段,主键为职位编号。该表共计 10 条数据。
    • 员工表(employee),包含员工编号(empid)和员工姓名(empname)等字段,主键为员工编号,部门编号(deptid)字段是引用部门表的外键,职位编号(jobid)字段是引用职位表的外键,经理编号(manager)字段是引用员工表自身的外键。该表共计 25 条数据。

    我们在 GitHub 上为大家提供了示例表和初始数据的创建脚本和安装说明,支持 Oracle、MySQL、SQL Server 以及 PostgreSQL。点击链接进行下载。

    运行这些脚本之前,需要先安装数据库软件。网络上有很多这类安装教程可以参考;如果无法安装数据库,也可以使用这个免费的在线 SQL 开发环境:http://sqlfiddle.com,它提供了各种常见的关系数据库服务。下图是使用 MySQL 运行示例脚本的结果:

    avatar

    选择数据库之后,将创建表和插入数据的脚本复制到左边窗口,点击“Build Schema”进行初始化;点击“Browser”可以查看表结构;在右侧窗口输入 SQL 语句,点击“Run SQL”运行并查看结果。该工具提供的数据库不是最新版本,但是可以运行大部分的示例。

    本专栏中所有的示例都在以下数据库版本中进行了验证:

    • Oracle database 18c
    • MySQL 8.0
    • SQL Server 2017
    • PostgreSQL 12

    我们使用 DBeaver 开发工具编写所有的 SQL 语句,该工具的安装和使用可以参考我的博客文章。当然,你也可以使用自己喜欢的开发工具。

    小结

    关系模型中定义了一个简单的数据结构,即关系(表),用于存储数据。SQL 是关系数据库的通用标准语言,它使用接近于自然语言(英语)的语法,通过声明的方式执行数据定义、数据操作、访问控制等。对于 SQL 而言,一切都是关系(表)。

    参考文献

    • [美] Abraham Silberschatz,Henry F.Korth,S.Sudarshan 著,杨冬青,李红燕,唐世渭 译 ,《数据库系统概念(原书第6版)》,机械工业出版社,2012
    展开全文
  • 目录 简介 环境及表说明 数据库连接 一对多表模型定义 不固定模型结构的表数据获取 ...实施过程中选择了Gorm来进行数据库操作,虽然这个库明面上是有一个较为完善的文档,但实际使用过程中坑...

     

    目录

    1.简介

    2.环境及表说明

    3.数据库连接

    4.一对多表模型定义

    5.不固定模型结构的表数据获取

    6.小结

    参考资料:


    1. 简介

    在一个实际工程中需要采集一些对象的属性信息,该工程涉及多个项目,每一个项目所采集的对象属性字段各不相同且无法提前预知,需要根据项目动态设计的字段生成对应项目的采集数据表。在服务端程序开发时,团队选择了Golang,其实自己也没有用过Go语言,也就正好借着这样的机会学习学习。实施过程中选择了Gorm来进行数据库操作,虽然这个库明面上是有一个较为完善的文档,但实际使用过程中坑还真不少,本文主要介绍Gorm进行数据操作完成前叙问题的主要过程,重点解决两个关键问题:Gorm中一对多表操作以及无固定数据库模型的操作方法。

    2. 环境及表说明

    Golang版本为:1.14.3 windows版

    Gorm版本为V1.9.14

    数据库为:PostgreSQL 10

    实验中的表为:

    如表示意图中所示,本问题中涉及三张表,记录项目基础信息的ProjectInfo表,记录各个项目需要采集属性字段的PropsToCollect表以及根据项目所需采集字段动态创建的XXXData表。三个表中ProjectInfo表中的ProjectName和PropsToCollect表中的ProjectNameRef为相互关联的外键。

    3. 数据库连接

    dbConnectStr:=fmt.Sprintf("host=%s port=%d user=%s dbname=%s password=%s sslmode=disable", pgDBInfo.Host, pgDBInfo.Port, pgDBInfo.User, pgDBInfo.Name, pgDBInfo.Password)
    DB, err = gorm.Open("postgres", dbConnectStr)
    

    数据库连接过程中需要提供数据库IP、端口、用户名、数据库名、用户密码几个参数。

    4. 一对多表模型定义

    // PropsToCollect 用于存储工程需要采集的字段信息
    type PropsToCollect struct {
       ProjectNameRef string //作为外键 如果在主表中没有指定associateForeignkey 那么必须为uint类型 不然就使用和associateForeignkey一致的字段类型
       Name           string `gorm:"column:name" json:"name"`
       Label          string `gorm:"column:label" json:"label"`
       DefaultValue   string `gorm:"column:defualtvalue" json:"defaultValue"`
    }
    
    // ProjectInfo 用于存储工程信息
    type ProjectInfo struct { //这里不要用gorm.model 不然会自动加一个id 主键 导致association时出错 primary_key nil
       ProjectName     string           `gorm:"column:projectname;primary_key;index;unique;not null" json:"projectName"`
       PropsToCollects []PropsToCollect `gorm:"ForeignKey:ProjectNameRef;AssociationForeignKey:ProjectName" json:"PropsToCollects"` //这种多个元素的字段 需要把字段名字该为xxxs因为gorm会自动把表名加上s
    }
    

    根据表设计定义表模型后,表会根据模型的关联关系被关联创建,数据的录入也会默认联动(删除好像不行)。该过程中需要注意几点:

    1. 一对多的模型写法:主表通过一个字段来记录一条记录中包含的多个关联记录,该字段一般为副表模型数组,如:ProjectInfo结构体中的PropsToCollects字段;且此处需要注意,如果没有对副表模型的表名特殊处理,此处的副表字段数组应该为XXXXs,因为Gorm默认会给表名加s,如果此处字段没有s结尾,两表关联不上。
    2. 关联键映射的写法:主表中的关联键需要标记ForeignKey和AssociationForeignKey,ForeignKey为关联表中的关联键,AssociationForeignKey为主表中的关联键,如本项目中,主表模型中的ForeignKey为ProjectnameRef,AssociationForeignKey为本模型中的ProjectName,注意这里的外键其实是逻辑外键,或者本文叫的关联键
    3. 不要在主表中使用Gorm中默认的模型参数。Gorm的表模型有个gorm.model可以自动定义自增长id,插入,修改以及删除字段,且该id为主键,如果在主表中引入了gorm的默认模型参数,那数据在入库的时候会报“association primary_key nil”的错

    5. 不固定模型结构的表数据获取

    本文不介绍不固定模型结构的表创建,因为……emm,我是通过Gorm执行原生SQL来创建的,非固定字段的表创建其实还比较容易,但是个人觉得获取未知字段的表数据还比较值得和大家分享下。

    在本项目中因为知道某项目的数据记录表中的字段数和名字,且各个字段类型都为string所以能较好的设计读取的方法,这里我不再描述如何获取所有字段数的,直接贴如何获取数据的代码:

    queryStr := "SELECT * from " + extrudeTable + " WHERE entityid = ?"
    
    rows, err := db.DB.Raw(queryStr, onePolygon.EntityID).Rows()
    if err != nil {
       …
    }
    
    var dest []interface{}
    dest = append(dest, new(float32), new(float32)) //其他类型示例
    for i := 0; i < len(propsToCollectInProject); i++ {
        dest = append(dest, new(string))
    }
    for rows.Next() {  
       rows.Scan(dest...) //获取数据方法 *dest[i].(*string)
    }
    

    如代码所示,首先我用了Gorm来执行原生SQL进行查询,查询后的数据因为不知道具体的结构,所以采用interface{}数组来表达,每一个元素根据预知的类型进行初始化,然后从获取的原始数据中Scan到interface{}数组中,扫描出来的数据可以通过*dest[i].(*string)获取。

    6. 小结

    本文重点介绍了Gorm使用过程中一对多表的操作方法,以及在未知表结构的情况下如何从表查询结果中获取数据,该获取方法其实也适用于原生的sql包的查询结果。整体而言,在使用Gorm的过程中的感受是,该库的确能一定程度缓解一些固定范式表的操作,但是坑还是不少,且灵活性不足,所以个人在使用过程中还是将原生的SQL结合起来的;另外的一个问题是,该库写出来的代码和SQL的语句顺序不一样,长期写SQL的人可能觉得这语序怪怪的。

    参考资料:

    [1] https://eli.thegreenplace.net/2019/to-orm-or-not-to-orm/ 关于是否使用orm的思考

    [2] https://gorm.io/docs/ grom官方文档

    展开全文
  • 数据库设计和E-R模型

    千次阅读 2018-07-30 21:17:47
    实现数据模型通常是关系数据模型,该阶段通常包括将以实体-联系模型定义的概念模式映射到关系模式 物理设计阶段 指明数据库的物理特征,包括文件组织格式和索引结构的选择 设计选择 设计数据库模式的时候...
  • django模型详解(四)

    2018-06-17 15:26:26
    1 概述 (1)概述 : Django对各种... 一个模型类对应数据库的一张表,在模型中定义属性,对应模型对照表的字段配置数据库 (3)django开发流程: 1 配置数据库 2 定义模型类 : 一个模型类一张数据表 3 生成迁移文件 ...
  • 以2005-2007年中国工业企业数据库的企业为研究对象,定义了城镇(村镇,街道)规模的邻居企业。 本文选择融资效率,企业规模,企业技术创新作为衡量邻居企业“异质性”的指标,并考察它们与企业自身是否有显着...
  • - 选择数据模型,采用所选数据模型的概念将这些需求转化为数据库的概念模式 此概念设计阶段所产生的模式提供了一个对企业的详细综述 概念模式定义了数据库表示的实体,实体的属性,实体间的联系,实体和联系上的...
  • Web应用普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了表示的实体的数据...
  • 2021-02-19 数据结构

    2021-02-20 05:37:00
    **抽象数据类型(ADT)**的含义是指一个数学模型以及定义在此数学模型上的一组操作。即把数据类型和数据类型上的运算捆一起,进行封装。引入抽象数据类型的目的是把数据类型的表示和数据类型上运算的实现与这些数据...
  • 4.1 流数据模型 4.1.1 一个数据流管理系统 4.1.2 流数据源的例子 4.1.3 流查询 4.1.4 流处理的若干问题 4.2 流当中的数据抽样 4.2.1 一个富于启发性的例子 4.2.2 代表性样本的获取 4.2.3 一般的抽样问题 ...
  • 4.1 流数据模型 4.1.1 一个数据流管理系统 4.1.2 流数据源的例子 4.1.3 流查询 4.1.4 流处理的若干问题 4.2 流当中的数据抽样 4.2.1 一个富于启发性的例子 4.2.2 代表性样本的获取 4.2.3 一般的抽样问题 ...
  • C#数据结构

    2013-12-10 11:49:54
    是为了讨论问题的方便,与数据在计算机的具体存储没有关系。然而,我们讨 论数据结构的目的是为了计算机实现对它的操作,因此还需要研究计算机 如何表示和存储数据结构,即数据的物理结构(Physical ...
  • 数据运营思维导图

    2018-04-26 14:24:22
    产品植入多段代码追踪用户连续行为,建立用户模型来具体化用户使用产品的操作行为 高级 研发团队合作,通过数据埋点还原出用户画像及用户行为 常用数据分析工具 友盟、Talkingdata 友盟的页面访问分析...
  • 4.1 数据库的设置Web应用普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了...
  • 2019数据运营思维导图

    2019-03-29 21:34:09
    数据来源 数据埋点 初级 追踪每次用户的行为,统计关键流程的使用程度 中级 产品植入多段代码追踪用户连续行为,建立用户模型来具体化用户使用产品的操作行为 高级 研发团队合作,通过数据埋点还原出用户...
  • 中间表一般就是包含两个模型的外键字段就可以,并且让他们两个来作为一个“复合主键”3、两个需要做多对多的模型中随便选择一个模型,定义一个relationship属性,来绑定三者之间的关系使用relationship的...
  • JAVA_API1.6文档(中文)

    万次下载 热门讨论 2010-04-12 13:31:34
    定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务提供者类。 java.nio.charset 定义用来字节和 Unicode 字符之间转换的 charset、解码器和编码器。 ...
  • 特征选择

    千次阅读 2016-04-22 20:22:32
    特征提取、特征选择是特征工程的两个重要重要问题,坊间常说:数据和特征决定机器学习的上限,而模型和算法只是逼近这个上限而已。 相关链接: 特征选择 1.简介 下面介绍特征选择方法之前,先进行一个简单...
  • 10.数据模型是数据库系统的核心和基础 1. 说明视图与基本表的区别和联系。 答:视图是从一个或几个基本表导出的表,它与基本表不同,它是一个虚表,(2分)数据库只存放视图的定义,而不存放视图对应的数据,...
  • 如何生成EDM的元数据文件csdl,msl,ssdl

    千次阅读 2010-02-28 13:46:00
    一个EDM模型上,点击右键,属性中选择“元数据项目处理”=〉“复制到输出目录” 这几个文件的分工大致如下 CSDL: 定义了业务实体 MSL:定义了业务实体与数据库对象之间的映射 SSDL:定义了在数据库内部的一些属性...
  • Django的models

    2018-08-20 18:58:41
    Django对各种数据库提供很好的支持,Django为这些数据库提供...一个模型类都数据库对应一张数据表。 3. 生成迁移文件,执行迁移生成数据表 4. 使用模型类进行增删改查(crud)操作 ORM 对象—关系—...
  • 1.2 关系数据结构 6 1.2.1 数据库和模式 6 1.2.2 表、行和列 7 1.2.3 信息原则 10 1.2.4 域 12 1.2.5 元数据 13 1.2.6 键 13 1.2.7 未显式赋值的项(NULL) 18 1.3 实体之间的关系 20 1.3.1 二元关系 21 ...
  • Web应用普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了表示的实体的数据...
  • 本书对Excel技术论坛上上百万个提问的分析与提炼的基础上,汇集用户使用Excel进行数据处理与分析过程最常见的需求,通过270多个实例的演示与讲解,将Excel高手的过人技巧手把手教给读者,并帮助读者发挥...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 230
精华内容 92
关键字:

在关系数据模型中定义了选择