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
Related
What I'm trying to achieve is to check if a table exists:
if it exists, just truncate it
if it does not exist, create the table
Below is my code but I get an error.
Code:
--Check if table exists
IF EXISTS (SELECT * FROM sys.objects
WHERE object_id = OBJECT_ID(N'[dbo].[Com_SQL_Server_Agent_Monitor]')
AND type in (N'U'))
TRUNCATE TABLE [dbo].[Com_SQL_Server_Agent_Monitor]
ELSE
--Create table if not exist
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Com_SQL_Server_Agent_Monitor]
(
[job_id] [uniqueidentifier] NULL,
[originating_server] [nvarchar](30) NULL,
[name] [nvarchar](128) NULL,
[enabled] [tinyint] NULL,
[description] [nvarchar](512) NULL,
[start_step_id] [int] NULL,
[category] [nvarchar](128) NULL,
[owner] [nvarchar](128) NULL,
[notify_level_eventlog] [int] NULL,
[notify_level_email] [int] NULL,
[notify_level_netsend] [int] NULL,
[notify_level_page] [int] NULL,
[notify_email_operator] [nvarchar](128) NULL,
[notify_netsend_operator] [nvarchar](128) NULL,
[notify_page_operator] [nvarchar](128) NULL,
[delete_level] [int] NULL,
[date_created] [datetime] NULL,
[date_modified] [datetime] NULL,
[version_number] [int] NULL,
[last_run_date] [int] NULL,
[last_run_time] [int] NULL,
[last_run_outcome] [int] NULL,
[next_run_date] [int] NULL,
[next_run_time] [int] NULL,
[next_run_schedule_id] [int] NULL,
[current_execution_status] [int] NULL,
[current_execution_step] [nvarchar](128) NULL,
[current_retry_attempt] [int] NULL,
[has_step] [int] NULL,
[has_schedule] [int] NULL,
[has_target] [int] NULL,
[type] [int] NULL
) ON [PRIMARY]
GO
This is the error I get:
There is already an object named 'Com_SQL_Server_Agent_Monitor' in the database
Any ideas what I'm missing?
The biggest problem in your code is the fact that you have multiple SQL statements in your ELSE block - but they're not framed by a BEGIN ... END.
So really what you have right now is:
IF EXISTS (....)
TRUNCATE TABLE [dbo].[Com_SQL_Server_Agent_Monitor]
ELSE
SET ANSI_NULLS ON
-- these statements will be executed ALWAYS - no matter what the
-- IF EXISTS() check returns!
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Com_SQL_Server_Agent_Monitor]
......
So even if the table exists, and gets truncated - the SET QUOTED_IDENTIFIER ON and the CREATE TABLE statement will still be executed! That's why you're getting an error "table already exists".
What you need to do is:
IF EXISTS (....)
TRUNCATE TABLE [dbo].[Com_SQL_Server_Agent_Monitor]
ELSE
BEGIN
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
CREATE TABLE [dbo].[Com_SQL_Server_Agent_Monitor]
......
END
I have been tasked with getting some data out of another database not designed by me, so the design cannot be altered.
Looking at the data I need to join a table dynamically based on the value held in another table.
E.G
SELECT * FROM TableA LEFT JOIN TableB oN TableA.TBID = TableB.ID LEFT JOIN TableB.TableOffset AS C ON C.TableAID = TableA.ID
So table B has a column called TableOffset, this holds the name of the table that needs to be joined on as C
(I've tried to do an SQLFIDDLE but the site isn't working with SQL Server ATM)
The issue is there are 112 attribute tables where the data could be, so doing a left join for every one of them would slow down the query I imagine.
So based on the below I would need to get a result set of:
| TableAID | TableATitle | AttrTableA21 | AttrTableA22 |
|----------|-------------|--------------|--------------|
|1 |test | Name | 2019 |
|2 |test2 | Name 2 | 2016 |
Example SQL Code
CREATE TABLE [dbo].[TableA](
[ID] [int] NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[TableBID] [int] NOT NULL
);
CREATE TABLE [dbo].[TableB](
[ID] [int] NOT NULL,
[TableName] [nvarchar](100) NOT NULL
);
CREATE TABLE [dbo].[ATTR_A](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
CREATE TABLE [dbo].[ATTR_B](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
CREATE TABLE [dbo].[ATTR_C](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
CREATE TABLE [dbo].[ATTR_D](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
INSERT INTO TableA VALUES(1, 'test', 1);
INSERT INTO TableB VALUES(1, 'ATTR_C');
INSERT INTO ATTR_C VALUES (1, 1, 'Name', 2019);
INSERT INTO TableA VALUES(2, 'test2', 2);
INSERT INTO TableB VALUES (2, 'ATTR_A');
INSERT INTO ATTR_A VALUES (1, 2, 'Name 2', 2016);
```
You were told already, that this approach is the wrong one entirely. But if you have to stick with this, you might try this:
Your test scenario in a new database (carefull, if you use this database name already...)
USE master;
GO
CREATE DATABASE MyTestDb;
GO
USE MyTestDb;
GO
CREATE TABLE [dbo].[TableA](
[ID] [int] NOT NULL,
[Title] [nvarchar](100) NOT NULL,
[TableBID] [int] NOT NULL
);
CREATE TABLE [dbo].[TableB](
[ID] [int] NOT NULL,
[TableName] [nvarchar](100) NOT NULL
);
CREATE TABLE [dbo].[ATTR_A](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
CREATE TABLE [dbo].[ATTR_B](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
CREATE TABLE [dbo].[ATTR_C](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
CREATE TABLE [dbo].[ATTR_D](
[ID] [int] NOT NULL,
[TableAID] [int] NOT NULL,
[A21] [nvarchar](100) NOT NULL,
[A22] [int] NOT NULL
);
INSERT INTO TableA VALUES(1, 'test', 1);
INSERT INTO TableB VALUES(1, 'ATTR_C');
INSERT INTO ATTR_C VALUES (1, 1, 'Name', 2019);
INSERT INTO TableA VALUES(2, 'test2', 2);
INSERT INTO TableB VALUES (2, 'ATTR_A');
INSERT INTO ATTR_A VALUES (1, 2, 'Name 2', 2016);
GO
--I create an inlined table valued function where all attribute tables are returned as one set using UNION ALL
--The engine is smart enough, to avoid the call, if the parameter does not fit.
CREATE FUNCTION dbo.GetTheRightSet(#SetKey VARCHAR(10))
RETURNS TABLE
AS
RETURN
SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_A WHERE #SetKey='ATTR_A'
UNION ALL
SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_B WHERE #SetKey='ATTR_B'
UNION ALL
SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_C WHERE #SetKey='ATTR_C'
UNION ALL
SELECT ID,TableAID,A21,A22 FROM dbo.ATTR_D WHERE #SetKey='ATTR_D'
GO
--This is how to use it
SELECT TableA.*
,TableB.*
,TheSet.*
FROM TableA
LEFT JOIN TableB ON TableA.TableBID = TableB.ID
OUTER APPLY dbo.GetTheRightSet(TableB.TableName) TheSet
GO
--Clean up (carefull with real data)
USE master;
GO
DROP DATABASE MyTestDb;
I have a problem with this script
SET ANSI_NULLS ON
GO
IF NOT EXISTS (SELECT * FROM [sys].[tables]
WHERE [object_id] = OBJECT_ID(N'[dbo].[FactFinance]')
AND OBJECTPROPERTY([object_id], N'IsUserTable') = 1)
BEGIN
CREATE TABLE [dbo].[FactFinance]
(
[FinanceKey] [int] IDENTITY PRIMARY KEY NOT NULL,
[TimeKey] [int] NULL,
[OrganizationKey] [int] NULL,
[DepartmentGroupKey] [int] NULL,
[ScenarioKey] [int] NULL,
[AccountKey] [int] NULL,
[Amount] [float] NULL
) ON [PRIMARY];
END
GO
SET ANSI_NULLS OFF
GO
When I run this, I get this result:
but if I remove this line [Finance Key] [int] IDENTITY PRIMARY KEY NOT NULL, from the script, it works
I have created a partition table and trying to query the partition but not able to do so in sql server 2016. Could somebody tell me where I am going wrong
CREATE PARTITION FUNCTION [financialStatementPartition](datetime)
AS RANGE RIGHT FOR VALUES (N'2013-01-01T00:00:00.000', N'2014-01-01T00:00:00.000',
N'2015-01-01T00:00:00.000', N'2016-01-01T00:00:00.000',
N'2017-01-01T00:00:00.000')
GO
Table schema
CREATE TABLE [dbo].[FinancialStatementIds]
(
[financialCollectionId] [int] NOT NULL,
[companyId] [int] NOT NULL,
[dataItemId] [int] NOT NULL,
[dataItemName] [varchar](200) NULL,
[dataItemvalue] [decimal](18, 0) NULL,
[unittypevalue] [int] NULL,
[fiscalyear] [int] NULL,
[fiscalquarter] [int] NULL,
[periodenddate] [datetime] NULL,
[filingdate] [datetime] NULL,
[restatementtypename] [varchar](200) NULL,
[latestforfinancialperiodflag] [bit] NULL,
[latestfilingforinstanceflag] [bit] NULL,
[currencyconversionflag] [int] NULL,
[currencyname] [varchar](200) NULL,
[periodtypename] [varchar](200) NULL
)
Query
SELECT *
FROM dbo.FinancialStatementIds
WHERE $PARTITION.financialStatementPartition(periodenddate) = '2013-01-01T00:00:00.000'
Error
Conversion failed when converting the varchar value '2013-01-01T00:00:00.000' to data type int.
Use following query instead:
SELECT *
FROM dbo.FinancialStatementIds
WHERE periodenddate = '20130101'
Anyway, the table is still not partitioned properly. You need to apply Partition Scheme to connect the table and Partition function.
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