MySQL必知必会

CH1:了解SQL

1.1 数据库基础

数据库(database):保存有组织的数据的容器(通常是一个文件或一组文件)。
表(table):某种特定类型的结构化清单。

  • 相同数据库中不能两次使用相同的表名。

模式(schema):关于数据库和表的布局及特性的信息。

  • 比如数据在表中如何存储、存储什么样的数据

列(column):表中的一个字段。所有表都是由一个或多个列组成。
数据类型(datatype):所容许的数据的类型。每个表列都有相应的数据类型,它限制(或容许)该列中存储的数据。
行(row):表中的一个记录。
主键(primary key):一列(或一组列),其值能够唯一区分表中每个行。

  • 主键值规则:
    • 任意两行都不具有相同的主键值;
    • 每个行都必须具有一个主键值(主键列不允许NULL值)。
  • 主键可以定义在表的一列上,也可以使用多个列,这时所有列的组合必须是唯一的(单个列可以不唯一)。

外键

1.2 什么是SQL

Structured Query Languane(SQL)是一种专门用来与数据库通信的语言。

CH2:MySQL简介

2.1 什么是MySQL

MySQL是一种DBMS(数据库管理系统),即数据库软件。
DBMS分为:

  • 基于共享文件系统的DBMS;
  • 基于客户机-服务器(Client-Server(C/S))的DBMS;

2.2 MySQL版本

mysql -u root -p -h myserver -P 9999

CH3:使用MySQL

3.1 连接

为了连接到MySQL,需要知道:

  • 主机名(计算机名)——如果连接到本地MySQL服务器,为localhost;
  • 端口(如果使用默认端口3306之外的端口);
  • 一个合法的用户名(如root);
  • 用户口令(密码);

3.2 选择数据库

关键字(key word):作为MySQL语言组成部分的一个保留字。决不要用关键字命名一个表和列。

USE crashcourse; -- 选择数据库

3.3 了解数据库和表

SHOW DATABASE; -- 返回可用数据库
SHOW TABLES; -- 返回当前选择的数据库内可用表
SHOW COLUMNS FROM customers; -- 返回选择的表的字段名、数据类型、键信息、默认值、是否允许NULL等
DESCRIBE customers -- 同上,DESCRIBE=SHOW COLUMNS FROM
SHOW STATUS; -- 显示广泛的服务器状态信息
SHOW GRANTS; -- 显示授予用户的安全权限
SHOW CREATE DATABASE; -- 显示创建特定数据库的MySQL语句
SHOW CREATE TABLE; -- 显示创建特定表的MySQL语句
SHOW ERRORS; -- 显示服务器错误信息
SHOW WARNINGS; -- 显示服务器警告信息

image.png

CH4:检索数据

4.1 SELECT语句

作用:从一个或多个表中检索信息。

4.2 检索单个列

SELECT prod_name -- SELECT后为所需列名
FROM products; -- FROM后为所需表名
  • 多条SQL语句必须以分号(;)分隔;
  • SQL语句不区分大小写;
  • 处理SQL语句时,其中所有空格都被忽略。

4.3 检索多个列

SELECT prod_id, prod_name, prod_price
FROM products;
  • 选择多个列时,一定要在列名之间加上逗号,但最后一个列名后不加。

4.4 检索所有列

SELECT *
FROM products;

4.5 检索不同的行

SELECT DISTINCT vend_id -- DISTINCT指示MySQL只返回不同的值
FROM products; -- 先从表products中选择字段vend_id,在返回字段中不同的值

image.png

4.6 限制结果

可用LIMIT子句返回前几行或第一行

  • 带一个值的LIMIT总是从第一行开始,给出的数为返回的行数;
  • 带两个值的LIMIT从行号为第一个值的位置开始,给出的第二个值为返回的行数;
SELECT prod_name
FROM products
LIMIT 4; -- LIMIT 4指示MySQL返回不多于4行
SELECT prod_name
FROM products
LIMIT 3, 4; -- LIMIT 3, 4指示MySQL返回从行3开始的4行。第一个数为开始位置,第二个数为要检索的行数
SELECT prod_name
FROM products
LIMIT 4 OFFSET 3; -- 同LIMIT 3, 4。从行3开始的4行

