如何修改此SQL查询以显示公司每个部门中最后一次发送测验的参与百分比?

时间:2012-03-07 11:58:07

标签: sql sql-server-2008-r2

我有以下查询,显示每个部门中最后一次发送测验的参与者数量。我希望保持原样但不是显示参与者的数量,而是要显示参与最后一次发送测验的百分比。

为了您的信息,我有以下数据库设计:

  • 员工表:Username, Name, Job, DivisionCode

  • 分部表:SapCode, DivisionName

  • 测验表:QuizID, Title, Description, IsSent

  • UserQuiz 表:UserQuizID, Score, DateTimeComplete, QuizID, Username

注意:每个表中的第一个属性是主键。

IsSent是一个标志,用于确定向用户发送哪个测验以及哪个测验不是。

那么如何修改此查询以显示参与百分比?

SQL查询:

SELECT     
    dbo.Divisions.DivisionShortcut, 
    COUNT(DISTINCT dbo.UserQuiz.Username) AS [Number of Participants], 
    dbo.Quiz.QuizID
FROM
    dbo.Divisions 
INNER JOIN
    dbo.employee ON dbo.Divisions.SapCode = dbo.employee.DivisionCode 
INNER JOIN
    dbo.UserQuiz ON dbo.employee.Username = dbo.UserQuiz.Username 
INNER JOIN
    dbo.Quiz ON dbo.UserQuiz.QuizID = dbo.Quiz.QuizID
WHERE     
    [Quiz].[QuizID] = (SELECT MAX([QuizID]) FROM dbo.Quiz WHERE (IsSent = 1))
GROUP BY 
    dbo.Divisions.DivisionShortcut, dbo.Quiz.QuizID

数据库架构:

/****** Object:  Table [dbo].[Divisions]    Script Date: 03/07/2012 15:48:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Divisions](
    [SapCode] [float] NOT NULL,
    [DivisionShortcut] [varchar](10) NOT NULL,
    [DivisionName] [varchar](max) NOT NULL,
 CONSTRAINT [PK_Divisions] PRIMARY KEY CLUSTERED 
(
    [SapCode] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[Quiz]    Script Date: 03/07/2012 15:48:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Quiz](
    [QuizID] [int] IDENTITY(1,1) NOT NULL,
    [Title] [varchar](max) NOT NULL,
    [IsSent] [bit] NOT NULL,
    [Description] [varchar](max) NULL,
 CONSTRAINT [PK_Quiz] PRIMARY KEY CLUSTERED 
(
    [QuizID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[employee]    Script Date: 03/07/2012 15:48:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[employee](
    [Name] [nvarchar](max) NOT NULL,
    [Username] [nvarchar](255) NOT NULL,
    [JobTitle] [nvarchar](max) NOT NULL,
    [BadgeNo] [float] NOT NULL,
    [EmpOrgType] [float] NOT NULL,
    [DivisionCode] [float] NOT NULL,
 CONSTRAINT [PK_employee] PRIMARY KEY CLUSTERED 
(
    [Username] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Table [dbo].[UserQuiz]    Script Date: 03/07/2012 15:48:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[UserQuiz](
    [UserQuizID] [int] IDENTITY(1,1) NOT NULL,
    [QuizID] [int] NOT NULL,
    [DateTimeComplete] [smalldatetime] NOT NULL,
    [Score] [float] NOT NULL,
    [Username] [nvarchar](255) NOT NULL,
 CONSTRAINT [PK_UserQuiz] PRIMARY KEY CLUSTERED 
(
    [UserQuizID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  Default [DF_Quiz_IsSent]    Script Date: 03/07/2012 15:48:13 ******/
ALTER TABLE [dbo].[Quiz] ADD  CONSTRAINT [DF_Quiz_IsSent]  DEFAULT ((0)) FOR [IsSent]
GO
/****** Object:  ForeignKey [FK_employee_Divisions]    Script Date: 03/07/2012 15:48:13 ******/
ALTER TABLE [dbo].[employee]  WITH CHECK ADD  CONSTRAINT [FK_employee_Divisions] FOREIGN KEY([DivisionCode])
REFERENCES [dbo].[Divisions] ([SapCode])
GO
ALTER TABLE [dbo].[employee] CHECK CONSTRAINT [FK_employee_Divisions]
GO
/****** Object:  ForeignKey [FK_UserQuiz_employee]    Script Date: 03/07/2012 15:48:13 ******/
ALTER TABLE [dbo].[UserQuiz]  WITH CHECK ADD  CONSTRAINT [FK_UserQuiz_employee] FOREIGN KEY([Username])
REFERENCES [dbo].[employee] ([Username])
GO
ALTER TABLE [dbo].[UserQuiz] CHECK CONSTRAINT [FK_UserQuiz_employee]
GO
/****** Object:  ForeignKey [FK_UserQuiz_Quiz]    Script Date: 03/07/2012 15:48:13 ******/
ALTER TABLE [dbo].[UserQuiz]  WITH CHECK ADD  CONSTRAINT [FK_UserQuiz_Quiz] FOREIGN KEY([QuizID])
REFERENCES [dbo].[Quiz] ([QuizID])
GO
ALTER TABLE [dbo].[UserQuiz] CHECK CONSTRAINT [FK_UserQuiz_Quiz]

