Unable to figure out SQL query for a task - sql-server

I have database with following tables
Login table:
CREATE TABLE [dbo].[Login]
(
[username] [nvarchar](100) NOT NULL,
[password] [nvarchar](50) NOT NULL,
[user_type] [nchar](10) NOT NULL,
[id] [int] IDENTITY(1,1) NOT NULL,
[isDelete] [bit] NOT NULL,
)
Test table:
CREATE TABLE [dbo].[Test]
(
[TestId] [int] IDENTITY(1,1) NOT NULL,
[TestName] [nvarchar](100) NOT NULL,
[UserId] [int] NOT NULL,
[isDelete] [bit] NOT NULL,
)
Questions table:
CREATE TABLE [dbo].[Questions]
(
[Qid] [int] IDENTITY(1,1) NOT NULL,
[Tid] [int] NOT NULL,
[Qtype] [int] NOT NULL,
[Question] [nvarchar](max) NOT NULL,
[isDelete] [bit] NULL,
)
Login.id is a foreign key and references Test.UserId
Test.TestId is foreign key and references Questions.Tid
My question is: I want to fetch Login.username, Test.TestName and the number of questions per test, e.g. I want all tests present and number of questions per test (even if 0).
I tried the following query
select
Test.TestId, Test.TestName, COUNT(Questions.Tid) as 'No.Of Questions'
from
Test, Questions
where
Test.TestId = Questions.Tid and
Questions.isDelete <> 'true'
group by
TestId, TestName
but this query only returns the tests for which at least single question is present in questions table.
I want all tests compulsory and then questions per test.

you need to use Left outer join
select T.TestId,T.TestName,COUNT(Q.Tid) as [No.Of Questions]
from Test t
Left Join Questions q
On Q.isDelete<>'true'
and T.TestId=Q.Tid
group by TestId,TestName
your current syntax works like Inner Join. Thats the reason you are getting tests which is not having any questions

Related

SQL Server, one table with data -> insert into table with a foreign key, and that foreign key table has to be filled also

For a school project I have made a .csv import via C# and imported all the data from the file into a table containing only strings. We have to do some validation on the imported code using SQL server which I have already done. The table I have imported my data into looks like this:
CREATE TABLE [dbo].[StoreData]
(
[StoreName] [nvarchar](max) NULL,
[Street] [nvarchar](max) NULL,
[StreetNumber] [nvarchar](max) NULL,
[City] [nvarchar](max) NULL,
[ZipCode] [nvarchar](max) NULL,
[TelephoneNumber] [nvarchar](max) NULL,
[Country] [nvarchar](max) NULL
)
With this table filled, I have to Insert this data into the [Stores] table :
CREATE TABLE [dbo].[Stores]
(
[Id] [nvarchar](450) NOT NULL, <- GUID
[Name] [nvarchar](85) NOT NULL,
[CountryCode] [nvarchar](max) NOT NULL,
[AddressId] [nvarchar](450) NULL <- FK to [Address] Table
)
And here is my problem, the [Stores] contains a FK to the [Addresses] table:
CREATE TABLE [dbo].[Addresses]
(
[Id] [nvarchar](450) NOT NULL, <- GUID
[Street] [nvarchar](100) NOT NULL,
[HouseNumber] [nvarchar](4) NOT NULL,
[Addition] [nvarchar](10) NULL,
[ZipCode] [nvarchar](6) NOT NULL,
[City] [nvarchar](85) NOT NULL,
[SeriesIndicationStart] [int] NOT NULL,
[SeriesIndicationEnd] [int] NOT NULL
CONSTRAINT [PK_Addresses] PRIMARY KEY CLUSTERED
)
So now I have [StoreData] that contains the data I have to put in [Addresses] and in [Stores], and I have to keep in mind that the FK has to be set in [Stores]. This is our first database semester, and I am clueless, and tomorrow is the deadline..
I hope someone can help me out.. thanks in advance!

CTE “Types don't match between the anchor and the recursive part”