image.png
image.png

4.7 使用完全限定的表名

SELECT products.prod_name -- 完全限定的列名:表名.列名
FROM products;
SELECT products.prod_name
FROM crashcourse.products; -- 完全限定的表名:数据库名.表名

CH5:排序检索数据

5.1 排序数据

子句(clause):SQL语句有子句构成,有些子句是必需的,而有的是可选的。一个子句通常由一个关键字和所提供的数据组成。

SELECT prod_name
FROM products
ORDER BY SELECT prod_name;

image.png

5.2 按多个列排序

指定多个列名,列名之间用逗号隔开。先按第一个列排序,第一个列的行相同的再按第二个列排序。

SELECT prod_id, prod_price, prod_name
FROM products
ORDER BY SELECT prod_price, prod_name;

5.3 指定排序方向

关键字:DESC。默认的是升序(ASC:ascending)

SELECT prod_id, prod_price, prod_name
FROM products
ORDER BY SELECT prod_price DESC; -- 降序排序
SELECT prod_id, prod_price, prod_name
FROM products
ORDER BY SELECT prod_price DESC, prod_name; -- DESC关键字只应用到直接位于其前面的列名
  • 如果想在多个列上进行降序排序,必须对每个列指定DESC关键字。

image.png
image.png

CH6:过滤数据

6.1 使用WHERE子句

  • WHERE子句在表名(FROM子句)之后给出。

image.png

6.2 WHERE子句操作符

条件操作符:
image.png

6.2.1 检查单个值

SELECT prod_name, prod_price
FROM products
WHERE prod_price = 2.50; -- 等号(=)操作符不仅能匹配数值还能匹配字符串,串类型要限定引号。
SELECT prod_name, prod_price
FROM products
WHERE prod_name = 'fuses'; -- MySQL在执行匹配时默认不区分大小写
SELECT prod_name, prod_price
FROM products
WHERE prod_price < 10;
SELECT prod_name, prod_price
FROM products
WHERE prod_price <= 10;

6.2.2 不匹配检查

SELECT vend_id, prod_name
FROM products
WHERE vend_id <> 1003;
SELECT vend_id, prod_name
FROM products
WHERE vend_id != 1003;

6.2.3 范围值检查

使用BETWEEN操作符,必须指定两个值——所需范围的低端值和高端值。这两个值必须用AND关键词分隔。BETWEEN匹配范围中的所有值,包括指定的开始值和结束值。

SELECT prod_name, prod_price
FROM products
WHERE prod_price BETWEEN 5 AND 10; -- [5,10]

6.2.4 空值检查

NULL 无值(no value),它与字段包括0、空字符串或仅仅包含空格不同。
检查具有NULL值的列的子句:IS NULL

SELECT cust_id
FROM customers
WHERE cust_email IS NULL;

image.png

CH7:数据过滤

7.1 组合WHERE子句

操作符(operator):用来联结或改变WHERE子句中的子句的关键字。也称为逻辑操作符(Logical operator)

  • AND:用在WHERE子句中的关键字,用来指示检索满足所有给定条件的行。
  • OR:WHERE子句中使用的关键字,用来表示检索匹配任一给定条件的行。
  • 计算次序:SQL在处理OR操作符前,优先处理AND操作符。圆括号具有较AND或OR操作符更高的计算次序。
SELECT prod_name, prod_price
FROM products
WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10;
SELECT prod_name, prod_price
FROM products
WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;

image.png

7.2 IN操作符

IN:WHERE子句中用来指定要匹配值的清单的关键字,功能与OR相当。
IN操作符用来指定条件范围,范围中的每个条件都可以进行匹配。
优点:
image.png

SELECT prod_name, prod_price
FROM products
WHERE vend_id IN (1002, 1003)
ORDER BY prod_name;

7.3 NOT操作符

NOT:WHERE子句中用来否定后跟条件的关键字。

SELECT prod_name, prod_price
FROM products
WHERE vend_id NOT IN (1002, 1003)
ORDER BY prod_name;

