How to come up with statistics that shows the total number of quizzes, total number of participants? - asp.net

I am developing a simple web application that provides the users with quizzes. since I am new to ASP.NET world, I am following the How to build Quiz Engine Video series on ASP.net website. My database design is to similar to the design used in these videos.
This is the link of the first video:
Everything works fine with me, but I want now to develop a query that helps me to display a statistics to the Admin which shows:
Total number of quizzes in the system
Total number of participants in each quiz
Total number of participants in general in daily basis, weekly basis, monthly basis and yearly basis (if possible)
To clarify the last point, I want the admin to see the following:
total number of participant druing last week was: ......
total number of taken quizzes during last week was: .........
total number of taken quizzes during last month was: .........
I think something like this is very useful to know the usage of the system and to show the management how the system is efficient in the copmany.
The sechma of the database:
CREATE TABLE [dbo].[Quiz](
[QuizID] [int] IDENTITY(1,1) NOT NULL,
[Title] [varchar](max) 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
SET IDENTITY_INSERT [dbo].[Quiz] ON
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description]) VALUES (6, N'Safety', N'General Safety Test')
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description]) VALUES (7, N'my title', N'my description')
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description]) VALUES (9, N'General Safety Quiz2', N'Testing')
INSERT [dbo].[Quiz] ([QuizID], [Title], [Description]) VALUES (10, N'General Safety Quiz3', N'Testing #2')
SET IDENTITY_INSERT [dbo].[Quiz] OFF
/****** Object: Table [dbo].[Question] Script Date: 11/17/2011 00:44:38 ******/
CREATE TABLE [dbo].[Question](
[QuestionID] [int] IDENTITY(1,1) NOT NULL,
[Question] [varchar](max) NOT NULL,
[Answer1] [varchar](max) NOT NULL,
[Answer2] [varchar](max) NOT NULL,
[Answer3] [varchar](max) NOT NULL,
[Answer4] [varchar](max) NOT NULL,
[CorrectAnswer] [tinyint] NOT NULL,
[AnswerExplanation] [varchar](max) NULL,
[QuestionOrder] [tinyint] NOT NULL,
[QuizID] [int] NOT NULL,
CONSTRAINT [PK_Question] PRIMARY KEY CLUSTERED
(
[QuestionID] 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].[Question] ON
INSERT [dbo].[Question] ([QuestionID], [Question], [Answer1], [Answer2], [Answer3], [Answer4], [CorrectAnswer], [AnswerExplanation], [QuestionOrder], [QuizID]) VALUES (4, N'What is your name?', N'Mohammed ', N'Ali', N'Hassan', N'Husain', 1, N'My Name', 1, 6)
INSERT [dbo].[Question] ([QuestionID], [Question], [Answer1], [Answer2], [Answer3], [Answer4], [CorrectAnswer], [AnswerExplanation], [QuestionOrder], [QuizID]) VALUES (7, N'What is the definition of Safety?', N'Being Safe', N'Being in danger', N'Be careful', N'be careless', 1, N'Nothing', 1, 9)
INSERT [dbo].[Question] ([QuestionID], [Question], [Answer1], [Answer2], [Answer3], [Answer4], [CorrectAnswer], [AnswerExplanation], [QuestionOrder], [QuizID]) VALUES (8, N'What is the definition of Safety? ', N'Being Safe', N'Being Careless', N'Being Careful', N'Being in Dangerous', 1, N'Nothing to say', 1, 10)
SET IDENTITY_INSERT [dbo].[Question] OFF
/****** Object: Table [dbo].[UserQuiz] Script Date: 11/17/2011 00:44:38 ******/
CREATE TABLE [dbo].[UserQuiz](
[UserQuizID] [int] NULL,
[QuizID] [int] NOT NULL,
[DateTimeComplete] [smalldatetime] NOT NULL,
[Score] [tinyint] NOT NULL,
[Username] [nvarchar](256) NOT NULL
) ON [PRIMARY]
GO
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (NULL, 6, CAST(0x9F8F02D8 AS SmallDateTime), 100, N'SMP\ALMARHMS')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (NULL, 6, CAST(0x9F8F02E3 AS SmallDateTime), 50, N'SMP\ALMARHMS')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (NULL, 6, CAST(0x9F8F0333 AS SmallDateTime), 50, N'SMP\ALMARHMS')
INSERT [dbo].[UserQuiz] ([UserQuizID], [QuizID], [DateTimeComplete], [Score], [Username]) VALUES (NULL, 7, CAST(0x9F8F0335 AS SmallDateTime), 100, N'SMP\ALMARHMS')
By help from one of the guys here in this great community, I came up with one query that shows the number of participants in each quiz. This is the query:
SELECT Q.QuizID, Q.Title, COUNT(*) AS Users
FROM dbo.UserQuiz AS UQ
INNER JOIN dbo.Quiz AS Q ON Q.QuizID = UQ.QuizID
GROUP BY Q.QuizID, Q.Title
Now I need to modify it or to come up withe new query that gives me the above three points. How can I do that?

If you want to count for the last 7 days and the last 30 days, you could use something like this:
-- Count of Participants in the last 7 days
SELECT COUNT(DISTINCT Q.UserName)
FROM dbo.UserQuiz Q
WHERE DateTimeComplete >= DATEADD(dd, -7, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
-- Count quizzes taken in the last 7 days
SELECT COUNT(Q.QuizID)
FROM dbo.UserQuiz Q
WHERE Q.DateTimeComplete >= DATEADD(dd, -7, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
-- Count quizzes taken in the last 30 days
SELECT COUNT(Q.QuizID)
FROM dbo.UserQuiz Q
WHERE Q.DateTimeComplete >= DATEADD(dd, -30, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0))
Note that if you want to count for calendar weeks and calendar months then you need to do a bit more work to filter the proper starting and ending date filters.
EDIT: Fixed the query syntax (1st answer posted without running it in SSMS) also I didn't notice at first that the UserQuiz.UserQuizID is nullable. This column is therefore not what I would have expected it to be.
EDIT #2: As per OP's request, these three statistics can also be retrieved in a single query using sub-selects. Sub-selects are necessary because of differences in either the filter criteria or the aggregations involved in counting each statistic (or both).
-- Combine three stats into one query using sub-selects...
SELECT
(SELECT COUNT(DISTINCT Q.UserName)
FROM dbo.UserQuiz Q
WHERE DateTimeComplete >= DATEADD(dd, -7, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)))
as ParticipantsLast7Days,
(SELECT COUNT(Q.QuizID)
FROM dbo.UserQuiz Q
WHERE Q.DateTimeComplete >= DATEADD(dd, -7, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)))
as QuizzesLast7Days,
(SELECT COUNT(Q.QuizID)
FROM dbo.UserQuiz Q
WHERE Q.DateTimeComplete >= DATEADD(dd, -30, DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)))
as QuizzesLast30Days

