Mysql常见查询示例:修订间差异

来自泡泡学习笔记
跳到导航 跳到搜索
无编辑摘要
无编辑摘要
第141行: 第141行:


  WITH s1 AS (
  WITH s1 AS (
SELECT article, dealer, price,
    SELECT article, dealer, price,
RANK() OVER (PARTITION BY article
          RANK() OVER (PARTITION BY article
ORDER BY price DESC
                            ORDER BY price DESC
) AS Rank
                      ) AS `Rank`
FROM shop
      FROM shop
  )
  )
  SELECT article, dealer, price
  SELECT article, dealer, price
FROM s1
  FROM s1
WHERE Rank = 1
  WHERE `Rank` = 1
  ORDER BY article
  ORDER BY article;

2023年6月25日 (日) 06:31的版本

以下是使用MySQL解决一些常见问题的示例。


创建表

其中一些示例使用表格shop来存储每个交易者(dealer)的每个商品(item number)的价格。假设每个交易者对于每个商品都有一个固定的价格,那么(article,dealer)是记录的主键。

启动命令行工具mysql并选择一个数据库:

$> mysql your-database-name

使用以下语句创建并填充示例表格:

CREATE TABLE shop (
article INT UNSIGNED DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT  NOT NULL,
price DECIMAL(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));
INSERT INTO shop VALUES
(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),
(3,'C',1.69),(3,'D',1.25),(4,'D',19.95);

执行完语句后,表格应该有以下内容:

SELECT * FROM shop ORDER BY article;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 1 | A | 3.45 |
| 1 | B | 3.99 |
| 2 | A | 10.99 |
| 3 | B | 1.45 |
| 3 | C | 1.69 |
| 3 | D | 1.25 |
| 4 | D | 19.95 |
+---------+--------+-------+

查询列的最大值

SELECT MAX(article) AS article FROM shop;

+---------+
| article |
+---------+
| 4 |
+---------+


找到某一列最大值所在行

这可以通过子查询轻松完成:

SELECT article, dealer, price
FROM shop
WHERE price=(SELECT MAX(price) FROM shop);

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0004 | D | 19.95 |
+---------+--------+-------+

另一种解决方案是使用 LEFT JOIN,如下所示:

SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.price < s2.price
WHERE s2.article IS NULL;

你也可以通过按价格降序排序所有行,并使用 MySQL 特定的 LIMIT 子句仅获取第一行,像这样:

SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1;
注意

如果有几个价格都是 19.95 的最贵商品,则 LIMIT 解决方案只会显示其中一个。


找到每个组的最大列值

SELECT article, MAX(price) AS price
FROM shop
GROUP BY article
ORDER BY article;

+---------+-------+
| article | price |
+---------+-------+
| 0001 | 3.99 |
| 0002 | 10.99 |
| 0003 | 1.69 |
| 0004 | 19.95 |
+---------+-------+


找到持有某一列分组最大值的行

可以使用以下子查询解决此问题:

SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article)
ORDER BY article;

+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+

上述示例使用了相关子查询,这可能效率不高。解决该问题的其他可能性是在FROM子句中使用非相关子查询、LEFT JOIN或带有窗口函数的公共表达式。


非相关子查询:

SELECT s1.article, dealer, s1.price
FROM shop s1
JOIN (
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article) AS s2
ON s1.article = s2.article AND s1.price = s2.price
ORDER BY article;


LEFT JOIN:

SELECT s1.article, s1.dealer, s1.price
FROM shop s1
LEFT JOIN shop s2 ON s1.article = s2.article AND s1.price < s2.price
WHERE s2.article IS NULL
ORDER BY s1.article;

LEFT JOIN基于这样的事实:当s1.price达到最大值时,没有s2.price的值更大,因此相应的s2.article值为NULL。


带有窗口函数的公共表达式:

WITH s1 AS (
   SELECT article, dealer, price,
          RANK() OVER (PARTITION BY article
                           ORDER BY price DESC
                      ) AS `Rank`
     FROM shop
)
SELECT article, dealer, price
  FROM s1
  WHERE `Rank` = 1
ORDER BY article;