SQL Server self referencing query - sql

Please consider the following:
CREATE DATABASE TEST
USE TEST
CREATE TABLE Student
(
StudentID INT IDENTITY
PRIMARY KEY ,
FirstName NVARCHAR(50) ,
LastName NVARCHAR(50)
)
CREATE TABLE StudentComponent
(
StudentComponentID INT IDENTITY
PRIMARY KEY ,
StudentID INT FOREIGN KEY REFERENCES dbo.Student(StudentID) ,
ComponentName NVARCHAR(50) ,
ComponentRef NVARCHAR(50) ,
ComponentType NCHAR(2)
)
CREATE TABLE Component
(
ComponentID INT IDENTITY
PRIMARY KEY ,
StudentComponentID INT FOREIGN KEY REFERENCES dbo.StudentComponent(StudentComponentID) ,
ComponentName NVARCHAR(50) ,
ComponentRef NVARCHAR(50) ,
ComponentType NCHAR(2)
)
I have 3 tables
Student
StudentComponent
Component
split out into dimensions
CREATE TABLE DimClass
(ClassDwKey INT,
ClassName NVARCHAR(50),
ClassRef NVARCHAR(50))
CREATE TABLE DimCollege
(CollegeDwKey INT,
CollegeName NVARCHAR(50),
CollegeRef NVARCHAR(50))
CREATE TABLE DimSubject
(SubjectDwKey INT,
SubjectName NVARCHAR(50),
SubjectRef NVARCHAR(50))
CREATE TABLE DimStudent
(StudentDwKey INT,
StudentName NVARCHAR(50))
INSERT INTO
CREATE TABLE FactAcademicEvent
(StudentDwKey int, ClassDwKey int, CollegeDwKey int, SubjectDwKey INT)
With relationship in same order between them (Student --> StudentComponent --> Component). I have split the components out into their own dimensions, DimClass, DimCollege, DimSubject (split by componenttype field, = 'CL' for class, 'SU' for subject, 'CO' for college etc. I am trying to load a fact table getting my surrogate keys from my dimensions and produce a row with the following
StudentDwKey (from dimstudent), ClassDwKey, CollegeDwKey, SubjectDwKey. There is a link between the dimensions and the component table ComponentKey, which links to student through studentcomponent table.
StudentComponent and Component are basically the same, except StudentComponent references students so has more rows.
Any ideas?

EDIT :
Complete change based on OP's edits and comments.
SELECT
s.StudentID,
MAX(dim_s.StudentDwKey ) AS StudentDwKey,
MAX(dim_cl.ClassDwKey ) AS ClassDwKey,
MAX(dim_su.SubjectDwKey) AS SubjectDwKey,
MAX(dim_co.CollegeDwKey) AS CollegeDwKey
FROM
Student AS s
LEFT JOIN
StudentComponent AS sc
ON sc.StudentID = s.StudentID
LEFT JOIN
dimStudent AS dim_s
ON dim_s.StudentName = s.StudentName -- or whatever is a reliable join
LEFT JOIN
dimClass AS dim_cl
ON dim_cl.ClassRef = sc.ComponentRef
AND sc.ComponentType = 'CL'
LEFT JOIN
dimSubject AS dim_su
ON dim_su.SubjectRef = sc.ComponentRef
AND su.ComponentType = 'SU'
LEFT JOIN
dimCollege AS dim_co
ON dim_co.CollegeRef = sc.ComponentRef
AND sc.ComponentType = 'CO'
GROUP BY
s.StudentID

Keep the student details in the Student table (which you have done) and the component details in the Component table (which you have not done) and use the StudentComponent table to link them together. Something like this:
CREATE DATABASE TEST
USE TEST
CREATE TABLE Student
(
StudentID INT IDENTITY
PRIMARY KEY ,
FirstName NVARCHAR(50) ,
LastName NVARCHAR(50)
)
CREATE TABLE StudentComponent
(
StudentComponentID INT IDENTITY
PRIMARY KEY ,
StudentID INT FOREIGN KEY REFERENCES dbo.Student(StudentID) ,
ComponentID INT FOREIGN KEY REFERENCES dbo.Component(ComponentID),
)
CREATE TABLE Component
(
ComponentID INT IDENTITY
PRIMARY KEY ,
ComponentName NVARCHAR(50) ,
ComponentRef NVARCHAR(50) ,
ComponentType NCHAR(2)
)

Related

Select the row with the max value from a table where sum is calculated

I'm trying to find out how can I extract the rows with the highest value on Suma column from a table which I did with this script:
SELECT specializare,
Count(codprocedura) AS NrProceduri,
Sum(pret) AS Suma
FROM (SELECT p.pret AS Pret,
fp.specializaredoctor AS Specializare,
fp.codprocedura AS CodProcedura
FROM proceduri p
INNER JOIN fisepacienti fp
ON fp.codpacienti = p.codproc)intermediar
GROUP BY intermediar.specializare
The DB tables can be created with this:
create table Pacienti(
CodP int not null primary key,
Nume varchar(50),
Prenume varchar(50),
Descriere varchar(50),
Varsta int,
DataNasterii varchar(50)
);
create table Proceduri(
CodProc int not null primary key,
Nume varchar(50),
Descriere varchar(50),
Pret int
);
create table FisePacienti(
PRIMARY KEY(CodPacienti, CodProcedura),
CodPacienti int FOREIGN KEY REFERENCES Pacienti(CodP),
CodProcedura int FOREIGN KEY REFERENCES Proceduri(CodProc),
Data varchar(50),
NumeDoctor varchar(50),
PrenumeDoctor varchar(50),
SpecializareDoctor varchar(50),
VechimeDoctor varchar(50)
);
You can use TOP (1) WITH TIES:
SELECT TOP (1) WITH TIES fp.specializare,
Count(fp.codprocedura) AS NrProceduri,
Sum(p.pret) AS Suma
FROM proceduri p JOIN
fisepacienti fp
ON fp.codpacienti = p.codproc
GROUP BY fp.specializare
ORDER BY SumA DESC;
Note that a subquery is not needed for the aggregation.

Invalid Object name 'Subject_Marks'

CREATE TABLE Subject_Marks
(
Marks_ID int primary key,
Maths_Score int,
Science_Score int,
Social_Score int,
English_Score int,
SUPW_Score int,
Student_ID int not null
);
INSERT into Subject_Marks VALUES
(1,1001, 50, 99,98,45,57);
NOT ABLE TO JOIN THIS TABLE WITH OTHER TABLE SHOWN BELOW.
CREATE TABLE Student_Data
(
Student_ID int IDENTITY(1001,1) PRIMARY KEY,
Student_Name VARCHAR(20) NOT NULL,
Student_Address VARCHAR(100),
Student_Phone bigint,
Student_Email VARCHAR(30),
college_id int NOT NULL
);
Since Student_ID is the key providing the relationship, you need to use this in a join. So, you need to construct a join like below for SQL Server:
select sd.* , sm.*
from Student_Data sd
inner join Subject_Marks sm on sm.Student_ID = sd.Student_ID

If exists update the XML column or insert into new row in reference table

If exists data into parent table then update the child table on XML column based on the reference id, other wise insert into row.
CREATE TABLE Person
(
PersonId INT CONSTRAINT PK_Person_PersonId PRIMARY KEY,
Name VARCHAR(50),
SubMittedDate DATETIME,
SubmittedBy INT,
RejectedDate DATETIME,
RejectedBy INT
)
INSERT INTO Person VALUES(1, 'Sai', GETDATE(),1,null,null)
CREATE TABLE PersonXML
(
PersonXMLId INT IDENTITY(1,1) CONSTRAINT PK_PersonXML_PersonId PRIMARY KEY,
PersonId INT CONSTRAINT FK_PersonXML_Person FOREIGN KEY REFERENCES Person(PersonId),
Name VARCHAR(50),
PersonHistory XML
)
INSERT INTO PersonXML(PersonId,Name,PersonHistory )
SELECT PersonId
,Name
,(SELECT PersonId
,Name
,SubMittedDate
,SubmittedBy
,ISNULL(RejectedDate,0) AS RejectedDate
,ISNULL(RejectedBy, 0) AS RejectedBy
FROM Person FOR XML PATH('PersonHistory') )
FROM Person
SELECT * FROM Person
SELECT * FROM PersonXML
Whenever i Update Person Table in RejectedDate, RejectedBy Column then those changes has to reflect in PersonXML table on PersonHistory column automatically could anyone please find me way to achieve it.
UPDATE Person SET RejectedDate = GETDATE(), RejectedBy= 100 WHERE PersonId = 1
DECLARE #PersonId int,#RejectedDate datetime,#RejectedBy int
SET #PersonId=1
SET #RejectedDate=Getdate()+1
SET #RejectedBy=105
CREATE TABLE Person
(
PersonId INT CONSTRAINT PK_Person_PersonId PRIMARY KEY,
Name VARCHAR(50),
SubMittedDate DATETIME,
SubmittedBy INT,
RejectedDate DATETIME,
RejectedBy INT
)
INSERT INTO Person VALUES(1, 'Sai', GETDATE(),1,null,null)
CREATE TABLE PersonXML
(
PersonXMLId INT IDENTITY(1,1) CONSTRAINT PK_PersonXML_PersonId PRIMARY KEY,
PersonId INT CONSTRAINT FK_PersonXML_Person FOREIGN KEY REFERENCES Person(PersonId),
Name VARCHAR(50),
PersonHistory XML
)
INSERT INTO PersonXML(PersonId,Name,PersonHistory )
SELECT PersonId
,Name
,(SELECT PersonId
,Name
,SubMittedDate
,SubmittedBy
,ISNULL(RejectedDate,0) AS RejectedDate
,ISNULL(RejectedBy, 0) AS RejectedBy
FROM Person FOR XML PATH('PersonHistory') )
FROM Person
IF Exists(SELECT * FROM Person WHERE PersonId=#PersonId)
BEGIN
UPDATE Person
SET
RejectedDate =#RejectedDate ,RejectedBy=#RejectedBy
WHERE PersonId=#PersonId
UPDATE PersonXML
SET PersonHistory=
(SELECT PersonId
,Name
,SubMittedDate
,SubmittedBy
,ISNULL(RejectedDate,#RejectedDate) AS RejectedDate
,ISNULL(RejectedBy,#RejectedBy) AS RejectedBy
FROM Person FOR XML PATH('PersonHistory') )WHERE PersonId=#PersonId
END
ELSE
BEGIN
INSERT INTO Person
Select #PersonId,'', GETDATE(),1,#RejectedDate,#RejectedBy
END
SELECT * FROM Person
SELECT * FROM PersonXML

Sql query join and aggragation at the same time

How can I Select the Sum of the ProjectPossibilityRatio column from the ProjectCompletion table given the ProjectID? I couldnt find sum:
SELECT pp.ProjectID,
pp.ProjectAlias,
Sum(pd.projectpossibilityratio)
FROM project pp
INNER JOIN projectcompletion pc
ON pp.projectId = pc.projectID
JOIN projectprocedure pd
ON pd.projectprocedureID = pc.projectprocedureID
GROUP BY pd.projectpossibilityratio
Here are the table definitions:
Create TABLE ProjectType(
ProjectTypeID int identity(1,1),
ProjectTypeName nvarchar(100),
Description nvarchar(200),
primary key(ProjectTypeID)
)
CREATE TABLE Project(
ProjectID int identity(1,1),
ProjectAlias nvarchar(100),
ProjectTypeID int foreign key references ProjectType(ProjectTypeID),
MandatedCompanyID int foreign key references Company(CompanyID),
Iscurrent bit,
BuySide bit,
TeamID int foreign key references WorkTeam(TeamID),
ProjectTurnOver varchar(100),
ProjectStartDate Datetime
primary key(ProjectID))
CREATE TABLE ProjectProcedure(
ProjectProcedureID int identity(1,1),
ProjectProcedureName nvarchar(100),
ProjectProcedureDescription nvarchar(200),
ProjectType int foreign key references ProjectType(ProjectTypeID),
ProjectProcedurePosition int,
ProjectProcedureTime smallint,
ProjectPossibilityRatio int,
Primary Key(ProjectProcedureID))
CREATE TABLE ProjectCompletion(
ProjectID int foreign key references Project(ProjectID),
ProjectProcedureID int foreign key references ProjectProcedure(ProjectProcedureID),
StartDate Datetime,
IsCompletedDate Datetime
Primary Key(ProjectID,ProjectProcedureID)
)
Add all the column names that you are selecting to the group by list.
Try this:
SELECT pp.ProjectID,pp.ProjectAlias,Sum(pd.projectpossibilityratio)
FROM project pp INNER JOIN projectcompletion pc ON pp.projectId=pc.projectID
JOIN projectprocedure pd ON pd.projectprocedureID=pc.projectprocedureID
GROUP BY pp.ProjectID,pp.ProjectAlias
And I agree with LeftyX, you should go back and accept answers

How to select IDs from a table if two conditions in other tables match

I am developing a user feedback system using ASP.NET and C#. I have multiple tables and am trying to populate dropdown lists so that the feedback can be filtered.
My tables:
CREATE TABLE tblModules
(
Module_ID nvarchar(10) PRIMARY KEY,
Module_Title nvarchar(MAX) NOT NULL
);
CREATE TABLE tblQuestions
(
Q_ID int PRIMARY KEY IDENTITY(1,1),
Question_Text varchar(1000) NOT NULL
);
CREATE TABLE tblFeedback
(
Submission_ID int PRIMARY KEY IDENTITY(1,1),
Username varchar(100) NOT NULL,
Domain varchar(50) NOT NULL,
DateTime_Submitted datetime NOT NULL
Module_ID nvarchar(10)
FOREIGN KEY (Module_ID) REFERENCES tblModules (Module_ID);
);
CREATE TABLE tblAnswers
(
Q_ID int NOT NULL,
Submission_ID int NOT NULL,
Answer_Text varchar(max),
FOREIGN KEY (Q_ID) REFERENCES tblQuestions(Q_ID),
FOREIGN KEY (Submission_ID) REFERENCES tblFeedback(Submission_ID)
);
I have two dropdown lists. First one is populated with all modules from a table. The second needs to be populated with Questions from tblQuestions but only if any answers to it exist (therefore if the Question ID 'Q_ID' exists in tblAnswers).
I can get the selectedModuleID from the first dropdown list. I have a List of all Questions referenced by Q_ID in tblAnswers. How do I crossreference this list with the module ID?
Each feedback submission gets a Submission ID and Module ID.
You want:
questions that have answers
questions that have a module parent (via tblfeedback)
So, my guess at what you want:
SELECT
*
FROM
tblQuestions Q
WHERE
EXISTS (SELECT *
FROM
tblAnswers A
JOIN
tblFeedback F ON A.Submission_ID = F.Submission_ID
WHERE
Q.Q_ID = A.Q_ID AND F.Module_ID = #moduleID)
This should do the trick...
SELECT Q_ID, Question_Text tblQuestions a
WHERE EXISTS (SELECT NULL FROM tblAnswers a WHERE a.Q_ID = q.Q_ID)