image.png

CH8:用通配符进行过滤

8.1 LIKE操作符

通配符(wildcard):用来匹配值的一部分的特殊字符。
搜索模式(search pattern):有字面值、通配符或两者组合构成的搜索条件。
为在搜索子句中使用通配符,必须使用LIKE操作符而不是相等匹配。

8.1.1 百分号(%)通配符

%表示任何字符出现任意次数。%代表搜索模式中给定位置的0个、1个或多个字符。

SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE 'jet%'; -- 检索任意以jet起头的词
SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE '%anvil%'; -- 匹配任意位置包含文本anvil的值
SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE 's%e'; -- 以s开头以e结尾

image.png
image.png

8.1.2 下划线(_)通配符

下划线的用途与%一样,但下划线只匹配单个字符而不是多个字符。
与%能匹配0个字符不一样,_总是匹配一个字符,不能多也不能少。

SELECT prod_id, prod_name
FROM products
WHERE prod_name LIKE '_ ton anvil';

8.2 使用通配符的技巧

CH9:用正则表达式进行搜索

9.1 正则表达式介绍

正则表达式是用来匹配文本的特殊的串(字符集合)。

9.2 使用MySQL正则表达式

注意:MySQL仅支持多数正则表达式实现的一个很小的子集。

9.2.1 基本字符匹配

SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000'
ORDER BY prod_name; -- REGEXP后所跟的东西作为正则表达式
SELECT prod_name
FROM products
WHERE prod_name REGEXP '.000'
ORDER BY prod_name; -- .是正则表达式语言中一个特殊的字符。它表示匹配任意*一个*字符。

image.png
image.png
image.png

9.2.2 进行OR匹配

为搜索两个串之一,使用|。

SELECT prod_name
FROM products
WHERE prod_name REGEXP '1000|2000'
ORDER BY prod_name; -- |为正则表达式的OR操作符。它表示匹配其中之一。

image.png

9.2.3 匹配几个字符之一

只想匹配特定字符,可通过指定一组用[和]括起来的字符来完成。[]是另一种形式的OR语句。
字符集合也可以被否定,即它们将匹配除指定字符外的任何东西。为否定一个字符集,在集合的开始处放置一个即可。例如:[123]匹配除1、2、3外的任何东西。

SELECT prod_name
FROM products
WHERE prod_name REGEXP '[123] Ton'
ORDER BY prod_name; -- [123] Ton = [1|2|3] Ton,是后者的缩写。意为1 Ton或2 Ton或3 Ton
										-- 需要用[]来定义OR语句查找什么。
SELECT prod_name
FROM products
WHERE prod_name REGEXP '1|2|3 Ton'
ORDER BY prod_name; -- 1|2|3 Ton意为1或2或3 Ton.
										-- 除非把字符|括在一个集合中,否则它将用于整个串。

9.2.4 匹配范围

集合可以用来定义要匹配的一个或多个字符。例如:[0123456789]=[0-9]。-定义一个范围。范围不一定只是数值的,[a-z]匹配人以字母字符。

9.2.5 匹配特殊字符

为了匹配特殊字符,必须用\为前导。\-表示查找-,\.表示查找.。这种处理就是所谓的转义(escaping)。
\也用来引用元字符(具有特殊含义的字符)。
image.png

9.2.6 匹配字符类

字符类(character class):预定义的字符集。
image.png

9.2.7 匹配多个实例

类似于通配符,
image.png

SELECT prod_name
FROM products
WHERE prod_name REGEXP '\\([0-9] sticks?\\)' -- (0/1…9 stick/sticks)
ORDER BY prod_name; -- s后的?使s可选,因为?匹配它前面的任意字符的0次或1次出现。
SELECT prod_name
FROM products
WHERE prod_name REGEXP '[[:digit:]]{4}' -- [[:digit:]]{4}=[0-9][0-9][0-9][0-9]
ORDER BY prod_name; -- 匹配连在一起的任意4位数字
										-- [:digit:]=[0-9], {4}要求它前面的字符出现4次
										-- 外面的[]是限定,定义{4}指定的要出现4次的字符,这里是[0-9]出现4次。

