AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 6668
Accepted
Peter Bridger
Peter Bridger
Asked: 2011-10-11 06:54:37 +0800 CST2011-10-11 06:54:37 +0800 CST 2011-10-11 06:54:37 +0800 CST

使用多个 PIVOT JOIN 和 GROUP BY 进行高级报告生成

  • 772

我开发了一个时间表记录系统,允许用户记录:

  • 一段时间(9:00 到 12:00)
  • 他们在那段时间做了什么(DutyActivity:1小时报告撰写,2小时培训)

当他们提交时间表时,系统还会记录他们的 GeographyId、RoleId、CategoryId(单个 id)和 AttributeId(多个 id)——这是用户在该时间点的快照。

然后可以查询此记录的时间表信息以获取报告。以最简单的形式,系统将返回一个 UserIds 列表,其中包含PeriodMinutes每个记录的 SUM DutyActivityId。如下所示:

简单的结果

但是,我还想做的是分组并返回AttributeIds与每个时间表一起记录的记录(在TimesheetAttribute表格中)。但是,因为每个时间表都有多个AttributeIds记录,所以它有点复杂。

我的尝试创建了以下报告:

复杂的结果

然而,这个问题是for SUM(PeriodMinutes)eachDutyCategoryId返回的现在太高了。似乎我AttributeIds为每个时间表包含的 SQL 导致SUM计算不正确。

我创建了一个 ZIP,其中包含用于数据库架构和数据的 SQL,以及我在此处截屏的两个查询的 SQL:ZIP Timesheet 示例数据库

以下信息包含在 ZIP 中,但为了便于访问,我将它们链接在这里:

数据库图

报告时间表,没有属性分组

SELECT
*
FROM
(
SELECT
T.UserId,
T.RoleId,T.GeographyId,T.CategoryId,
TDA.DutyActivityId AS TypeId,
SUM(TDA.PeriodMinutes) AS Total
FROM 
Timesheet AS T

LEFT JOIN 
TimesheetDutyActivity AS TDA ON
TDA.TimesheetId = T.TimesheetId

GROUP BY
T.UserId,
T.RoleId,T.GeographyId,T.CategoryId,
TDA.DutyActivityId
) AS SourceTable

/* PIVOT against the known DutyActivityIds */
PIVOT
(
SUM(Total)
FOR TypeId IN ([1],[2],[3],[4],[5])
)
AS PivotType

ORDER BY UserId ASC

报告时间表,尝试进行属性分组

SELECT
*
FROM
(
SELECT
T.UserId,
T.RoleId,T.GeographyId,T.CategoryId,
TA.AttributeId * -1 AS AttributeId, /* Multiply AttributeId by -1 in order to create negative Ids, so that two PIVOT operations can be used */
TDA.DutyActivityId AS TypeId,
SUM(TDA.PeriodMinutes) AS Total

FROM 
Timesheet AS T

LEFT JOIN 
TimesheetAttribute AS TA ON
TA.TimesheetId = T.TimesheetId

LEFT JOIN 
TimesheetDutyActivity AS TDA ON
TDA.TimesheetId = T.TimesheetId

GROUP BY
T.UserId,
AttributeId,
T.RoleId,T.GeographyId,T.CategoryId,
TDA.DutyActivityId
) AS SourceTable

/* PIVOT against the known DutyActivityIds */
PIVOT
(
SUM(Total)
FOR TypeId IN ([1],[2],[3],[4],[5])
)
AS PivotType

/* Also PIVOT against the known AttributeIds */
PIVOT
(
SUM(AttributeId)
FOR AttributeId IN ([-1],[-2],[-3],[-4],[-5])
)
AS PivotAttribute

ORDER BY UserId ASC
join pivot
  • 1 1 个回答
  • 30161 Views

1 个回答

  • Voted
  1. Best Answer
    Peter Bridger
    2011-10-14T05:35:26+08:002011-10-14T05:35:26+08:00

    我设法通过删除第二个 PIVOT 和AttributeIdGROUP BY 参数并在属性上使用 LEFT JOIN 来获得所需的结果。

    此答案由visahk16在SQL 团队论坛上提供:

    SELECT
        *
        FROM
        (
        SELECT
        T.UserId,
        T.RoleId,T.GeographyId,T.CategoryId,
        TA.[-1],TA.[-2],TA.[-3],TA.[-4],TA.[-5],
        TDA.DutyActivityId AS TypeId,
        SUM(TDA.PeriodMinutes) AS Total
    
        FROM 
        Timesheet AS T
    
        LEFT JOIN 
        (SELECT TimesheetId,
         SUM(CASE WHEN AttributeId ='1' THEN -1 ELSE 0 END) AS [-1],
         SUM(CASE WHEN AttributeId ='2' THEN -1 ELSE 0 END) AS [-2],
    ...
         SUM(CASE WHEN AttributeId ='5' THEN -1 ELSE 0 END) AS [-5] 
         FROM TimesheetAttribute 
         GROUP BY TimesheetId 
         )AS TA ON
        TA.TimesheetId = T.TimesheetId
    
        LEFT JOIN 
        TimesheetDutyActivity AS TDA ON
        TDA.TimesheetId = T.TimesheetId
    
        GROUP BY
        T.UserId,
        AttributeId,
        T.RoleId,T.GeographyId,T.CategoryId,
        TDA.DutyActivityId
        ) AS SourceTable
    
        /* PIVOT against the known DutyActivityIds */
        PIVOT
        (
        SUM(Total)
        FOR TypeId IN ([1],[2],[3],[4],[5])
        )
        AS PivotType
    
        ORDER BY UserId ASC
    
    • 1

相关问题

  • SQL Server:使用“有效”日期连接两个表

  • SQL 返回另一个表中选项的答案数为 0

  • 我可以自动执行 MySQL 查询中的“on”语句吗?

  • INNER JOIN 和 OUTER JOIN 有什么区别?

  • JOIN 语句的输出是什么样的?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve