sql - 是否有任何经验法则可以根据人类可读的描述构造 SQL 查询?

标签 sql database relational-database heuristics human-readable

每当我们面前有任何关于查询的描述时,我们都会尝试应用启发式和头脑 Storm 来构建查询。

是否有任何系统的分步或数学方法可以根据给定的人类可读描述构造 SQL 查询?

例如,如何确定 SQL 查询是否需要连接而不是子查询,是否需要 group by,是否需要 IN 子句等。

例如,任何学习过数字电子学的人都会知道卡诺图或奎因麦克劳斯基方法等方法。这些是一些简化数字逻辑的系统方法。

是否有类似这样的方法来手动分析sql查询以避免每次都进行头脑 Storm ?

最佳答案

Is there any systematic step-by-step or mathematical way to construct SQL query from a given human-readable description?



就在这里。

事实证明,自然语言表达式和逻辑表达式以及关系代数表达式和 SQL 表达式(后两者的混合)以一种相当直接的方式对应。 (接下来是没有重复的行和没有空值。)

每个表(基本或查询结果)都有一个关联的谓词——一个由列名参数化的自然语言填充(命名)空白语句模板。

[liker] likes [liked]

一个表包含每一行,这些行使用行的列值来填充(命名的)空格,构成一个真命题,即命题。这是一个包含该谓词及其行命题的表格:

liker  | liked
--------------
Bob    | Dex    /* Bob likes Dex */
Bob    | Alice  /* Bob likes Alice */
Alice  | Carol  /* Alice likes Carol */

用表中一行的值填充谓词的每个命题都是真的。用不在表中的行中的值填充谓词的每个命题都是假的。这张表是这样写的:

/*
    Alice likes Carol
AND NOT Alice likes Alice
AND NOT Alice likes Bob
AND NOT Alice likes Dex
AND NOT Alice likes Ed
...
AND Bob likes Alice
AND Bob likes Dex
AND NOT Bob likes Bob
AND NOT Bob likes Carol
AND NOT Bob likes Ed
...
AND NOT Carol likes Alice
...
AND NOT Dex likes Alice
...
AND NOT Ed likes Alice
...
*/   

DBA 为每个基表提供谓词。表声明的 SQL 语法很像给定谓词的自然语言版本的传统逻辑简写。这是一个基表的声明来保存我们的值:

/* (person, liked) rows where [liker] likes [liked] */
/* (person, liked) rows where Likes(liker, liked) */
CREATE TABLE Likes (
    liker ...,
    liked ...
);

SQL 查询(子)表达式将参数表值转换为新表值,该值包含根据新谓词生成真语句的行。新的表谓词可以根据(子)表达式的关系/表运算符用参数表谓词来表达。查询是一个 SQL 表达式,其谓词是我们想要的行表的谓词。

当我们给出一个表 &(可能是隐式的)别名时 A要加入,该运算符作用于一个值和谓词,就像表的一样,但列重命名为 C,...A.C,... .然后
  • R , S & R CROSS JOIN Sthe predicate of R AND the predicate of S 所在的行
  • R INNER JOIN S ON condition是行,其中 the predicate of R AND the predicate of S AND condition
  • R LEFT JOIN S ON condition是行,其中(对于仅 S 列 S1,...)

        the predicate of R AND the predicate of S AND condition
    OR
            the predicate of R
        AND NOT FOR SOME values for S1,... [the predicate of S AND condition]
        AND S1 IS NULL AND ...
    
  • R WHERE condition是行,其中 the predicate of R AND condition
  • SELECT DISTINCT A.C AS D,... FROM R (可能带有隐式 A. 和/或隐式 AS D )是其中的行
  • FOR SOME values for A.*,... [A.C=D AND ... AND the predicate of R] (这可以不那么紧凑,但看起来更像 SQL。)
  • 如果没有删除的列,the predicate of RA.C,...替换为 D,...
  • 如果有删除的列,FOR SOME values for删除的列 [ the predicate of RA.C,...替换为 D,... ]
  • (X,...) IN (R)方法
  • the predicate of R带列C,...替换为 X,...
  • (X,...) IN R

  • 示例: (person, liked) 行的自然语言,其中 [person] 是 Bob 并且 Bob 喜欢喜欢 [liked] 但不喜欢 Ed 的人:

    /* (person, liked) rows where
    FOR SOME value for x,
            [person] likes [x]
        and [x] likes [liked]
        and [person] = 'Bob'
        and not [x] likes 'Ed'
    */
    

    使用速记谓词重写:

    /* (person, liked) rows where
    FOR SOME value for x,
            Likes(person, x)
        AND Likes(x, liked)
        AND person = 'Bob'
        AND NOT Likes(x, 'Ed')
    */
    

    仅使用基表和别名表的速记谓词重写:

    /* (person, liked) rows where
    FOR SOME values for l1.*, l2.*,
            person = l1.liker AND liked = l2.liked
        AND Likes(l1.liker, l1.liked)
        AND Likes(l2.liker, l2.liked)
        AND l1.liked = l2.liker
        AND person = 'Bob'
        AND NOT (l1.liked, 'Ed') IN Likes
    */
    

    用 SQL 重写:

    SELECT DISTINCT l1.liker AS person, l2.liked AS liked
        /* (l1.liker, l1.liked, l2.liker, l2.liked) rows where
            Likes(l1.liker, l1.liked)
        AND Likes(l2.liker, l2.liked)
        AND l1.liked = l2.liker
        AND l1.liker = 'Bob'
        AND NOT (l1.liked, 'Ed') IN Likes
        */
    FROM Likes l1
    INNER JOIN Likes l2
    ON l1.liked = l2.liker
    WHERE l1.liker = 'Bob'
    AND NOT (l1.liked, 'Ed') IN (SELECT * FROM Likes)
    

    相似地,
  • R UNION CORRESPONDING Sthe predicate of R OR the predicate of R 所在的行
  • R UNION Sthe predicate of R OR the predicate we get by replacing the columns of S by the columns of R in the predicate of R 所在的行
  • VALUES (X,...), ...带列C,...C = X AND ... OR ... 所在的行

  • 例子:

    /* (person) rows where
        FOR SOME value for liked, Likes(person, liked)
    OR  person = 'Bob'
    */
    
        SELECT liker AS person
        FROM Likes
    UNION
        VALUES ('Bob')
    

    因此,如果我们根据给定的基表自然语言语句模板表达我们想要的行,这些行使行为真或为假(返回或不返回),那么我们可以转换为 SQL 查询,这些查询是逻辑简写和运算符和/或表名的嵌套& 运营商。然后 DBMS 可以完全转换为表来计算使我们的谓词为真的行。

    How to get matching data from another SQL table for two different columns: Inner Join and/or Union?将其重新应用于 SQL。 (另一个自连接。)
    Relational algebra for banking scenario有关自然语言短语的更多信息。 (在关系代数上下文中。)
    Null in Relational Algebra关系查询的另一种演示。

    关于sql - 是否有任何经验法则可以根据人类可读的描述构造 SQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33947260/

    相关文章:

    mysql - 在 SQL 中返回记录 "only first,"和 "all but first"

    mysql - 连接 4 个 SQL 表,3 个源 1 'container'

    mysql - 未使用数据库索引导致查询缓慢

    SQL 建模/查询问题

    mysql - 在每个数据库上创建表

    database - X-Y Fast Trie 在实际应用中的应用

    mysql - 连接同一个表中的两个外键引用相同的主键

    mysql - 我的数据库模型的有效性

    oracle - 在没有不可读的动态 SQL 的情况下使用 Oracle 数据库链接

    c# - SQL - 仅当记录不存在时才插入