Related

How to make something similar as an if statement in Sqlite?

This is my SQLite file:
CREATE TABLE IF NOT EXISTS COTXE ( /*Table to create the cars*/
matricula VARCHAR(7) NOT NULL PRIMARY KEY, /*CarPlate*/
marca INTEGER, /*Brand*/
color INTEGER /*Color*/
);
CREATE TABLE IF NOT EXISTS PLASA ( /*Table to crate all the sites of the parking*/
pos INTEGER NOT NULL PRIMARY KEY, /*Number of the parkingsite*/
superficie INTEGER, /*How many m² it has*/
ocupada BOOL /*If its empty or not (0 = empty)*/
);
CREATE TABLE IF NOT EXISTS APARCAR ( /*Table to park a car in a site of the parking*/
pos_plaça INTEGER, /*Number of the parking site*/
matricula VARCHAR(7), /*Carplate*/
data_in DEFAULT CURRENT_TIMESTAMP, /*Date when it enters the parking*/
data_out DEFAULT NULL, /*Date when it leaves the parking*/
PRIMARY KEY (matricula, data_in),
FOREIGN KEY (pos_plaça) REFERENCES PLASA(pos),
FOREIGN KEY (matricula) REFERENCES COTXE(matricula)
);
/*Inserts to add cars and parking sites*/
INSERT INTO COTXE VALUES ('9882JPX', 0, 0);
INSERT INTO COTXE VALUES ('1111DDD', 4, 9);
INSERT INTO COTXE VALUES ('2222SSS', 8, 8);
INSERT INTO COTXE VALUES ('3333FFF', 3, 5);
INSERT INTO PLASA (superficie, ocupada) VALUES (50, 0);
INSERT INTO PLASA (superficie, ocupada) VALUES (34, 0);
INSERT INTO PLASA (superficie, ocupada) VALUES (24, 0);
I've got a little problem and its when i try to add, for example the first car two times in the same parking site without leaving in any of those it adds again the same car in the same parking site that should be impossible, i drop here an example:
sqlite> INSERT INTO APARCAR (pos_plaça, matricula) VALUES (1, '9882JPX');
sqlite> UPDATE PLASA SET ocupada = 1 WHERE pos = 1;
sqlite> INSERT INTO APARCAR (pos_plaça, matricula) VALUES (1, '9882JPX');
sqlite> SELECT * FROM APARCAR;
pos_plaça matricula data_in data_out
---------- ---------- ------------------- ----------
1 9882JPX 2022-03-17 17:41:24
1 9882JPX 2022-03-17 17:41:26
So i'm asking you guys if any of you know how to condition the INSERT INTO and before adding the car in that parking site, check if its full.
Sorry for my bad english and explanations.