9.2.8 定位符

以上都匹配任意一串中任意位置的文本,为匹配特定位置的文本,需要用定位符。
image.png

SELECT prod_name
FROM products
WHERE prod_name REGEXP '^[0-9\\.]'
ORDER BY prod_name; -- 以一个数或.开始的产品

image.png
image.png
image.png

CH10:创建计算字段

10.1 计算字段

字段(field):基本上与列(column)的意思相同,经常互换使用,不过数据库列一般称为列,而术语字段通常用在计算字段的连接上。

10.2 拼接字段

拼接(concatenate):将值联结到一起构成单个值。
别名(alias):一个字段或值的替换名。用AS关键字赋予。
在MySQL的SELECT语句中,可使用Concat()函数来拼接两个列。
image.png

SELECT Concat(vend_name, ' (', vend_country, ')')
FROM vendors
ORDER BY vend_name; -- Concat()拼接串,即把多个串连接起来形成一个较长的串。
SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')')
FROM vendors
ORDER BY vend_name; -- RTrim()函数去掉右边的所有空格。
SELECT Concat(RTrim(vend_name), ' (', RTrim(vend_country), ')') AS vend_title
FROM vendors
ORDER BY vend_name;

image.png
image.png
image.png

10.3 执行算术计算

SELECT prod_id,
       quantity,
    	 item_price,
       quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 2005; -- expanded_price列 为一个计算字段,计算quantity*item_price

image.png

  • 圆括号可以用来区分优先顺序。

image.png

CH11:使用数据处理函数

11.1 函数

11.2 使用函数

11.2.1 文本处理函数

image.png
image.png

SELECT cust_name, cust_contact
FROM customers
WHERE Soundex(cust_contact) = Soundex('Y lie'); -- Soundex()匹配所有发音类似于Y.Lie的联系名。
-- SOUNDEX是一个将任何文本串转换为描述其语音表示的字母数字模式的算法。

11.2.2 日期和时间处理函数

  • 一般,应用程序不使用用来存储日期和时间的格式,因此日期和时间函数总是用来读取、统计和处理这些值。

image.png

  • 日期必须为格式yyyy-mm-dd。
SELECT cust_name, cust_contact
FROM customers
WHERE Date(order_date) = '2005-09-01';
SELECT cust_name, cust_contact
FROM customers
WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
SELECT cust_name, cust_contact
FROM customers
WHERE Year(order_date) = 2005 AND Month(order_date) = 9;

11.2.3 数值处理函数

image.png

CH12:汇总数据

12.1 聚集函数

聚集函数(aggregate function):运行在行组上,计算和返回单个值的函数。
image.png

12.1.1 AVG()函数

  • AVG()可以返回所有列的平均值,也可以用来返回特定列或行的平均值。
SELECT AVG(prod_price) AS avg_price
FROM products;
SELECT AVG(prod_price) AS avg_price
FROM products
WHERE vend_id = 1003;

image.png
image.png

12.1.2 COUNT()函数

  • COUNT()确定表中行的数目或符合特定条件的行的数目。有两种使用方式。
    • 使用COUNT(*)对表中行的数目进行计数,不管表列中包含的是空值(NULL)还是非空值;
    • 使用COUNT(column)对特定列中具有值的行进行计数,忽略NULL值。
SELECT COUNT(*) AS num_cust
FROM customers; -- 返回所有行数。
SELECT COUNT(cust_email) AS num_cust
FROM customers; -- 返回cust_email列中有值的行。
-- 是否因为*代表所有行,只要有一列值不是NULL,该行就计数,若该行所有列都为NULL,COUNT(*)也不计数。

image.png

12.1.3 MAX()函数

  • MAX()返回指定列中的最大值,可以是数值、日期值、字符串。MAX()要求指定列名。

image.png
image.png

12.1.4 MIN()函数

  • 与MAX()相反,它返回指定列的最小值。

image.png
image.png

12.1.5 SUM()函数

  • SUM()用来返回指定列值的和。
  • 也可以用来合计计算值。
