为简洁起见,我简化了场景.

初始数据:

| EngineerId | FirstName | LastName | BirthdateOn | CupsOfCoffee | HoursOfSleep |
| ---------- | --------- | -------- | ----------- | ------------ | ------------ |
| 1          | John      | Doe      | 1990-01-01  | 5            | 8            |
| 2          | James     | Bond     | 1990-01-01  | 1            | 6            |
| 3          | Leeroy    | Jenkins  | 2000-06-20  | 16           | 10           |
| 4          | Jane      | Doe      | 2000-06-20  | 8            | 2            |
| 5          | Lorem     | Ipsum    | 2010-12-25  | 4            | 5            |
db.engineers.insertMany([
    { FirstName: 'John', LastName: 'Doe', BirthdateOn: ISODate('1990-01-01'), CupsOfCoffee: 5, HoursOfSleep: 8 },
    { FirstName: 'James', LastName: 'Bond', BirthdateOn: ISODate('1990-01-01'), CupsOfCoffee: 1, HoursOfSleep: 6 },
    { FirstName: 'Leeroy', LastName: 'Jenkins', BirthdateOn: ISODate('2000-06-20'), CupsOfCoffee: 16, HoursOfSleep: 10 },
    { FirstName: 'Jane', LastName: 'Doe', BirthdateOn: ISODate('2000-06-20'), CupsOfCoffee: 8, HoursOfSleep: 2 },
    { FirstName: 'Lorem', LastName: 'Ipsum', BirthdateOn: ISODate('2010-12-25'), CupsOfCoffee: 4, HoursOfSleep: 5 }
])

我们希望看到:

  • 工程师喝掉的那杯咖啡
  • 按咖啡杯降序排列的行号
  • 出生日期相同的工程师的数量
  • 有共同生日的工程师喝的咖啡的总和
  • 拥有共同生日的工程师的平均睡眠时间

该SQL查询为:

SELECT
    FirstName,
    LastName,
    BirthdateOn,
    CupsOfCoffee,
    ROW_NUMBER() OVER (PARTITION BY BirthdateOn ORDER BY CupsOfCoffee DESC) AS 'Row Number',
    COUNT(EngineerId) OVER (PARTITION BY BirthdateOn) AS TotalEngineers,
    SUM(CupsOfCoffee) OVER (PARTITION BY BirthdateOn) AS TotalCupsOfCoffee,
    AVG(HoursOfSleep) OVER (PARTITION BY BirthdateOn) AS AvgHoursOfSleep
FROM Engineers

导致以下情况:

| FirstName | LastName | BirthdateOn | Row Number | CupsOfCoffee | TotalEngineers | TotalCupsOfCoffee | AvgHoursOfSleep |
| --------- | -------- | ----------- | ---------- | ------------ | -------------- | ----------------- | --------------- |
| John      | Doe      | 1990-01-01  | 1          | 5            | 2              | 6                 | 7               |
| James     | Bond     | 1990-01-01  | 2          | 1            | 2              | 6                 | 7               |
| Leeroy    | Jenkins  | 2000-06-20  | 1          | 16           | 2              | 24                | 6               |
| Jane      | Doe      | 2000-06-20  | 2          | 8            | 2              | 24                | 6               |
| Lorem     | Ipsum    | 2010-12-25  | 1          | 4            | 1              | 4                 | 5               |

我对MongoDB Aggregate管道做了相当多的阅读,但还没有找到一个好的解决方案.我知道这是not个SQL,解决方案可能不会产生这种格式的结果(尽管这将是令人惊讶的).我考虑过的一件事是将聚合和集合的结果组合在一起,但这要么是不可能的,要么是我一直在使用错误的术语进行搜索.$merge看起来很有希望,但AFAIU它会修改原来的Collection ,这不是好事.

我已经做到了以下几点,但结果不包括"行号"、特定工程师消耗的杯子或工程师的ID和姓名.

db.engineers.aggregate([
    {
        $group: {
            _id: '$BirthdateOn',
            TotalEngineers: {
                $count: {  }
            },
            TotalCupsOfCoffee: {
                $sum: '$CupsOfCoffee'
            },
            AvgHoursOfSleep: {
                $avg: '$HoursOfSleep'
            }
        }
    }
])

我的 idea 是把所有的工程师加到find个,然后运行汇总,然后按BirthdateOn"加入"到工程师那里.

谢谢你的帮助!非常感谢.

推荐答案

你开了个好头.要获得可与$push运算符一起使用的输入数据,请执行以下操作.

将是这样的:

db.engineers.aggregate([
  {
    $group: {
      _id: "$BirthdateOn",
      TotalEngineers: { $count: {} },
      TotalCupsOfCoffee: { $sum: "$CupsOfCoffee" },
      AvgHoursOfSleep: { $avg: "$HoursOfSleep" },
      data: { $push: "$$ROOT" }
    }
  }
])

关于正确的输出try :

db.engineers.aggregate([
  {
    $group: {
      _id: "$BirthdateOn",
      TotalEngineers: { $count: {} },
      TotalCupsOfCoffee: { $sum: "$CupsOfCoffee" },
      AvgHoursOfSleep: { $avg: "$HoursOfSleep" },
      data: { $push: "$$ROOT" }
    }
  },
  { $unwind: "$data" },
  { $replaceWith: { $mergeObjects: ["$$ROOT", "$data"] } }
])

通常,运行$group和之后运行$unwind是没有意义的,这基本上恢复了以前的操作.

MongoDB 5.0版本引入了$setWindowFields阶段,非常类似于SQL窗口函数:

我想应该是这个:

db.engineers.aggregate([
  {
    $setWindowFields: {
      partitionBy: "$BirthdateOn",
      sortBy: { CupsOfCoffee: 1 },
      output: {
        TotalEngineers: { $count: {} },
        TotalCupsOfCoffee: { $sum: "$CupsOfCoffee" },
        AvgHoursOfSleep: { $avg: "$HoursOfSleep" },
        "Row Number": { $documentNumber: {} }
      }
    }
  }
])

Database相关问答推荐

Postgres和Oracle之间 Select 查询的结果差异

为什么引用 SQLite rowid 会导致外键不匹配?

在 bindParam 中使用 LIKE 进行 MySQL PDO 查询

创建数据库索引有哪些最佳实践和经验法则?

为什么 COUNT() 只显示一行表格?

数据库排序规则更改问题 (SQL Server 2008)

SQLServer:如何对按外键依赖性排序的表名进行排序

PostgreSQL Clob 数据类型

TSQL - 表值函数中的 If..Else 语句 - 无法通过

将整数作为字符串存储在数据库中的缺点

如何最好地在 MS SQL Server 中复制整个数据库?

C# 连接到数据库并列出数据库

如何将数据库从一台计算机复制到另一台计算机?

为什么String or Binary data would be truncated不是更具描述性的错误?

Joomla 数据库设置

cURL 和 PHP 显示1

如何在 MySQL 中清理或调整 ibtmp1 文件的大小?

根据上次日期 Select 记录

在一个查询中使用 group by 计算多列

美国城市和州的列表/数据库