SQLite composite key for a table between two tables

I am trying to Connect Three tables. Two of them have Primary Keys which the Third is supposed to link to. I need this inbetween as it is linked to a fourth (but this Works fine). The code I have written is as follows:
CREATE TABLE CUSTOMERS(
CUSTOMER_ID INT(10) NOT NULL,
SURNAME CHAR(50) NOT NULL,
NAME CHAR(50) NOT NULL,
PRIMARY KEY (CUSTOMER_ID)
);
CREATE TABLE WORKSHOP(
WORKSHOP_ID INT(10) NOT NULL,
NAME CHAR(100) NOT NULL,
CHAIN_NAME CHAR(100),
CHAIN_ID INT(10),
CONTRACT_WORKSHOP CHAR(5) NOT NULL,
PRIMARY KEY (WORKSHOP_ID, CHAIN_ID)
);
CREATE TABLE CAR_DAMAGE(
DAMAGE_ID INT(10) NOT NULL,
CUSTOMER_ID INT(10) NOT NULL,
DATE INT(20) NOT NULL,
PLACE CHAR(128) NOT NULL,
WORKSHOP_ID INT(10) NOT NULL,
PRIMARY KEY (DAMAGE_ID, CUSTOMER_ID, WORKSHOP_ID, DATE, PLACE),
FOREIGN KEY (CUSTOMER_ID) REFERENCES CUSTOMERS (CUSTOMER_ID),
FOREIGN KEY (WORKSHOP_ID) REFERENCES WORKSHOP (WORKSHOP_ID)
);
INSERT INTO CUSTOMERS VALUES (1, "OLSEN", "TROND");
INSERT INTO CUSTOMERS VALUES (2, "JOHNSEN", "FELIX");
INSERT INTO CUSTOMERS VALUES (3, "SVINDAL", "AKSEL");
INSERT INTO CUSTOMERS VALUES (4, "BJORGEN", "MARIT");
INSERT INTO CUSTOMERS VALUES (5, "SVENDSON", "LISA");
INSERT INTO WORKSHOP VALUES (1, "BERTEL", "MOLLER", 1, "YES");
INSERT INTO WORKSHOP VALUES (2, "OLOF", "OLOF AUTO", 3, "NO");
INSERT INTO WORKSHOP VALUES (3, "J-AUTO", "MOLLER", 1, "YES");
INSERT INTO WORKSHOP VALUES (4, "SPEED", "BIRGER N. HAUG", 2, "YES");
INSERT INTO WORKSHOP VALUES (5, "RELAX AUTO", "MOLLER", 1, "YES");
INSERT INTO CAR_DAMAGE VALUES (1, 1, 10102008, "HELLERUD", 1);
INSERT INTO CAR_DAMAGE VALUES (2, 2, 14032015, "JAR", 2);
INSERT INTO CAR_DAMAGE VALUES (3, 3, 24052016, "LOMMEDALEN", 3);
INSERT INTO CAR_DAMAGE VALUES (4, 4, 31102017, "FLAKTVEIT", 4);
INSERT INTO CAR_DAMAGE VALUES (5, 5, 08062016, "STOCKHOLM", 5);
However, the problem occur as I get the error "foriegn key mismatch - CAR_DAMAGE referencing WORKSHOP.
I am using SQLite as I am forced to use it, given by my University.
Table WORKSHOP has a composite primary key (WORKSHOP_ID, CHAIN_ID). Any foreign key referencing that table must be a composite foreign key, consisting of the same two fields. Hence, you would need to add CHAIN_ID to table WORKSHOP and change your foreign key declaration to something like:
FOREIGN KEY (WORKSHOP_ID, CHAIN_ID) REFERENCES WORKSHOP (WORKSHOP_ID, CHAIN_ID)
[More generally, your primary keys seem, based on the information given, more complex than they need to be: why not just have WORKSHOP_ID as PK of WORKSHOP and DAMAGE_ID as PK of CAR_DAMAGE? But maybe you have good reasons.]
Thank you. This Method worked. Hence, when I proceeded, a New problem occured. The table CAR_DAMAGE is linked to a fourth table (Called DAMAGE_INFORMATION), With the code:
CREATE TABLE DAMAGE_INFORMATION(
DAMAGE_ID INT(10) NOT NULL,
DAMAGE_TYPE CHAR(100) NOT NULL,
DAMAGE_SIZE CHAR(50) NOT NULL,
SPEND INT(10) NOT NULL,
FOREIGN KEY (DAMAGE_ID) REFERENCES CAR_DAMAGE (DAMAGE_ID)
);
And I receive the same error as earlier, i.e. Foreign key mismatch "DAMAGE_INFORMATION" referencing "CAR_DAMAGE".
Is it not allowed to make a combination of 3 tables to 1, With different primary keys? The primary key of CAR_DAMAGE is:
PRIMARY KEY (DAMAGE_KEY, CUSTOMER_ID, WORKSHOP_ID)

