使用 ChatGPT 访问 PostgreSQL

John Doe 三月 28, 2023

GPT 可以编写 SQL。如果我们用简单的语言写下我们的问题,然后让 GPT 编写 SQL 来获得答案,那么我们就可以节省大量花费在企业流程管理、数据分析软件上面的时间。

scenery

测试

让我们用一个简单的查询来试试看。

> "Get all the customers who have not made any order"

SELECT customers.*
FROM customers
LEFT JOIN orders
ON customers.customer_id = orders.customer_id
WHERE orders.customer_id IS NULL;

嗯,看起来不太好。

  1. 我猜 GPT 认为我们的问题可以使用一些限定条件进行修饰,所以它添加了一个谓词并将其包含在英语中
  2. GPT 不知道我们的表格,所以它自己编造了

请注意,GPT 自信地返回了错误答案,即使它缺少正确执行此操作所需的几乎所有必要信息。GPT 没有提出后续问题的想法。

在 OpenAI 的访问接口中,有一个temperature参数可以控制 GPT 在其响应中的宽松的程度。使用什么采样温度,介于 0 和 2 之间。较高的值(如 0.8)将使输出更加随机,而较低的值(如 0.2)将使其更加集中和确定。

让我们再试一次,将采样温度调整到0

> "Get all the customers"

SELECT * FROM customers;

非常酷,非常明确。但是 GPT 仍然不知道数据架构或实际的表名,因此该查询不会运行正确。

迭代

我们需要告诉 GPT 更多关于我们正在处理的数据的信息;什么模式有什么表,以及这些表有什么列。

GPT 为此提供的唯一机制是提示,所以我们必须做孩子们所说的提示工程 — 一个花哨的短语,用于将尽可能多的信息塞入有限的空间。

我们可以为我们的表生成一些简洁明了的英语描述以添加到提示中:

Schema STRIPE has tables: 
  CHARGE with columns [ID, AMOUNT, CREATED, CURRENCY, CUSTOMER_ID, ...]
  CUSTOMER with columns [ID, NAME, CREATED, SHIPPING_ADDRESS_STATE, ...]
	...

将模式信息添加到提示词后,使用新上下文运行相同的查询,GPT 返回:

> "Get all the customers"

SELECT * FROM STRIPE.CUSTOMER;

看起来不错,第一次跑成功!让我们尝试另一个:

> "Get all charges from customers created in the past year"

SELECT c.ID, c.AMOUNT, c.CREATED, c.CURRENCY, c.CUSTOMER_ID
FROM CHARGE c
INNER JOIN CUSTOMER cu
ON c.CUSTOMER_ID = cu.ID
WHERE cu.CREATED > date('now', '-1 year');

我注意到 GPT 更喜欢枚举列,即使使用*也可以。

这看起来不错,但不会运行。

  1. 我不确定date('now', '-1 year')有效语法在哪里,但它不在 PostgreSQL 中,所以我们应该指定数据库。
  2. 需要在每个表引用之前指定模式
  3. GPT 认为该CREATED列是一个日期(合理),但这实际上是一个 VARCHAR 需要转换的日期。理想情况下,我们会告诉 GPT 每列的类型。

让我们在提示中澄清这一点并尝试另一个查询:

> "Get the three users from China who have paid the most money since February 2022"

SELECT c.name, c.email, SUM(ch.amount) AS total_amount
FROM STRIPE.CUSTOMER c
INNER JOIN STRIPE.CHARGE ch
ON c.id = ch.customer_id
WHERE c.shipping_address_country = 'China'
AND date_part(MONTH, CAST(ch.created AS DATE)) >= 2
AND date_part(YEAR, CAST(ch.created AS DATE)) >= 2022
GROUP BY c.name, C.email
ORDER BY total_amount DESC
LIMIT 3;

撇开 SQL 挑剔不谈,这太不可思议了。机器立即回答了我关于自己业务的含糊不清、写得不好的问题。我们生活在激动人心的时代。