I know this question has already been answered a lot, but I can't find the mistake.
I'm getting the following error:
Types don't match between the anchor and the recursive part in column "Parent" of recursive query "GroupHierarchy".
This is the query:
WITH GroupHierarchy (UserGroupName, UserGroupID, IsGroup, Parent, Level)
AS
(
-- Anchor member definition
SELECT ug.UserGroupName, ug.UserGroupID, ug.IsGroup, CAST('' as nvarchar(MAX)) as Parent, 0 AS Level
FROM KnowledgeVaultMaster.dbo.UserGroup AS ug
WHERE ug.IsGroup = 0
UNION ALL
-- Recursive member definition
SELECT ug.UserGroupName, ug.UserGroupID, ug.IsGroup, CAST(gh.UserGroupName as nvarchar(MAX)) as Parent, Level + 1
FROM KnowledgeVaultMaster.dbo.UserGroup AS ug
JOIN KnowledgeVaultMaster.dbo.UserGroupGroup AS ugg
ON ug.UserGroupID = ugg.ParentUserGroupId
INNER JOIN GroupHierarchy gh
ON ugg.UserGroupId = gh.UserGroupID
)
-- Statement that executes the CTE
SELECT UserGroupName, UserGroupID, IsGroup, Parent, Level
FROM GroupHierarchy
The original column UserGroup.UserGroupName is nvarchar(255), not null
EDIT: These are the tables (constraints and defaults omitted):
CREATE TABLE [dbo].[UserGroup](
[UserGroupID] [bigint] IDENTITY(1,1) NOT NULL,
[UserGroupName] [nvarchar](255) NOT NULL,
[SystemName] [nvarchar](50) NULL,
[UserPassword] [nvarchar](50) NULL,
[Salt] [nvarchar](20) NULL,
[IsGroup] [tinyint] NOT NULL,
[SuperUser] [bit] NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](100) NULL,
[Email] [nvarchar](100) NULL,
[CreateDate] [datetime] NOT NULL,
[CreateUserID] [bigint] NOT NULL,
[AuthType] [int] NOT NULL,
[Active] [bit] NOT NULL
) ON [PRIMARY] GO
CREATE TABLE [dbo].[UserGroupGroup](
[UserGroupId] [bigint] NOT NULL,
[ParentUserGroupId] [bigint] NOT NULL
) ON [PRIMARY] GO
Finally I found the problem. The database was imported with compatibility level SQL Server 2012 (110).
I changed it to SQL Server 2016 (130) and now the cte works.

Fastest way to record count using filter in SQL Server