sqlite: update TableA with a max() from a joined table

I've been spoiled by years of PostgreSQL and am having a hard time adapting to sqlite's limited update syntax. I cobbled together a working query, but I'm hoping someone might know of a better way. (This isn't very pretty to look at and is the product of sqlite guiding me with error messages).
Scenario:
I have a standard association table setup: A, A2B, B
I want to update every record in A with the "latest" corresponding B (B is joined through the A2B association table, and the "latest" is a max function on a B column).
-- works
UPDATE t_a
SET id_latest_b = (
SELECT id_b FROM (
SELECT t_b.id as id_b,
max(t_b.timestamp_event),
t_a2b.id_a
FROM t_b
JOIN t_a2b
ON (t_b.id = t_a2b.id_b)
GROUP BY t_a2b.id_a
) q_inner
WHERE
t_a.id = q_inner.id_a
);
-- test data
CREATE TABLE t_b (id INT PRIMARY KEY, timestamp_event INT);
CREATE TABLE t_a (id INT PRIMARY KEY, id_latest_b INT REFERENCES t_b(id));
CREATE TABLE t_a2b (id_a REFERENCES t_a(id), id_b REFERENCES t_b(id), PRIMARY KEY (id_a, id_b));
INSERT INTO t_a VALUES (1, NULL);
INSERT INTO t_a VALUES (2, NULL);
INSERT INTO t_a VALUES (3, NULL);
INSERT INTO t_a VALUES (4, NULL);
INSERT INTO t_b VALUES (1, 10);
INSERT INTO t_b VALUES (2, 20);
INSERT INTO t_b VALUES (3, 30);
INSERT INTO t_a2b VALUES (1, 1);
INSERT INTO t_a2b VALUES (1, 2);
INSERT INTO t_a2b VALUES (2, 2);
INSERT INTO t_a2b VALUES (3, 1);
INSERT INTO t_a2b VALUES (3, 2);
INSERT INTO t_a2b VALUES (3, 3);
INSERT INTO t_a2b VALUES (4, 1);
INSERT INTO t_a2b VALUES (4, 4);
You can use ORDER BY to get the row with the largest value:
UPDATE t_a
SET id_latest_b = (SELECT t_b.id
FROM t_b
JOIN t_a2b ON t_b.id = t_a2b.id_b
WHERE t_a2b.id_a = t_a.id
ORDER BY t_b.timestamp_event DESC
LIMIT 1);

SQL Help Using NESTED SELECTION