SELECT SUM(quantity) AS items_ordered
FROM orderiterms
WHERE order_num = 20005;
SELECT SUM(item_price*quantity) AS total_price
FROM orderiterms
WHERE order_num = 20005; -- WHERE子句保证只统计某个物品订单中的物品。

image.png
image.png

12.2 聚集不同值

image.png
image.png
image.png

SELECT AVG(DISTINCT prod_price) AS avg_price
FROM products
WHERE vend_id = 1003;

12.3 组合聚集函数

SELECT COUNT(*) AS num_items,
    	 MIN(prod_price) AS price_min,
    	 MAX(prod_price) AS price_max,
    	 AVG(prod_price) AS price_avg
FROM prducts;

image.png

CH13:分组数据

13.1 数据分组

分组允许把数据分为多个逻辑组,以便能对每个组进行聚集计算。

13.2 创建分组

分组是在SELECT语句中的GROUP BY子句建立的。

  • GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套。

image.png
image.png

13.3 过滤分组

WHERE过滤行,HAVING过滤分组。
image.png
image.png

SELECT vend_id, COUNT(*) AS num_prods
FROM products
WHERE prod_price >= 10 -- WHERE子句过滤所有prod_price至少为10的行。
GROUP BY vend_id -- 然后按vend_id分组数据。
HAVING COUNT(*) >= 2; -- HANVING子句过滤计数为2以上的分组。

13.4 分组和排序

image.png
image.png

SELECT order_num, SUM(quantity*item_price) AS ordertotal
FROM orderitems
GROUP BY order_num
HAVING SUM(quantity*item_price) >= 50
ORDER BY ordertotal;

13.5 SELECT子句顺序

image.png
image.png

CH14:使用子查询

14.1 子查询

查询(query):任何SQL语句都是查询。但此术语一般指SELECT语句。
子查询(subquery):嵌套在其他查询中的查询。

14.2 利用子查询进行过滤

  • WHERE子句使用子查询能够编写出功能很强并且很灵活的SQL语句。对于能够嵌套的子查询的数目没有限制,不过在实际使用时由于性能的限制,不能嵌套太多的子查询。

image.png

SELECT cust_name, cust_contact
FROM customers
WHERE cust_id IN (SELECT cust_id
                  FROM orders
                  WHERE order_num IN (SELECT order_num
                                      FROM orderitems
                                      WHERE prod_id = 'TNT2'));

14.3 作为计算字段使用子查询

相关子查询(correlated subquery):涉及外部查询的子查询。

SELECT cust_name,
    	 cust_state,
       (SELECT COUNT(*)
        FROM orders
        WHERE orders.cust_id = customers.cust_id) AS orders -- 完全限定名。
FROM customers
ORDER BY cust_name;
-- 列名有多义性,必须使用相关子查询。
-- 该子查询对检索出的每个客户执行一次。
-- SQL比较orders表中的cust_id与当前正从customers表中检索的cust_id。怎么理解?合成一个表?

CH15:联结表

15.1 联结

SQL最强大的功能之一就是能在数据检索查询的执行中联结(join)表。

15.1.1 关系表

关系表的设计就是要保证把信息分解成多个表,一类数据一个表。各表通过某些常用的值(即关系设计中的关系(relational))互相关联。
外键(foreign key):外键为某个表中的一列,它包含拎一个表中的主键值,定义了两个表之间的关系。
可伸缩性(scale):能够适应不断增加的工作量而不失败。设计良好的数据库或应用程序称之为可伸缩性好(scale well)。
关系数据可以有效地存储和方便地处理。因此,关系数据库地可伸缩性远比非关系数据库要好。

15.1.2 为什么要使用联结

image.png

15.2 创建联结

规定要联结地所有表以及它们如何关联即可。

SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id 
ORDER BY vend_name, prod_name;
-- WHERE子句指示MySQL匹配vendors表中的vend_id和products表中的vend_id。联结两个表。
SELECT vend_name, prod_name, prod_price
FROM vendors, products
ORDER BY vend_name, prod_name; -- 返回笛卡尔积
SELECT *
FROM vendors, products
ORDER BY vend_name, prod_name; -- 直接返回两个表所有的列,行为笛卡尔积配对结果。
SELECT *
FROM vendors, products
WHERE vendors.vend_id = products.vend_id 
ORDER BY vend_name, prod_name; -- 返回笛卡尔积配对结果中vend_id一样的结果。

15.2.1 WHERE子句的重要性

在联结两个表时,你实际上做的是将第一个表中的每一行与第二个表中的每一行配对。WHERE子句作为过滤条件,它只包含那些匹配给定条件(这里是联结条件)的行,没有WHERE子句,第一个表中的每个行将与第二个表中的每个行配对,而不管它们逻辑上是否可以配在一起。
笛卡尔积(cartesian product):由没有联结条件的表关系返回的结果为笛卡尔积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。
image.png
image.png

15.2.2 内部联结

以上联结称为等值联结(equijoin),也称为内部联结,基于两个表之间的相等测试。
使用不同语法来明确指定联结的类型:

SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;

15.2.3 联结多个表

SELECT prod_name, vend_name, prod_price, quantity
FROM orderitems, products, vendors
WHERE products.vend_id = vendors.vend_id
  AND orderitems.prod_id = products.prod_id
  AND order_num = 20005;

image.png

CH16:创建高级联结

16.1 使用表别名

别名除了用于列名和计算字段外,SQL还允许给表名起别名。理由如下:

  • 缩短SQL语句;
  • 允许在单条SELECT语句中多次使用相同的表。

注意,表别名只在查询执行中使用。与列别名不一样,表别名不返回到客户机。

16.2 使用不同类型的联结

16.2.1 自联结

SELECT p1.prod_id, p1.prod_name
FROM products AS p1, products AS p2
WHERE p1.vend_id = p2.vend_id
  AND p2.prod_id = 'DTNTR';

SELECT prod_id, prod_name
FROM products
WHERE vemd_id = (SELECT vend_id
                 FROM products
                 WHERE prod_id = 'DTNTR');

image.png

16.2.2 自然联结

自然联结排除多次出现,使每个列只返回一次。系统不完成这项工作,由你自己完成,你只能选择那些唯一的列。一般是通过对表使用通配符(SELECT *),对所有其他表的列使用明确的子集来完成。

SELECT c.*, o.order_num, o.order_date,
    	 oi.prod_id, oi.quantity, oi.item_price
FROM customers AS c, orders AS o, orderitems AS oi
WHERE c.cust_id = o.cust_id
  AND oi.order_num = o.order_num
  AND prof_id = 'FB';

16.2.3 外部联结

外部联结:联结包含了那些在相关表中没有关联行的行。
关键字:LEFT OUTER JOINRIGHT OUTER JOIN

  • LEFT和RIGHT指定包含其所有行的表,LEFT指左边,RIGHT指右边。
SELECT customers.cust_id, orders.order_num
FROM customers LEFT OUTER JOIN orders
 ON customers.cust_id = orders.cust_id; 
-- customers表中所有cust_id行均选择,orders表中只选择cust_id与customers表中相等的。

image.png
image.png

16.3 使用带聚集函数的联结

SELECT customers.cust_name, customers.cust_id,
    	 COUNT(orders.order_num) AS num_ord
FROM customers INNER JOIN orders
 ON customers.cust_id = orders.cust_id
GROUP BY customers.cust_id;

16.4 使用联结和联结条件

CH17:组合查询

17.1 组合查询

MySQL允许执行多个查询(多条SELECT语句),并将结果作为单个查询结果集返回。这些组合查询通常称为并(union)或复合查询(compound query)。
需要使用组合查询的两种基本情况:

  • 在单个查询中从不同的表返回类似结构的数据;
  • 在对单个表执行多个查询,按单个查询返回数据。

image.png

17.2 创建组合查询

关键字:UNION

17.2.1 使用UNION

在各条UNION语句之间放上关键字UNION

posted @   本座齐天大圣  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 【.NET】调用本地 Deepseek 模型
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示