大发时时彩官网_网络大发时时彩平台_网络大发时时彩网站 - 大发时时彩官网,网络大发时时彩平台,网络大发时时彩网站是知名的中文新闻门户网站,大发时时彩官网,网络大发时时彩平台,网络大发时时彩网站也是全球互联网中文新闻资讯最重要的原创内容供应商之一。依托中新社遍布全球的采编网络,每天24小时面向广大网民和网络媒体。

神奇的 SQL 之子查询,细节满满 !

  • 时间:
  • 浏览:0

前言

  开心一刻

    有一天,麻雀遇见一只乌鸦。

    麻雀问:你是啥子鸟哟 ?

    乌鸦说:我是凤凰。

    麻雀说:哪有你在龟儿子没有 黢黑的凤凰 ?

    乌鸦说:你懂个铲铲,老子是烧锅炉的凤凰。

子查询

  讲子查询后要,亲戚朋友 先来看看视图,何谓视图 ? 视图是基于 SQL 一段话的结果集的可视化的表,带有行和列,就像有另一个 多真实的表,但后要一张虚拟表,亲戚朋友 可不无需 将其视作为一张普通的表;视图只供数据查询,只能进行数据更改,后要能保存数据,查询数据来源于亲戚朋友 的实体表;说的简单点,视图后要错综复杂 SELECT 一段话的有另一个 多代号,为查询提供便利。视图无缘无故 显示最近的数据,每当亲戚朋友 查询视图时,数据库引擎通过使用 SQL 一段话来重建数据。

  那何谓子查询,它与视图又有何关系 ? 视图是持久化的 SELECT 一段话,而子查询后要将定义视图的 SELECT 一段话直接用于 FROM 子句当中,它是个一次性的视图,在 SELECT 一段话执行完后要就会消失。光说概念,否则还是不太好理解,亲戚朋友 来看下视图与子查询的具体示例,通过示例亲戚朋友 就能更好的理解了

  假设亲戚朋友 有如下表

CREATE TABLE t_customer_credit (
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    login_name VARCHAR(30) NOT NULL COMMENT '登录名',
    credit_type TINYINT(1) NOT NULL COMMENT '额度类型,1:自由资金,2:冻结资金,3:优惠',
    amount DECIMAL(22,6) NOT NULL DEFAULT '0.00000' COMMENT '额度值',
    create_by VARCHAR(30) NOT NULL COMMENT '创建者',
    create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
    update_by VARCHAR(30) NOT NULL COMMENT '修改者',
  PRIMARY KEY (id)
);
INSERT INTO `t_customer_credit` VALUES (1, 'zhangsan', 1, 530.000000, 'system', '2019-7-7 11:30:09', '2019-7-8 20:21:05', 'system');
INSERT INTO `t_customer_credit` VALUES (2, 'zhangsan', 2, 0.000000, 'system', '2019-7-7 11:30:09', '2019-7-7 11:30:09', 'system');
INSERT INTO `t_customer_credit` VALUES (3, 'zhangsan', 3, 0.000000, 'system', '2019-7-7 11:30:09', '2019-7-7 11:30:09', 'system');
INSERT INTO `t_customer_credit` VALUES (4, 'lisi', 1, 0.000000, 'system', '2019-7-7 11:30:09', '2019-7-7 11:30:09', 'system');
INSERT INTO `t_customer_credit` VALUES (5, 'lisi', 2, 0.000000, 'system', '2019-7-7 11:30:09', '2019-7-7 11:30:09', 'system');
INSERT INTO `t_customer_credit` VALUES (6, 'lisi', 3, 0.000000, 'system', '2019-7-7 11:30:09', '2019-7-7 11:30:09', 'system');
View Code

  以及如下 3 个视图

  没有 亲戚朋友 可不无需 用如下 SQL 来显示用户的有另一个 多额度

SELECT v1.login_name, v1.free_amount, v2.freeze_amount, v3.promotion_amount FROM
view_free v1 
LEFT JOIN view_freeze v2 ON v1.login_name = v2.login_name
LEFT JOIN view_promotion v3 ON v1.login_name = v3.login_name;

  加进去子查询的妙招,SQL 如下

  注意 SQL 的执行顺序,子查询作为内层查询会首先执行;原则上子查询都要设定名称,什么都亲戚朋友 尽量从外理内容的高度出发为子查询设定有另一个 多恰当的名称