3 个答案:

答案 0 :(得分:1)

假设参与占总用户的百分比,请尝试:

SELECT     dbo.Divisions.DivisionShortcut, 
           COUNT(DISTINCT dbo.UserQuiz.Username) AS [Number of Participants], 
           COUNT(DISTINCT dbo.UserQuiz.Username) * 100 
                   / MAX([AllUsers].[UserCount]) AS [Percent Participation], 
           dbo.Quiz.QuizID
FROM       (SELECT COUNT(*) [UserCount] from dbo.employee) as [AllUsers]
CROSS JOIN dbo.Divisions 
INNER JOIN dbo.employee 
        ON dbo.Divisions.SapCode = dbo.employee.DivisionCode 
INNER JOIN dbo.UserQuiz
        ON dbo.employee.Username = dbo.UserQuiz.Username 
INNER JOIN dbo.Quiz
        ON dbo.UserQuiz.QuizID = dbo.Quiz.QuizID
WHERE   [Quiz].[QuizID] = (SELECT MAX([QuizID]) FROM dbo.Quiz WHERE (IsSent = 1))
GROUP BY dbo.Divisions.DivisionShortcut, dbo.Quiz.QuizID

编辑:允许用户能够多次回答测验,您应该能够运行以下查询以在部门级别返回参与占用户的百分比:

SELECT     DivisionShortcut, 
           MAX(NumberParticipants) - MAX(NullParticipant) AS [Number of Participants], 
           (MAX(NumberParticipants) - MAX(NullParticipant)) * 100 
                  / MAX(DivisionEmployees) AS [Percent Participation], 
           MAX(LatestQuiz) AS LatestQuiz
FROM
(SELECT     D.DivisionShortcut, 
            DENSE_RANK() OVER (PARTITION BY D.DivisionShortcut ORDER BY UQ.Username) 
                  AS NumberParticipants,
            CASE WHEN UQ.Username IS NULL THEN 1 ELSE 0 END AS NullParticipant,
            DENSE_RANK() OVER (PARTITION BY D.DivisionShortcut ORDER BY E.Username) 
                  AS DivisionEmployees,
            LQ.LatestQuiz
 FROM       (SELECT MAX([QuizID]) AS LatestQuiz FROM dbo.Quiz WHERE (IsSent = 1)) AS LQ
 CROSS JOIN dbo.Divisions AS D
 INNER JOIN dbo.employee AS E
         ON D.SapCode = E.DivisionCode 
 LEFT JOIN  dbo.UserQuiz AS UQ
         ON E.Username = UQ.Username AND LQ.LatestQuiz = UQ.QuizID) AS SQ
GROUP BY DivisionShortcut

答案 1 :(得分:0)

例如,参与者总数为50,那么您应该这样查询:

SELECT     dbo.Divisions.DivisionShortcut, (COUNT(DISTINCT dbo.UserQuiz.Username)/50)*100 AS [Percentage of Participarion], dbo.Quiz.QuizID
FROM         dbo.Divisions INNER JOIN
                      dbo.employee ON dbo.Divisions.SapCode = dbo.employee.DivisionCode INNER JOIN
                      dbo.UserQuiz ON dbo.employee.Username = dbo.UserQuiz.Username INNER JOIN
                      dbo.Quiz ON dbo.UserQuiz.QuizID = dbo.Quiz.QuizID
WHERE     [Quiz].[QuizID] = (SELECT MAX([QuizID]) FROM dbo.Quiz WHERE (IsSent = 1))
GROUP BY dbo.Divisions.DivisionShortcut, dbo.Quiz.QuizID

答案 2 :(得分:0)

如果不是所有员工都参加了测验,那么我认为非参与者在UserQuiz表中没有条目。您需要对员工进行LEFT OUTER JOIN到userQuiz。通过这种方式,您可以获得所有员工,仅获得参与员工的测验结果。

然后从Employee获取所有DISTINCT员工姓名的计数 - 这是100%的员工,然后获得DISTINCT UserQuiz.Username的计数 - 并将其作为所有员工的百分比进行计算。这将为您提供参加测验的员工百分比