Here's my table
CREATE TABLE emp (num INTEGER NOT NULL,
name VARCHAR(20) NOT NULL,
dept VARCHAR(20) NOT NULL,
salary INTEGER NOT NULL,
boss INTEGER NOT NULL,
PRIMARY KEY (num),
FOREIGN KEY (boss) REFERENCES emp (num)
);
INSERT INTO emp
VALUES ('1', 'PRESIDENT', 'gh', '10000', '1');
INSERT INTO emp
VALUES ('2', 'Bob', 'Slave', '6456', '3');
INSERT INTO emp
VALUES ('3', 'Matthew', 'M', '1', '1');
INSERT INTO emp
VALUES ('4', 'Marl', 'P', '534465', '2');
INSERT INTO emp
VALUES ('5', 'Apple', 'P', '554545646512', '2');
INSERT INTO emp
VALUES ('6', 'Roy', 'Slave', '125', '1');
INSERT INTO emp
VALUES ('7', 'Marth', 'Slave', '56456', '1');
INSERT INTO emp
VALUES ('8', 'Mart', 'Slave', '98', '3');
Here are my Queries:
SELECT * FROM emp;
SELECT * FROM emp
WHERE boss = (SELECT num FROM emp
WHERE num = boss) AND num != boss;
SELECT e1.num,e1.name FROM emp e1
WHERE
(SELECT e2.salary FROM emp e2
WHERE e2.boss = (SELECT e3.num FROM emp e3
WHERE e3.num = e3.boss) AND e2.num != e2.boss) < 98;
So the first output prints out everything as expected. The second output prints out: Matthew, Roy and Marth as expected.
But the final output prints out one.
This is a practice test question I was given
My goal is print the num and name of everyone working under the president who makes less than MIN of people who aren't working for the president.
I can calculate the MIN with the following code:
SELECT min(salary) FROM emp
WHERE boss != (SELECT num FROM emp
WHERE num = boss);
Ideally I want to replace 98 in the previous query with this statement, but I decided it would be best if I broke it down and tried one thing at a time.
Your problem is too many subqueries.
e2 is completely independent from e1; the e2 subquery returns all salaries of those working under the president; the comparison is then against the first value returned.
You could use a correlated subquery to tie e2 to e1, but you don't need a subquery at all:
SELECT e1.num,
e1.name
FROM emp AS e1
WHERE e1.boss = (SELECT e3.num
FROM emp AS e3
WHERE e3.num = e3.boss)
AND e1.num != e1.boss
AND e1.salary < 98;

Delete data using merge statement in Oracle

How to only delete data using merge using oracle...
I am using the below code:
Merge
into
target_table
using
source_tablle
on (...)
when matched
then delete
But I am getting an error "missing Keyword" at last line
Your MERGE at the end is missing the UPDATE clause.
Lets look at a sample MERGE
CREATE TABLE employee (
employee_id NUMBER(5),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
dept_no NUMBER(2),
salary NUMBER(10));
INSERT INTO employee VALUES (1, 'Dan', 'Morgan', 10, 100000);
INSERT INTO employee VALUES (2, 'Helen', 'Lofstrom', 20, 100000);
INSERT INTO employee VALUES (3, 'Akiko', 'Toyota', 20, 50000);
INSERT INTO employee VALUES (4, 'Jackie', 'Stough', 20, 40000);
INSERT INTO employee VALUES (5, 'Richard', 'Foote', 20, 70000);
INSERT INTO employee VALUES (6, 'Joe', 'Johnson', 20, 30000);
INSERT INTO employee VALUES (7, 'Clark', 'Urling', 20, 90000);
CREATE TABLE bonuses (
employee_id NUMBER, bonus NUMBER DEFAULT 100);
INSERT INTO bonuses (employee_id) VALUES (1);
INSERT INTO bonuses (employee_id) VALUES (2);
INSERT INTO bonuses (employee_id) VALUES (4);
INSERT INTO bonuses (employee_id) VALUES (6);
INSERT INTO bonuses (employee_id) VALUES (7);
COMMIT;
Now we have a sample data structure lets do some merging:
MERGE INTO bonuses b
USING (
SELECT employee_id, salary, dept_no
FROM employee
WHERE dept_no =20) e
ON (b.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET b.bonus = e.salary * 0.1
DELETE WHERE (e.salary < 40000)
;
So this command the MERGE syntax using the merge_update_clause:
MERGE INTO (table/view)
USING (table/view)
ON (condition)
WHEN MATCHED THEN
UPDATE SET (column..expression)
DELETE WHERE (condition)
I guess what I'm hinting at is that you are missing your UPDATE SET clause as well as the DELETE conditions. I recommend following up on the MERGE syntax.
**Edit:**SQLFiddle is back so here you go.

Resources