普通子查询

  中间讲到的子查询后要普通子查询,只能给个定义一段话,后要返回多行结果的子查询。类事 在实际应用中还是用的非常多的,类事 相信亲戚朋友 都比较熟悉,不做不要 的说明,只举个简单例子

  假设亲戚朋友 有商品表:t_commodity

DROP TABLE IF EXISTS t_commodity;
CREATE TABLE t_commodity (
    id INT(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
    serial_number VARCHAR(32) NOT NULL COMMENT '编号',
    name VARCHAR(30) NOT NULL COMMENT '名称',
    category VARCHAR(30) NOT NULL COMMENT '类别',
    sell_unit_price DECIMAL(22,6) NOT NULL COMMENT '出售单价',
    purchase_unit_price DECIMAL(22,6) NOT NULL COMMENT '进货单价',
    create_time DATETIME NOT NULL COMMENT '创建时间',
    update_time DATETIME NOT NULL COMMENT '更新时间',
    primary key(id)
) COMMENT '商品表';

-- 初始数据
INSERT INTO t_commodity(serial_number, name, category, sell_unit_price, purchase_unit_price, create_time, update_time)
VALUES
('0001', 'T恤衫', '衣服', '30', '20', NOW(), NOW()),
('0002', '羽绒服', '衣服', '230.5', '30', NOW(), NOW()),
('0003', '休闲裤', '裤子', '30', '15.5', NOW(), NOW()),
('0004', '运动短裤', '裤子', '30', '10', NOW(), NOW()),
('0005', '菜刀', '厨具', '35', '10', NOW(), NOW()),
('0006', '锅铲', '厨具', '15', '6.5', NOW(), NOW()),
('0007', '', '厨具', '30', '20', NOW(), NOW()),
('0008', '电饭煲', '厨具', '240', '70', NOW(), NOW()),
('0009', '打孔器', '办公用品', '30', '10.5', NOW(), NOW()),
('0010', '文件架', '办公用品', '35', '13', NOW(), NOW()),
('0011', '办公桌', '办公用品', '230', '120', NOW(), NOW()),
('0012', '办公椅', '办公用品', '256', '30', NOW(), NOW());
View Code

  现在亲戚朋友 要实现如下要求:统计出各个类别下商品的数量,亲戚朋友 可不无需 写出如下 SQL

标量子查询

  普通子查询一般是返回多行结果(偶尔也会只返回 1 行,有时也会查只能结果);当返回结果是 1 行 1 列时,该子查询被称作标量子查询,标量子查询有个特殊的限制,都要否则只能返回 1 行 1 列的结果。

  说的简单点:标量子查询后要返回单一值的子查询。否则返回值是单一值,什么都标量子查询可不无需 用在 = 或 <> 曾经都要单一值的比较运算符之中,这也正是其优势所在。亲戚朋友 来看其他简单的例子,还是以 t_commodity 为例,假设亲戚朋友 有如下需求,亲戚朋友 该咋样实现它

    1、查询出售单价高于平均出售单价的商品

    2、查询所有商品信息,并在每个商品的信息中加入平均出售单价、平均进货单价

    3、按照商品类别分类,查询出平均出售单价高于删剪商品的平均出售单价的商品类别(类别名、类别平均出售单价)

  查询 1

    第一感觉,亲戚朋友 我说会写出如下的 SQL

-- 错误的 SQL
SELECT * FROM t_commodity
WHERE sell_unit_price > AVG(sell_unit_price);

    实际上类事 SQL 执行会报错,WHERE 子句中只能使用聚合函数。那类事 查询要为甚么写了,此时标量子查询就派上用场了,SQL 如下

-- 查询出售单价高于平均出售单价的商品
SELECT * FROM t_commodity
WHERE sell_unit_price > (
    SELECT AVG(sell_unit_price) 
    FROM t_commodity
);

  查询 2

    类事 SQL 应该比较容易想到,SELECT 子句中加入 平均出售单价、平均进货单价 列即可,如下

-- 查询所有商品信息,并在每个商品的信息中加入平均出售单价、平均进货单价
SELECT *,
    (SELECT AVG(sell_unit_price) FROM t_commodity) avg_sell_price,
    (SELECT AVG(purchase_unit_price) FROM t_commodity) avg_purchase_price
FROM t_commodity;

  查询 3

    先以类别进行分组,否则取分组后各个类别的平均出售价格,与删剪商品的平均出售价格比较,过滤出满足条件的类别,SQL 如下

-- 按照商品类别分类,查询出平均出售单价高于删剪商品的平均出售单价的商品类别(类别名、类别平均出售单价)
SELECT category, AVG(sell_unit_price) category_avg_sell_price
FROM t_commodity
GROUP BY category
HAVING AVG(sell_unit_price) > (
    SELECT AVG(sell_unit_price) 
    FROM t_commodity
)

  使用标量子查询时,亲戚朋友 都要注意其他:亲戚朋友 要明确的知道该子查询返回的结果后要单一值,绝对只能返回多行结果。不然执行会报错

关联子查询

  关联子查询是指有另一个 多带有对表的引用的子查询,该表也显示在内部内部结构查询中。通俗其他来讲,后要子查询引用到了主查询的数据。在关联子查询中,对于内部内部结构查询返回的每一行数据,内部内部结构查询后要执行一次。另外,在关联子查询中是信息流是双向的,内部内部结构查询的每行数据传递有另一个 多值给子查询,否则子查询为每一行数据执行一次并返回它的记录。否则,内部内部结构查询根据返回的记录做出决策。光看概念,晦涩难懂,亲戚朋友 结合具体的例子来看关联子查询

  还是以商品表:t_commodity  为例,咋样选择出各商品类别中高于该类别平均出售价格的商品,否则亲戚朋友 还没明白类事 需求,没有 亲戚朋友 具体点

    所有商品的类别、出售价格如下

    各类别及类别平均出售价格如下

     亲戚朋友 得到的正确结果应该是

  类事 SQL 亲戚朋友 要咋样写? 像曾经

-- 错误的 SQL
SELECT * FROM t_commodity
WHERE sell_unit_price > (
    SELECT AVG(sell_unit_price) FROM t_commodity
    GROUP BY category
)

  是肯定不行的,那正确的打开妙招应该是为甚么样的了,此时都要关联子查询上场了,SQL如下

SELECT * FROM t_commodity t1
WHERE sell_unit_price > (
    SELECT AVG(sell_unit_price) FROM t_commodity t2
    WHERE t1.category = t2.category
    GROUP BY category
)

   子查询中的 WHERE 子句(WHERE t1.category = t2.category) 至关重要,它的作用是在同一商品类别中对各商品的出售单价与平均单价进行比较。在对表中某一次责记录的集合进行比较时,就可不无需 使用关联子查询,当无缘无故 冒出 “限定” 或 “限制” 曾经的词汇时,通常会使用关联子查询。

  在关联子查询中,对于内部内部结构查询返回的每一行数据,内部内部结构查询后要执行一次,DBMS 内部内部结构的执行结果类事如下

总结

  1、SQL 的逻辑执行顺序

(8) SELECT  (9) DISTINCT (11) <TOP_specification> <select_list>
(1)  FROM <left_table>
(3) <join_type> JOIN <right_table>
(2) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP}
(7) HAVING <having_condition>
(10) ORDER BY <order_by_list>

  2、书写位置

    子查询可不无需 在 SELECT、INSERT、UPDATE 和 DELETE 一段话中,同 =、<、>、>=、<=、IN、BETWEEN 等运算符并肩使用,使用起来也是非常灵活的;标量子查询无缘无故 冒出的位置就更灵活了,暂且仅仅局限于 WHERE 子句中,通常任何可不无需 使用单一值的位置都可不无需 使用,SELECE 子句、GROUP BY 子句、HAVING 子句、ORDER BY 子句,也后要说,无需 使用常量否则列名的地方,都可不无需 使用标量子查询。

  3、时延疑问

    子查询的时延无缘无故 后要有另一个 多比较头疼的疑问,加合适 的索引能改善时延,但也后要局限于很少的情况报告;否则数据量大,对性能要求又高,能无需子查询就尽量别用子查询,尽量用其他的妙招替代,什么都情况报告下,子查询可不无需 用关联查询来替代

参考

  《SQL基础教程》

  《SQL进阶教程》