【问题标题】:MySQL: How to use main query variable inside sub query WHERE conditionMySQL:如何在子查询 WHERE 条件中使用主查询变量
【发布时间】:2020-05-06 12:43:41
【问题描述】:

这是我的表“资产”

+----+----------------------------+-------+-----------+
| id | model                      | grade | warehouse |
+----+----------------------------+-------+-----------+
|  1 | Optiplex 9030 AIO i5       |     2 |         2 |
|  2 | Optiplex 9030 AIO i3 Touch |     2 |         2 |
|  3 | Optiplex 9030 AIO i7       |     2 |         1 |
|  4 | Optiplex 9030 AIO i5 Touch |     1 |         1 |
|  5 | Optiplex 9030 AIO i7       |     1 |         1 |
|  6 | Optiplex 9030 AIO i7       |     2 |         1 |
|  7 | Optiplex 9030 AIO i7       |     1 |         2 |
|  8 | Optiplex 9030 AIO i5 Touch |     2 |         2 |
|  9 | Optiplex 9030 AIO i5       |     1 |         1 |
| 10 | Optiplex 9030 AIO i5       |     2 |         2 |
+----+----------------------------+-------+-----------+

我想做的是

SELECT id, model, grade, @ids := GROUP_CONCAT(id) AS ids, 
(SELECT COUNT(*) FROM assets WHERE id IN (@ids) AND warehouse = 1 ) AS w_1_count,
(SELECT COUNT(*) FROM assets WHERE id IN (@ids) AND warehouse = 2 ) AS w_2_count
FROM `assets` GROUP BY model, grade

它给了我这样的结果

+----+----------------------------+-------+------+-----------+-----------+
| id | model                      | grade | ids  | w_1_count | w_2_count |
+----+----------------------------+-------+------+-----------+-----------+
|  2 | Optiplex 9030 AIO i3 Touch |     2 | 2    |         1 |         0 |
|  9 | Optiplex 9030 AIO i5       |     1 | 9    |         0 |         1 |
|  1 | Optiplex 9030 AIO i5       |     2 | 1,10 |         1 |         0 |
|  4 | Optiplex 9030 AIO i5 Touch |     1 | 4    |         0 |         1 |
|  8 | Optiplex 9030 AIO i5 Touch |     2 | 8    |         1 |         0 |
|  5 | Optiplex 9030 AIO i7       |     1 | 5,7  |         0 |         1 |
|  3 | Optiplex 9030 AIO i7       |     2 | 3,6  |         1 |         0 |
+----+----------------------------+-------+------+-----------+-----------+

预期结果是:我想得到哪个?但没有运气

+----+----------------------------+-------+------+-----------+-----------+
| id | model                      | grade | ids  | w_1_count | w_2_count |
+----+----------------------------+-------+------+-----------+-----------+
|  2 | Optiplex 9030 AIO i3 Touch |     2 | 2    |         0 |         1 |
|  9 | Optiplex 9030 AIO i5       |     1 | 9    |         1 |         0 |
|  1 | Optiplex 9030 AIO i5       |     2 | 1,10 |         0 |         2 |
|  4 | Optiplex 9030 AIO i5 Touch |     1 | 4    |         1 |         0 |
|  8 | Optiplex 9030 AIO i5 Touch |     2 | 8    |         0 |         1 |
|  5 | Optiplex 9030 AIO i7       |     1 | 5,7  |         1 |         1 |
|  3 | Optiplex 9030 AIO i7       |     2 | 3,6  |         2 |         0 |
+----+----------------------------+-------+------+-----------+-----------+

当我选择@ids 变量进行显示时,它给了我奇怪的结果集

SELECT id, model, grade, @ids := GROUP_CONCAT(id) AS ids, @ids, 
(SELECT COUNT(*) FROM assets WHERE id IN (@ids) AND warehouse = 1 ) AS w_1_count,
(SELECT COUNT(*) FROM assets WHERE id IN (@ids) AND warehouse = 2 ) AS w_2_count
FROM `assets` GROUP BY model, grade
+----+----------------------------+-------+------+------+-----------+-----------+
| id | model                      | grade | ids  | @ids | w_1_count | w_2_count |
+----+----------------------------+-------+------+------+-----------+-----------+
|  2 | Optiplex 9030 AIO i3 Touch |     2 | 2    | 3,6  |         1 |         0 |
|  9 | Optiplex 9030 AIO i5       |     1 | 9    | 2    |         0 |         1 |
|  1 | Optiplex 9030 AIO i5       |     2 | 1,10 | 9    |         1 |         0 |
|  4 | Optiplex 9030 AIO i5 Touch |     1 | 4    | 1,10 |         0 |         1 |
|  8 | Optiplex 9030 AIO i5 Touch |     2 | 8    | 4    |         1 |         0 |
|  5 | Optiplex 9030 AIO i7       |     1 | 5,7  | 8    |         0 |         1 |
|  3 | Optiplex 9030 AIO i7       |     2 | 3,6  | 5,7  |         1 |         0 |
+----+----------------------------+-------+------+------+-----------+-----------+

问题:

1.) 如何实现与@ids 和另一个条件绑定的预期结果集?

2.) 为什么@ids 列显示下一行的错误值,它应该与 group_concat ids 相同?我不知道我哪里错了

这里我附上了一个 SQL fiddle 以获得快速帮助

http://sqlfiddle.com/#!9/9e3e5d/1/0

【问题讨论】:

  • 未指定表达式求值顺序。特别是当使用 GROUP BY、DISTINCT 或其他东西时——实际上,在这种情况下,评估顺序是绝对不可预测的。您将无法获得正确的结果。使用 CTE(或子查询)。
  • 您使用的是哪个版本的 MySQL?
  • MySQL 5.7 或 MariaDB 10
  • @Akina CTE 是什么?
  • 公用表表达式(WITH 子句)。在 MySQL 8+ 和 MariaDB 10.2.1+ 中可用

标签: mysql group-by mariadb group-concat mysql-variables


【解决方案1】:

我认为您只想在这里进行条件聚合。下面的解决方案加入了一个子查询,该查询按型号和等级进行聚合,得出每个组中最低的id、ID 的 CSV 列表以及两个条件仓库计数。

SELECT
    a2.min_id AS id,
    a1.model,
    a1.grade,
    a2.ids,
    a2.w_1_count,
    a2.w_2_count
FROM assets a1
INNER JOIN
(
    SELECT
        model,
        grade,
        MIN(id) AS min_id,
        GROUP_CONCAT(id) AS ids,
        SUM(warehouse = 1) AS w_1_count,
        SUM(warehouse = 2) AS w_2_count
    FROM assets
    GROUP BY model, grade
) a2
    ON a1.model = a2.model AND
       a1.grade = a2.grade AND
       a1.id = a2.min_id;

这是使用上述查询的更新演示的链接:

Demo

【讨论】:

  • 谢谢@Tim,你又给了我一个想法,其实原始查询太长了,但我只遇到这部分
  • 顺便说一句,您的最后一行结果与实际预期结果/计数不匹配
  • @AZinkey 那是因为您的预期输出不正确,至少不是基于实际样本输入表数据。检查数据;你会看到我的计数是正确的。
猜你喜欢
  • 2018-07-14
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多