if I have a two tables (one of customers, with their information including address, name, emails etc) and another of orders (with order number, shipping date, customer name who ordered that item), how could I show the email of the customers who have less than 3 orders?
I know I have to use an inner join and some alias's, but i'm not sure how to proceed.
Thanks!
what I have so far:
SELECT customer.email
FROM customer as cust
INNER JOIN (select customer_id, sum(line_qty) AS total
from orders as o ON cust.customer_id = o.customer_id
where total = (SELECT total < 3
FROM (select customer_id, sum(line_qty) AS total
from orders as o ON cust.customer_id = o.customer_id
) as sub);
I have created the full example with SQL. Just run the query to create the database, tables, and the Stored Procedure "Get Customer Orders".
There are sample data in the two table of "Customers" and the table "Orders" the relation is "1 Customer to MANY Orders" so there is a Foreign key for the Customer inside table Orders, to identify which customer had did the order. So.
First Create the Data base, Run this query.
Create DataBase [Customer_OrdersDB]
Refresh the Server explorer, you will find a database with that name has created.
Then Run the Query to create Stored Procedure and Tables.
USE [Customer_OrdersDB]
GO
CREATE PROCEDURE [dbo].[GetCustomer_Mail]
AS
BEGIN
select Email as Customer_Mail
from Customers as cust inner join Orders as ord
on cust.CustomerId = ord.OrderCustomerId
group by(Email)
having COUNT(ord.OrderCustomerId) < 3
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customers](
[CustomerId] [int] IDENTITY(1,1) NOT NULL,
[CustomerName] [nvarchar](50) NULL,
[Address] [nvarchar](50) NULL,
[Email] [nvarchar](50) NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
(
[CustomerId] 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].[Orders] Script Date: 12/6/2014 5:19:11 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Orders](
[OrderId] [int] IDENTITY(1,1) NOT NULL,
[OrderDate] [datetime] NULL,
[OrderNumber] [nvarchar](50) NULL,
[OrderCustomerId] [int] NULL,
CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED
(
[OrderId] 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 IDENTITY_INSERT [dbo].[Customers] ON
INSERT [dbo].[Customers] ([CustomerId], [CustomerName], [Address], [Email]) VALUES (1, N'Ahmed', N'Cairo', N'Ahmed#Yahoo.Com')
INSERT [dbo].[Customers] ([CustomerId], [CustomerName], [Address], [Email]) VALUES (2, N'Ali', N'Paris', N'Ali#yahoo.com')
INSERT [dbo].[Customers] ([CustomerId], [CustomerName], [Address], [Email]) VALUES (3, N'Samir', N'UK', N'Samir#msn.com')
SET IDENTITY_INSERT [dbo].[Customers] OFF
SET IDENTITY_INSERT [dbo].[Orders] ON
INSERT [dbo].[Orders] ([OrderId], [OrderDate], [OrderNumber], [OrderCustomerId]) VALUES (1, CAST(0x0000A2A600000000 AS DateTime), N'1234', 1)
INSERT [dbo].[Orders] ([OrderId], [OrderDate], [OrderNumber], [OrderCustomerId]) VALUES (2, CAST(0x0000A2C700000000 AS DateTime), N'555', 1)
INSERT [dbo].[Orders] ([OrderId], [OrderDate], [OrderNumber], [OrderCustomerId]) VALUES (3, CAST(0x00009CF100000000 AS DateTime), N'56d66', 1)
INSERT [dbo].[Orders] ([OrderId], [OrderDate], [OrderNumber], [OrderCustomerId]) VALUES (4, CAST(0x00009E9B00000000 AS DateTime), N'555we', 2)
INSERT [dbo].[Orders] ([OrderId], [OrderDate], [OrderNumber], [OrderCustomerId]) VALUES (5, CAST(0x0000A2A600000000 AS DateTime), N'1234', 1)
INSERT [dbo].[Orders] ([OrderId], [OrderDate], [OrderNumber], [OrderCustomerId]) VALUES (6, CAST(0x0000A2C700000000 AS DateTime), N'555', 1)
SET IDENTITY_INSERT [dbo].[Orders] OFF
ALTER TABLE [dbo].[Orders] WITH CHECK ADD CONSTRAINT [FK_Orders_Customers] FOREIGN KEY([OrderCustomerId])
REFERENCES [dbo].[Customers] ([CustomerId])
GO
ALTER TABLE [dbo].[Orders] CHECK CONSTRAINT [FK_Orders_Customers]
GO
Then to access your Stored procedure that you want to get the Customer Email if he/she did orders less than 3 Orders.
Go to Server/Object explorer in SQL server.
Select your data base of name [Customer_OrdersDB].
Select "Programbility".
Select "StoredProcedures".
Right Click on your storedprocedure "GetCustomer_Mail" and then select Execute.
Try this:
SELECT c.email
FROM customer AS c
LEFT OUTER JOIN orders AS o ON c.customer_id = o.customer_id
GROUP BY c.email
HAVING SUM(o.line_qty) < 3
Related
I have a table called Items with these three fields:
Id (int)
ParentId(int)
NodeId (HierarchyId)
Id NodeId ParentId
2 / NULL
3 /120/1/ 1520
4 /1/ 2
ParentId and NodeId are basically duplicates as they both point to the parent. In the future, ParentId will be dropped in favor of the HierarchyId.
However, in the meantime, I need to ensure that they stay in sync, so I need to write a constraint to ensure this:
declare #id int = 4
DECLARE #result int = 0, #parentNodeId1 HierarchyId,#parentNodeId2 HierarchyId, #parentId int;
Select #parentNodeId1 = NodeId.GetAncestor(1), #parentId = parentId from Items where id = #id;
Select #parentNodeId2 = NodeId from Items where Id = #parentId;
if #parentNodeId1 = #parentNodeId2
Select #result = 1;
How do I write this as a constraint?
Update
I tried Damiens solution as suggested. It works to enforce the multi-column integrity on existing data. However, the NodeId can change from left to right in the hierarchy. For example a NodeId of /1/ can change to /3/. It's parent has not changed (the parent is /), so really the Foreign Key has not been in-validated. And this works for items with no children.
However, if an item has children, and the NodeId is changed, the database engine sees it as a violation of the Foreign Key and throws an error.
See this DB Fiddle: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=44637c2bbed80b8db3f305933798cdad
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[People](
[Id] [int] NOT NULL,
[ParentId] [int] NULL,
[NodeId] [hierarchyid] NOT NULL,
[_ParentNodeId] AS ([NodeId].[GetAncestor]((1))) PERSISTED,
CONSTRAINT [PK_People] PRIMARY KEY CLUSTERED
(
[Id] ASC,
[NodeId] 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
INSERT [dbo].[People] ([Id], [ParentId], [NodeId]) VALUES (1, NULL, N'/')
GO
INSERT [dbo].[People] ([Id], [ParentId], [NodeId]) VALUES (2, 1, N'/2/')
GO
INSERT [dbo].[People] ([Id], [ParentId], [NodeId]) VALUES (3, 1, N'/3/')
GO
INSERT [dbo].[People] ([Id], [ParentId], [NodeId]) VALUES (4, 2, N'/2/1/')
GO
INSERT [dbo].[People] ([Id], [ParentId], [NodeId]) VALUES (5, 4, N'/2/1/1.1/')
GO
ALTER TABLE [dbo].[People] WITH CHECK ADD CONSTRAINT [FK_People_Parent] FOREIGN KEY([ParentId], [_ParentNodeId])
REFERENCES [dbo].[People] ([Id], [NodeId])
GO
ALTER TABLE [dbo].[People] CHECK CONSTRAINT [FK_People_Parent]
GO
Update People set NodeId = N'/2/1/2/' where Id = 5--Works
Update People set NodeId = N'/2/2/' where Id = 4 --Error
If we can add another column, a foreign key constraint can enforce this:
create table T(
Id int not null,
NodeId hierarchyid,
ParentId int,
_ParentNodeId as NodeId.GetAncestor(1) persisted,
constraint PK_T primary key (Id,NodeId),
constraint FK_T_Parent foreign key (ParentId,_ParentNodeId) references T (Id,NodeId)
)
(I'm using the PK as the FK target, but any unique constraint will do if, say, Id is the current PK and you want to keep that)
I've prefixed the new column name with _. That's my convention for "I'm adding this column for my purposes in enforcing integrity. I don't expect anybody else to ever even look in it".
I want the row which have max id. i need the rows which have id 2 and there.
My tables
please create tables using below script.
/****** Object: Table [dbo].[Customers] Script Date: 03/07/2017 14:48:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customers](
[CustomerID] [bigint] IDENTITY(1,1) NOT NULL,
[Name] [nchar](10) NULL,
CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED
(
[CustomerID] 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].[Instalments] Script Date: 03/07/2017 14:48:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Instalments](
[id] [int] IDENTITY(1,1) NOT NULL,
[Amount] [int] NULL,
[Date] [date] NULL,
[CustomerID] [bigint] NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[id] 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 IDENTITY_INSERT [dbo].[Customers] ON
INSERT [dbo].[Customers] ([CustomerID], [Name]) VALUES (1, N'Muddassir ')
INSERT [dbo].[Customers] ([CustomerID], [Name]) VALUES (2, N'Irshad ')
SET IDENTITY_INSERT [dbo].[Customers] OFF
SET IDENTITY_INSERT [dbo].[Instalments] ON
INSERT [dbo].[Instalments] ([id], [Amount], [Date], [CustomerID]) VALUES (1, 500, CAST(N'2014-09-30' AS Date), 1)
INSERT [dbo].[Instalments] ([id], [Amount], [Date], [CustomerID]) VALUES (2, 600, CAST(N'2015-09-30' AS Date), 1)
INSERT [dbo].[Instalments] ([id], [Amount], [Date], [CustomerID]) VALUES (3, 800, CAST(N'2014-09-30' AS Date), 2)
SET IDENTITY_INSERT [dbo].[Instalments] OFF
My query
This is my query that i am using.
SELECT a.CustomerID,a.[Name],b.Amount,b.Date,b.id from Customers as a
left join Instalments as b On b.CustomerID=a.CustomerID
My Result
this is the result of my query.
CustomerID Name Amount Date id
1 Muddassir 500 2014-09-30 1
1 Muddassir 600 2015-09-30 2
2 Irshad 800 2014-09-30 3
What result i want?
but i want below result. i want all the rows which have max id only
CustomerID Name Amount Date id
1 Muddassir 600 2015-09-30 2
2 Irshad 800 2014-09-30 3
Try This
SELECT CustomerID
,[Name]
,Amount
,[Date]
,id
FROM (
SELECT a.CustomerID
,a.[Name]
,b.Amount
,b.DATE
,b.id
,Row_NUmber() OVER (
PARTITION BY a.CustomerID ORDER BY b.DATE DESC
) AS Rno
FROM Customers AS a
LEFT JOIN Instalments AS b ON b.CustomerID = a.CustomerID
) DT
WHERE DT.Rno = 1
Result
CustomerID Name Amount Date id
1 Muddassir 600 2015-09-30 2
2 Irshad 800 2014-09-30 3
are you sure you don't need always the most recent Instalments for each Customer?
This would be:
SELECT a.CustomerID
,a.Name
,b.Amount
,b.Date
,b.id
FROM Customers AS a
LEFT JOIN Instalments AS b
ON b.CustomerID=a.CustomerID
AND b.Date = (SELECT MAX(Date)
FROM Instalments T
WHERE T.CustomerID = b.CustomerID
)
You could use MAX() to get the highest ID in a subquery and compare it with the current ID of Instalments.
Try this:
SELECT a.CustomerID,a.[Name],b.Amount,b.Date,b.id FROM Customers AS a
LEFT JOIN Instalments AS b ON b.CustomerID=a.CustomerID
WHERE b.id = (SELECT MAX(id) FROM Instalments AS i WHERE i.CustomerID = a.CustomerID);
I have three tables, table 1, table 2 and table 3. Table 1 records all the existing records, and table 2 records the delta (new updates) to be applied to table 1.
Table 3 is the resultant table.
Table 1 and 3 structure: ID is the primary key
ID, date, location, age, count
Table 2 structure: ID is the primary key
ID, date, location, age, count, ChangeType
Table 2 records new update values only for fields that changed in table 1.
For example:
Table 1
1, 03/03/2017, A, 11, 1
2, 01/03/2017, B, 39, 1
3, 01/01/2017, D, 1, 1
Table 2
2, 03/03/2017,NULL, NULL,2, Update
1, NULL, CC, NULL, NULL, Update
Therefore table 3 should be
1, 03/03/2017, CC, 11, 1
2, 03/03/2017, B, 39, 2
3, 01/01/2017, D, 1, 1
Any suggestions would be appreciated.
GO
/****** Object: Table [dbo].[Table_1] Script Date: 03/03/2017 10:41:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_1](
[ID] [int] NOT NULL,
[date] [date] NULL,
[location] [nvarchar](50) NULL,
[age] [int] NULL,
[count] [int] NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Table_2] Script Date: 03/03/2017 10:41:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_2](
[ID] [int] NOT NULL,
[date] [date] NULL,
[location] [nvarchar](50) NULL,
[age] [int] NULL,
[count] [int] NULL,
[ChangeTyppe] [nvarchar](10) NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Table_3] Script Date: 03/03/2017 10:41:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_3](
[ID] [int] NOT NULL,
[date] [date] NULL,
[location] [nvarchar](50) NULL,
[age] [int] NULL,
[count] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Table_1] ([ID], [date], [location], [age], [count]) VALUES (1, CAST(0x863C0B00 AS Date), N'A', 11, 1)
GO
INSERT [dbo].[Table_1] ([ID], [date], [location], [age], [count]) VALUES (2, CAST(0x843C0B00 AS Date), N'B', 39, 1)
GO
INSERT [dbo].[Table_1] ([ID], [date], [location], [age], [count]) VALUES (3, CAST(0x493C0B00 AS Date), N'D', 1, 1)
GO
INSERT [dbo].[Table_2] ([ID], [date], [location], [age], [count], [ChangeTyppe]) VALUES (2, CAST(0x863C0B00 AS Date), NULL, NULL, 2, N'Update')
GO
INSERT [dbo].[Table_2] ([ID], [date], [location], [age], [count], [ChangeTyppe]) VALUES (1, NULL, N'CC', NULL, NULL, N'Update')
GO
If all you need is a one time thing, then this should work.
Left Join the two tables on the primary key and take the value from T2 if it is not null. Take the value from T1 if the value from 2 was null.
Coalesce will return the first value which is not null.
The values from T2 will be null if the row did not exist in T2 or if the value in T2 was null - per ID.
INSERT dbo.Table_3
( ID, date, location, age, count )
SELECT t1.ID ,
[date] = COALESCE(t2.date, t1.date) ,
[location] = COALESCE(t2.location, t1.location) ,
[age] = COALESCE(t2.age, t1.age) ,
[count] = COALESCE(t2.count, t1.count)
FROM dbo.Table_1 t1
LEFT OUTER JOIN dbo.Table_2 t2 ON t2.ID = t1.ID
I am a new web developer and I am developing a simple training management system which provides the users with quizzes. The system developed using ASP.NET and MS SQLServer. Now,
I need to come up with a query that shows the percentage of participation of each division in all the offered safety quizzes (which means quizzes with IsSent = true).
I have the following database design:
Employee Table: Username, Name, DivisionCode
Divisions Table: SapCode, Divison
Quiz Table: QuizID, Title, Description, IsSent
UserQuiz: UserQuizID, QuizID, DateTimeComplete, Username
(DivisionCode is a foreign key to the SapCode. IsSent is a flag to indicate to the quizzes that have been offered and sent to the users to participate in them.)
For example, If I have four divisions; A, B, C and D, and I have around 23 quizzes have been sent to the employees in those divisions. Since each division has a specific percentage of participation in each quiz. My query should show the overall percentage of participation in all offered quizzes for each division. So the result should not be broken down with respect to each quiz.
So how to do that?
And here's the schema of the database with its data:
USE [Test]
GO
/****** Object: Table [dbo].[Divisions] Script Date: 08/03/2012 19:36:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Divisions](
[SapCode] [nvarchar](50) NOT NULL,
[Division] [varchar](50) 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
INSERT [dbo].[Divisions] ([SapCode], [Division]) VALUES (N'1', N'A')
INSERT [dbo].[Divisions] ([SapCode], [Division]) VALUES (N'2', N'B')
INSERT [dbo].[Divisions] ([SapCode], [Division]) VALUES (N'3', N'C')
/****** Object: Table [dbo].[Quiz] Script Date: 08/03/2012 19:36:09 ******/
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](50) NOT NULL,
[Description] [varchar](50) NOT NULL,
[IsSent] [bit] NOT 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
SET IDENTITY_INSERT [dbo].[Quiz] ON
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description], [IsSent]) VALUES (1, N'Quiz I', N'Test', 1)
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description], [IsSent]) VALUES (2, N'Quiz II', N'Test test', 1)
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description], [IsSent]) VALUES (3, N'Quiz III', N'TEST TEST', 0)
SET IDENTITY_INSERT [dbo].[Quiz] OFF
/****** Object: Table [dbo].[Employee] Script Date: 08/03/2012 19:36:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Employee](
[Usename] [nvarchar](50) NOT NULL,
[Name] [varchar](50) NOT NULL,
[DivisionCode] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[Usename] 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
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'John12', N'John A', N'1')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'John13', N'John B', N'1')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'John15', N'John C', N'3')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Maria12', N'Maria A', N'3')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Rony14', N'Rony A', N'2')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Tid52', N'Tid A', N'3')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Tim12', N'Tim A', N'1')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Tim15', N'Tim B', N'2')
/****** Object: Table [dbo].[UserQuiz] Script Date: 08/03/2012 19:36:09 ******/
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] [datetime] NOT NULL,
[Score] [float] NOT NULL,
[Username] [nvarchar](50) 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
SET IDENTITY_INSERT [dbo].[UserQuiz] ON
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (1, 1, CAST(0x0000A07900000000 AS DateTime), 100, N'John12')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (2, 1, CAST(0x0000A07900000000 AS DateTime), 50, N'Tim12')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (3, 1, CAST(0x0000A07B00000000 AS DateTime), 100, N'Rony14')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (4, 1, CAST(0x0000A07900000000 AS DateTime), 0, N'Tim15')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (5, 1, CAST(0x0000A07900000000 AS DateTime), 100, N'Tid52')
SET IDENTITY_INSERT [dbo].[UserQuiz] OFF
/****** Object: ForeignKey [FK_Employee_Divisions] Script Date: 08/03/2012 19:36:09 ******/
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: 08/03/2012 19:36:09 ******/
ALTER TABLE [dbo].[UserQuiz] WITH CHECK ADD CONSTRAINT [FK_UserQuiz_Employee] FOREIGN KEY([Username])
REFERENCES [dbo].[Employee] ([Usename])
GO
ALTER TABLE [dbo].[UserQuiz] CHECK CONSTRAINT [FK_UserQuiz_Employee]
GO
/****** Object: ForeignKey [FK_UserQuiz_Quiz] Script Date: 08/03/2012 19:36:09 ******/
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]
GO
UPDATE:
The results should be like this:
Division ************* Overall Percentage
A **************** 80
B **************** 60
C **************** 50
And the overall percentage is the total of all percent completion of each division in each quiz. For instance, the percent completion for division A in Quiz#1 = 40%, and in Quiz#2 = 60% and in Quiz#3 = 90%, the overall percentage that should be shown by this query is the total of all the of them divided by the total number of sent quizzes (which is 3). I hope I am clear and the concept is obvious.
UPDATE #2:
I am still struggling with it but I came up with a query that shows the total number of employees and participants in each quiz for each division. And here's the query:
SELECT COUNT(dbo.Employee.Usename) AS [Total Number of Employees], COUNT(dbo.UserQuiz.Username) AS [Total Number of Participants], dbo.Divisions.Division,
dbo.Quiz.Title
FROM dbo.Divisions INNER JOIN
dbo.Employee ON dbo.Divisions.SapCode = dbo.Employee.DivisionCode INNER JOIN
dbo.UserQuiz ON dbo.Employee.Usename = dbo.UserQuiz.Username INNER JOIN
dbo.Quiz ON dbo.UserQuiz.QuizID = dbo.Quiz.QuizID
WHERE (dbo.Quiz.IsSent = 1)
GROUP BY dbo.Divisions.Division, dbo.Quiz.Title
What should I do to improve it and get what I need?
The following query may do what you want. I calculates the number of employees in each division, multiplies this by the number of quizzes. It then divides the number actually taken by this total:
select de.Division, de.numemployees, de.numemployees*q.numquizzes as qe_combos,
numquizzestaken/1.0*de.numemployees*q.numquizzes as proportion
from (select d.Division, count(*) as numemployees
from Employee e join
Division d
on e.DivisionCode = d.SapCode
group by d.Division
) de left outer join
(select d.Division, count(*) as numquizzestaken
from Employee e join
Division d
on e.DivisionCode = d.SapCode join
UserQuiz uq
on e.UserName = uq.UserName join
Quiz q
on uq.QuidId = q.QuizId and
q.issent = true
group by de.Division
) dq
on de.division = dq.division cross join
(select count(*) as numquizes
from Quiz q
where isSent = true
) q
I am a new web developer and I am developing a simple training management system which provides the users with quizzes. The system developed using ASP.NET and MS SQLServer. Now,
I need to come up with a query that shows the percentage of participation of each division in all the offered safety quizzes (which means quizzes with IsSent = true).
I have the following database design:
Employee Table: Username, Name, DivisionCode
Divisions Table: SapCode, Divison
Quiz Table: QuizID, Title, Description, IsSent
UserQuiz: UserQuizID, QuizID, DateTimeComplete, Username
(DivisionCode is a foreign key to the SapCode. IsSent is a flag to indicate to the quizzes that have been offered and sent to the users to participate in them.)
For example, If I have four divisions; A, B, C and D, and I have around 23 quizzes have been sent to the employees in those divisions. Since each division has a specific percentage of participation in each quiz. My query should show the overall percentage of participation in all offered quizzes for each division. So the result should not be broken down with respect to each quiz.
The desired result that I am looking for it:
Division ************* Overall Percentage
A **************** 80
B **************** 60
C **************** 50
And the overall percentage is the total of all percent completion of each division in each quiz. For instance, the percent completion for division A in Quiz#1 = 40%, and in Quiz#2 = 60% and in Quiz#3 = 90%, the overall percentage that should be shown by this query is the total of all the of them divided by the total number of sent quizzes (which is 3). I hope I am clear and the concept is obvious.
So how to do that?
And here's the schema of the database with its data:
USE [Test]
GO
/****** Object: Table [dbo].[Divisions] Script Date: 08/03/2012 19:36:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Divisions](
[SapCode] [nvarchar](50) NOT NULL,
[Division] [varchar](50) 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
INSERT [dbo].[Divisions] ([SapCode], [Division]) VALUES (N'1', N'A')
INSERT [dbo].[Divisions] ([SapCode], [Division]) VALUES (N'2', N'B')
INSERT [dbo].[Divisions] ([SapCode], [Division]) VALUES (N'3', N'C')
/****** Object: Table [dbo].[Quiz] Script Date: 08/03/2012 19:36:09 ******/
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](50) NOT NULL,
[Description] [varchar](50) NOT NULL,
[IsSent] [bit] NOT 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
SET IDENTITY_INSERT [dbo].[Quiz] ON
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description], [IsSent]) VALUES (1, N'Quiz I', N'Test', 1)
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description], [IsSent]) VALUES (2, N'Quiz II', N'Test test', 1)
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description], [IsSent]) VALUES (3, N'Quiz III', N'TEST TEST', 0)
SET IDENTITY_INSERT [dbo].[Quiz] OFF
/****** Object: Table [dbo].[Employee] Script Date: 08/03/2012 19:36:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Employee](
[Usename] [nvarchar](50) NOT NULL,
[Name] [varchar](50) NOT NULL,
[DivisionCode] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED
(
[Usename] 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
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'John12', N'John A', N'1')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'John13', N'John B', N'1')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'John15', N'John C', N'3')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Maria12', N'Maria A', N'3')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Rony14', N'Rony A', N'2')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Tid52', N'Tid A', N'3')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Tim12', N'Tim A', N'1')
INSERT [dbo].[Employee] ([Usename], [Name], [DivisionCode]) VALUES (N'Tim15', N'Tim B', N'2')
/****** Object: Table [dbo].[UserQuiz] Script Date: 08/03/2012 19:36:09 ******/
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] [datetime] NOT NULL,
[Score] [float] NOT NULL,
[Username] [nvarchar](50) 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
SET IDENTITY_INSERT [dbo].[UserQuiz] ON
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (1, 1, CAST(0x0000A07900000000 AS DateTime), 100, N'John12')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (2, 1, CAST(0x0000A07900000000 AS DateTime), 50, N'Tim12')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (3, 1, CAST(0x0000A07B00000000 AS DateTime), 100, N'Rony14')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (4, 1, CAST(0x0000A07900000000 AS DateTime), 0, N'Tim15')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (5, 1, CAST(0x0000A07900000000 AS DateTime), 100, N'Tid52')
SET IDENTITY_INSERT [dbo].[UserQuiz] OFF
/****** Object: ForeignKey [FK_Employee_Divisions] Script Date: 08/03/2012 19:36:09 ******/
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: 08/03/2012 19:36:09 ******/
ALTER TABLE [dbo].[UserQuiz] WITH CHECK ADD CONSTRAINT [FK_UserQuiz_Employee] FOREIGN KEY([Username])
REFERENCES [dbo].[Employee] ([Usename])
GO
ALTER TABLE [dbo].[UserQuiz] CHECK CONSTRAINT [FK_UserQuiz_Employee]
GO
/****** Object: ForeignKey [FK_UserQuiz_Quiz] Script Date: 08/03/2012 19:36:09 ******/
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]
GO
And here's the query:
SELECT COUNT(DISTINCT dbo.UserQuiz.Username) AS [Total Number of Participants], dbo.Divisions.DivisionShortcut, dbo.Quiz.Title
FROM dbo.employee INNER JOIN
dbo.UserQuiz ON dbo.employee.Username = dbo.UserQuiz.Username INNER JOIN
dbo.Quiz ON dbo.UserQuiz.QuizID = dbo.Quiz.QuizID INNER JOIN
dbo.Divisions ON dbo.employee.DivisionCode = dbo.Divisions.SapCode
WHERE (dbo.Quiz.IsSent = 1)
GROUP BY dbo.Divisions.DivisionShortcut, dbo.Quiz.Title, dbo.UserQuiz.QuizID
ORDER BY dbo.UserQuiz.QuizID DESC
What should I do to improve it and get what I need?