Temat: [TSQL] Dynamiczy SQL
to co potrzebujesz to są najprostsze z możliwych zapytań...
tutaj masz kod tworzący nową bazę egzamin i tabele z przykładowymi danymi, piszesz że to psełdo kod bo faktycznie brakuje tam paru rzeczy między innymi wiązania pomiędzy wzorem odpowiedzi a pytaniami (przyjąłem że to wiązanie będzie po id ale w rozwiązaniu pordukcyjnym proponował bym jednak powiązać to przez osobne pole...)
test jest przeprowadzony na 300 arkuszach testów wypełnionych losowymi odpowiedziami (nie brałem pod uwagę filtrowania sprawdzonych arkuszy i braku odpowiedzi która powinna być też błędem)
kod na przykładowe dane :
set nocount on;
Use master;
if DB_ID('Egzamin') IS NULL
CREATE DATABASE Egzamin;
GO
USE Egzamin;
GO
SET NOCOUNT ON;
IF OBJECT_ID('NUM', 'U') IS NOT NULL
DROP TABLE DBO.NUM;
CREATE TABLE NUM(N INT NOT NULL PRIMARY KEY);
IF OBJECT_ID('Formularz','U') IS NOT NULL
DROP TABLE DBO.Formularz;
CREATE TABLE [dbo].[Formularz](
[id.formularz] [int] IDENTITY(1,1) NOT NULL,
[nr.formularza] [nchar](10) NULL,
[p.1] [bit] NULL,
[p.2] [bit] NULL,
[p.3] [bit] NULL,
[stan] [bit] NULL
) ON [PRIMARY]
IF OBJECT_ID('Bledy','U') IS NOT NULL
DROP TABLE DBO.Bledy;
CREATE TABLE [dbo].[Bledy](
[id.bledy] [int] IDENTITY(1,1) NOT NULL,
[bp.1] [bit] NULL,
[bp.2] [bit] NULL,
[bp.3] [bit] NULL,
[poziomBledu] [int] NULL
) ON [PRIMARY]
DECLARE @MAX AS INT , @RC AS INT;
SET @MAX = 1000;
SET @RC =1;
INSERT INTO DBO.NUM(N) VALUES (1);
WHILE @RC *2 <=@MAX
BEGIN
INSERT INTO DBO.NUM(N) SELECT N+@RC FROM DBO.NUM;
SET @RC = @RC *2;
END;
INSERT INTO DBO.NUM(N)
SELECT N+@RC FROM NUM WHERE N+@RC <= @MAX;
GO
DECLARE @ILOSC_TESTOW AS INT, @ZIARNO as INT
SET @ILOSC_TESTOW = 300
SET @ZIARNO = 10
INSERT INTO DBO.Formularz([nr.formularza] ,[p.1] ,[p.2] ,[p.3] ,[stan])
SELECT ('TEST NR' + CONVERT(nvarchar(10), N)) AS [nr.formularza],
CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [P.1],
CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [P.2],
CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [P.3],
CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [STAN]
FROM DBO.NUM
WHERE N <= @ILOSC_TESTOW
INSERT INTO [dbo].[Bledy]([bp.1] ,[bp.2] ,[bp.3] ,[poziomBledu])
SELECT CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [PB.1],
CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [PB.2],
CASE WHEN ((abs(CHECKSUM(newid())+2147483649)/4294967296) * @ZIARNO) >=4 THEN 0 ELSE 1 END AS [PB.3],
NULL
FROM DBO.NUM
WHERE N<= @ILOSC_TESTOW
kod funkcji sprawdzającej...
USE [Egzamin]
GO
/****** Object: UserDefinedFunction [dbo].[SF_SPRAWDZ_TETS] Script Date: 2013-09-03 23:31:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
CREATE FUNCTION [dbo].[SF_SPRAWDZ_TETS]
(
-- Add the parameters for the function here
@num_testu as int
)
RETURNS INT
AS
BEGIN
DECLARE @WYNIK AS INT =0, @licznik_b as int;
-- Add the T-SQL statements to compute the return value here
SELECT @WYNIK = CASE WHEN F.[p.1] = B.[bp.1] THEN @wynik + 0 ELSE @wynik + 1 END
,@WYNIK = CASE WHEN F.[p.2] = B.[bp.2] THEN @WYNIK + 0 ELSE @WYNIK + 1 END
,@WYNIK = CASE WHEN F.[p.3] = B.[bp.3] THEN @WYNIK + 0 ELSE @WYNIK + 1 END
FROM DBO.Formularz F LEFT JOIN DBO.Bledy B ON F.[id.formularz] = B.[id.bledy]
WHERE F.[id.formularz] = @num_testu
-- Return the result of the function
RETURN @WYNIK
END
GO
no i kod zwykłego selecta w którym otrzymujesz ilość błędów w danym pytaniu..
/****** Script for SelectTopNRows command from SSMS ******/
SELECT TOP 1000 F.[id.formularz]
,f.[nr.formularza]
,[dbo].[SF_SPRAWDZ_TETS] (f.[id.formularz]) as bledy
,f.[p.1],b.[bp.1]
,f.[p.2],b.[bp.2]
,f.[p.3],b.[bp.3]
,f.[stan]
FROM [Egzamin].[dbo].[Formularz] F
join Egzamin.dbo.Bledy B on f.[id.formularz]=b.[id.bledy]
where f.stan = 0
GO
jak będziesz miała pytania to pisz...
i tak jak napisałem lepiej chyba będzie ci rozbić to na osobne pytania, bo będą powiązane z konkretnym wzorem odpowiedzi ustalonym raz i jak będziesz chciała np. pomieszać pytania do testu losowo to nie będziesz tworzyć dużej tabeli wzoru odpowiedzi... chyba wiesz o co mi chodzi... nie ma też problemu żeby zamiast selecta którego wstawiłem zrobić procedurę która sprawdzi arkusze, zrobi update w kolumnie stan i zmieni poziomBledu...
nie potrzeba widoków tabel tymczasowych i tym podobnych...
a i jeszcze jedno... nie przejmuj się tabelą num bo powstała ona tylko w celu utworzenia przykładowych danych
tak rzuciłem okiem tylko jeszcze na próbie porównania 30 tyś pytań u mnie na kompie trwało to 1:16 s...
Ten post został edytowany przez Autora dnia 03.09.13 o godzinie 23:57