I am using SQL Server version 2012. I have a table which has more than 10 million rows. I have to count records using a SQL filter.
My query is this:
select count(*)
from reconcil
where tenantid = 101
which is taking more than 5 minutes for 5 millions records.
Is there any fastest way to count records?
Reconcil table structure is
CREATE TABLE [dbo].[RECONCIL]
(
[AckCode] [nvarchar](50) NULL,
[AckExpireTime] [int] NULL,
[AckFileName] [nvarchar](255) NULL,
[AckKey] [int] NULL,
[AckState] [int] NULL,
[AppMsgKey] [nvarchar](30) NULL,
[CurWrkActID] [nvarchar](50) NULL,
[Date_Time] [datetime] NULL,
[Direction] [nvarchar](1) NULL,
[ErrorCode] [nvarchar](50) NULL,
[FGLOGKEY] [int] NOT NULL,
[FolderID] [int] NULL,
[FuncGCtrlNo] [nvarchar](14) NULL,
[INLOGKEY] [int] NULL,
[InputFileName] [nvarchar](255) NULL,
[IntCtrlNo] [nvarchar](14) NULL,
[IsAssoDataPresent] [nvarchar](1) NULL,
[JobState] [int] NULL,
[LOGDATA] [nvarchar](max) NULL,
[MessageID] [nvarchar](25) NULL,
[MessageState] [int] NULL,
[MessageType] [int] NULL,
[NextWrkActID] [nvarchar](50) NULL,
[NextWrkHint] [nvarchar](20) NULL,
[NONFAERRORLOG] [nvarchar](max) NULL,
[NumberOfBytes] [int] NULL,
[NumberOfSegments] [int] NULL,
[OutputFileName] [nvarchar](255) NULL,
[Priority] [nvarchar](1) NULL,
[ReceiverID] [nvarchar](30) NULL,
[RecNo] [int] NULL,
[RecordID] [int] IDENTITY(1,1) NOT NULL,
[RelationKey] [int] NULL,
[SEGLOG] [nvarchar](max) NULL,
[SenderID] [nvarchar](30) NULL,
[ServerID] [nvarchar](255) NULL,
[Standard] [int] NULL,
[TenantID] [int] NULL,
[TPAgreementKey] [int] NULL,
[TSetCtrlNo] [nvarchar](35) NULL,
[UserKey1] [nvarchar](255) NULL,
[UserKey2] [nvarchar](255) NULL,
[UserKey3] [nvarchar](255) NULL,
CONSTRAINT [RECONCIL_PK]
PRIMARY KEY CLUSTERED ([RecordID] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Unless you materialized the count, this non-clustered index on TenentID will provide better performance because it is narrower than the clustered primary key index and will scan only the matching rows:
CREATE INDEX idx ON [dbo].[RECONCIL](TenantID);
If performance of the aggregate query with this index isn't acceptable, you could create an indexed view with the count. The indexed view will provide the fastest performance for this query but will incur additional costs for storage and index maintenance for inserts and deletes. Also, queries that modify the table must have required SET options for indexed views. Those costs may be justified if the count query is executed often.
SQL Server can use the indexed view automatically in Enterprise (or Developer) editions even if not directly referenced in the query as long as the optimizer can match the semantics of the query using the view. In lesser editions, you'll need to query the indexed view directly and specify the NOEXPAND hint.
CREATE VIEW dbo.VW_RECONCIL_COUNT
WITH SCHEMABINDING
AS
SELECT
TenantID
, COUNT_BIG(*) AS TenentRowCount
FROM [dbo].[RECONCIL]
GROUP BY TenantID;
GO
CREATE UNIQUE CLUSTERED INDEX cdx ON dbo.VW_RECONCIL_COUNT(TenantID);
GO
--Enterprise Edition can use the view index automatically
SELECT COUNT_BIG(*) AS TenentRowCount
FROM [dbo].[RECONCIL]
WHERE TenantID = 101
GROUP BY TenantID;
GO
--other editions require the view to be specified plus the NOEXPAND hint
SELECT TenentRowCount
FROM dbo.VW_RECONCIL_COUNT WITH (NOEXPAND)
WHERE TenantID = 101;
GO
As being suggested, create an index or even partition your table by tenantId if you have so many items. This way you would have one data file per partition which increases performance.
select count(tenantid)
from reconcil
where tenantid = 101 group by tenantid ;
not sure but try using this.

Stored procedure query for selecting values

I have a Test table
CREATE TABLE [dbo].[Test](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[TestName] [nvarchar](50) NOT NULL,
[UserId] [int] NOT NULL,
[isDelete] [bit] NOT NULL,
and Questions table as
CREATE TABLE [dbo].[Questions](
[Qid] [int] IDENTITY(1,1) NOT NULL,
[Tid] [int] NOT NULL,
[Qtype] [int] NOT NULL,
[Question] [nvarchar](max) NOT NULL,
[isDelete] [bit] NULL,
Questions table stores all the questions for each test with Tid as foreign key.
I want to write a stored procedure to fetch TestName, TestId and number of questions in each test in a single stored procedure. But I am unable to get this.
You can write the stored procedure as:
CREATE PROCEDURE [dbo].[procGetNumberofQuestionsForTest]
AS
BEGIN
SELECT T.[TestId], T.[TestName], COUNT(Q.[Qid]) AS NumberOfQuestions
FROM [dbo].[Test] T
JOIN [dbo].[Questions] Q ON Q.Tid = T.TestId
GROUP BY T.[TestId], T.[TestName]
END
If you want to get the result for specific Test, then pass the parameter as #TestId INT and add the WHERE clause as WHERE T.[TestId] = #TestId before the GROUP BY.
Try this (table create, insert, proc creation and execution included);
CREATE TABLE [dbo].[Test](
[TestId] [int] IDENTITY(1,1) NOT NULL,
[TestName] [nvarchar](50) NOT NULL,
[UserId] [int] NOT NULL,
[isDelete] [bit] NOT NULL)
go
CREATE TABLE [dbo].[Questions](
[Qid] [int] IDENTITY(1,1) NOT NULL,
[Tid] [int] NOT NULL,
[Qtype] [int] NOT NULL,
[Question] [nvarchar](max) NOT NULL,
[isDelete] [bit] NULL
)
go
insert into [dbo].[Test]
values('test #1',1,0)
go
insert into [dbo].[Questions]
values(1,1,'what is life',0)
go
create proc dbo.MyInfo
as
select
t.TestName,
t.TestId,
[No Questions]=COUNT(q.Qid)
from
[dbo].[Test] t
inner join
[dbo].[Questions] q on t.TestId=q.Qid
group by
t.TestName,
t.TestId
go
exec dbo.MyInfo
go

Display corresponding name based on ID SQL select query

I have 2 tables
tbl_jobs
CREATE TABLE [dbo].[tbl_jobs]
(
[JobID] [int] IDENTITY(1,1) NOT NULL,
[JobType] [nvarchar](50) NOT NULL,
[RequestID] [int] NOT NULL,
[AssignTo] [int] NOT NULL,
[FromOrgID] [int] NOT NULL,
[ToOrgID] [int] NOT NULL,
[Ammount] [nvarchar](50) NOT NULL,
[JobStatus] [nvarchar](50) NOT NULL,
[Remark] [nvarchar](50) NULL,
[strOwner] [nvarchar](50) NOT NULL,
[dbTstamp] [datetime2](7) NOT NULL,
CONSTRAINT [PK_tbl_jobs]
PRIMARY KEY CLUSTERED ([JobID] ASC)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tbl_jobs] WITH CHECK
ADD CONSTRAINT [FK_tbl_jobs_tbl_orgs]
FOREIGN KEY([FromOrgID]) REFERENCES [dbo].[tbl_orgs] ([OrgID])
GO
ALTER TABLE [dbo].[tbl_jobs] CHECK CONSTRAINT [FK_tbl_jobs_tbl_orgs]
GO
ALTER TABLE [dbo].[tbl_jobs] WITH CHECK
ADD CONSTRAINT [FK_tbl_jobs_tbl_orgs1]
FOREIGN KEY([ToOrgID]) REFERENCES [dbo].[tbl_orgs] ([OrgID])
GO
tbl_orgs
CREATE TABLE [dbo].[tbl_orgs]
(
[OrgID] [int] IDENTITY(1,1) NOT NULL,
[OrgName] [nvarchar](50) NOT NULL,
[OrgTele] [nvarchar](50) NULL,
[OrgEmail] [nvarchar](50) NULL,
[OrgArea] [nvarchar](50) NOT NULL,
[OrgCity] [nvarchar](50) NOT NULL,
[OrgLocation] [nvarchar](50) NOT NULL,
[OrgType] [nvarchar](50) NOT NULL,
[OrgStatus] [nvarchar](50) NOT NULL,
[strOwner] [nvarchar](50) NOT NULL,
[dbTStamp] [datetime2](7) NOT NULL,
CONSTRAINT [PK_tbl_orgs]
PRIMARY KEY CLUSTERED ([OrgID] ASC)
) ON [PRIMARY]
GO
I need to get most of the tbl_jobs columns and corresponding tbl_orgs.OrgName for tbl_jobs.FromOrgID & tbl_jobs.ToOrgID.
If I choose tbl_orgs.orgname, I don't get the proper results.
I am stuck here. What type of query should I use to get the result.?
You're joining two times to the same table instance. You should click on "add table" and add tbl_orgs one more time and join "FromOrgID" to one instance of it and "ToOrgID" to the other one. Otherwise the join doesn't make sense unless "FromOrgID" and "ToOrgID" are equal.

Resources