Order by performance issue on joined tables - sql-server

I have two tables: "Alarms" and "Devices" and a view "vwAlarms"
Alarms Table has 250K rows and Devices Table has only 50 rows.
vwAlarms is just join of two table.
my problems is when i add Top(x) and order by id desc to select * from vwAlarm it takes 10 seconds to execute query. however the same query runs quickly on table Alarm.
select * from Alarm --in milliseconds.
select * from vwAlarms --in milliseconds
select top (100) * from Alarms order by id desc --in milliseconds
select top (100) * from vwAlarms order by id desc --takes 10 seconds
Here is my view definition:
CREATE VIEW [dbo].[vwAlarms]
AS SELECT
dbo.Devices.Id ,
dbo.Devices.Name ,
dbo.Devices.PortsTagPrefix ,
dbo.Devices.ControlCenterNumber ,
dbo.Devices.AlarmNumber1 ,
dbo.Devices.AlarmNumber2 ,
dbo.Devices.SimCardNumber ,
dbo.Devices.StationNumber ,
dbo.Devices.SlaveId ,
dbo.Devices.TypeId ,
dbo.Devices.RegionId ,
dbo.Devices.EnquiryPassword ,
dbo.Devices.SetupPassword ,
dbo.Devices.ProtocolId ,
dbo.Devices.UploadedPacketsCount ,
dbo.Devices.LastPort ,
dbo.Devices.LastIp ,
dbo.Devices.IsForTesting ,
dbo.Devices.Latitude ,
dbo.Devices.Longitude ,
dbo.Devices.X ,
dbo.Devices.Y ,
dbo.Devices.MainSchematicId ,
dbo.Devices.MainTimeChartId ,
dbo.Devices.MainCategoryChartId ,
dbo.Alarms.Id ,
dbo.Alarms.DeviceId ,
dbo.Alarms.LogId ,
dbo.Alarms.PortId ,
dbo.Alarms.TypeId ,
dbo.Alarms.DateTime ,
dbo.Alarms.AcknowledgerId ,
dbo.Alarms.AcknowledgeDateTime ,
dbo.Alarms.Acknowledged ,
dbo.Alarms.PortValue
FROM Devices
INNER JOIN Alarms ON Devices.Id = Alarms.DeviceId
ORDER BY dbo.Alarms.Id DESC
Here is execution plan:
Warning message of of sort:
Alarm table Schema:
CREATE TABLE [dbo].[Alarms](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DeviceId] [int] NOT NULL,
[LogId] [int] NOT NULL,
[PortId] [int] NOT NULL,
[TypeId] [int] NOT NULL,
[DateTime] [datetime2](0) NOT NULL,
[AcknowledgerId] [int] NULL,
[AcknowledgeDateTime] [datetime2](0) NULL,
[Acknowledged] [bit] NULL,
[PortValue] [numeric](19, 4) NULL,
CONSTRAINT [PK_Alarms] PRIMARY KEY CLUSTERED
(
[Id] 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
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_AlarmTypes] FOREIGN KEY([TypeId])
REFERENCES [dbo].[AlarmTypes] ([Id])
GO
ALTER TABLE [dbo].[Alarms] CHECK CONSTRAINT [FK_Alarms_AlarmTypes]
GO
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_Devices] FOREIGN KEY([DeviceId])
REFERENCES [dbo].[Devices] ([Id])
GO
ALTER TABLE [dbo].[Alarms] CHECK CONSTRAINT [FK_Alarms_Devices]
GO
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_ExtendedUsers] FOREIGN KEY([AcknowledgerId])
REFERENCES [dbo].[ExtendedUsers] ([Id])
GO
ALTER TABLE [dbo].[Alarms] CHECK CONSTRAINT [FK_Alarms_ExtendedUsers]
GO
ALTER TABLE [dbo].[Alarms] WITH CHECK ADD CONSTRAINT [FK_Alarms_Logs] FOREIGN KEY([LogId])
REFERENCES [dbo].[Logs] ([Id])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER

Is using the view a must? If not, you probably should first get your 100 alarms and then join with devices. That's the end result you want right?

It is not being smart about the sort.
Do you have the FK defined?
I would try all option of the table hints on the join to try and push that sort earlier.
Join Hints (Transact-SQL)
If table hints does not work I would try a Cross Apply.
I think the Cross Apply should be smart about sort.
But at the cost of not being as fast on the "join".
So it would be good at returning the first 1000 or 10,000 but bad at all.
SELECT t1.*, t2o.*
FROM t1
CROSS APPLY
(
SELECT *
FROM t2
WHERE t2.t1_id = t1.id
) t2o

Related

Warnings when using graph queries in Visual Studio Database Project

We have some SQL "normal" and graph tables, a script that syncs the information between them.
Everything is working ok from SSMS but when building the database project in Visual Studio using msbuild we get warnings (see code and warnings details below).
If we set TreatTSqlWarningsAsErrors to True these warnings become errors.
We don't want to ignore warnings but its unclear why we even get them.
Are these warnings correct?
Why are they showing in Visual Studio only and not in SSMS?
How can we resolve them without ignoring them?
The details:
We have the following two "normal" SQL tables:
CREATE TABLE [dbo].[Currency]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](250) NOT NULL,
[UId] [uniqueidentifier] NOT NULL,
CONSTRAINT [PK_Currency]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Currency]
ADD CONSTRAINT [DF_Currency_UId] DEFAULT (NEWID()) FOR [UId]
GO
and
CREATE TABLE [dbo].[Portfolio]
(
[Id] [INT] IDENTITY(1,1) NOT NULL,
[Name] [NVARCHAR](250) NULL,
[CurrencyId] [INT] NOT NULL,
[UId] [UNIQUEIDENTIFIER] NOT NULL,
CONSTRAINT [PK_Portfolio]
PRIMARY KEY CLUSTERED ([Id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Portfolio]
ADD CONSTRAINT [DF_Portfolio_UId] DEFAULT (NEWID()) FOR [UId]
GO
ALTER TABLE [dbo].[Portfolio] WITH CHECK
ADD CONSTRAINT [FK_Portfolio_Currency]
FOREIGN KEY([CurrencyId]) REFERENCES [dbo].[Currency] ([Id])
GO
ALTER TABLE [dbo].[Portfolio] CHECK CONSTRAINT [FK_Portfolio_Currency]
GO
and we created the following SQL graph schema together with two SQL node tables and one SQL edge:
CREATE SCHEMA [graph] ;
CREATE TABLE [graph].[Currency]
(
[Id] UNIQUEIDENTIFIER NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
INDEX [GRAPH_UNIQUE_INDEX_4FFC60C0FCBE4843A7F4B9AB0729FF78] UNIQUE NONCLUSTERED ($node_id)
) AS NODE;
CREATE TABLE [graph].[Portfolio]
(
[Id] UNIQUEIDENTIFIER NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
INDEX [GRAPH_UNIQUE_INDEX_F39F92BE8DD34DD791D6CA955DA0DA9A] UNIQUE NONCLUSTERED ($node_id)
) AS NODE;
CREATE TABLE [graph].[isOf]
(
[IsActive] BIT CONSTRAINT [DF_isOf_IsActive] DEFAULT ((1)) NOT NULL,
INDEX [GRAPH_UNIQUE_INDEX_AD8C5B40D277413580EDD943AC192869] UNIQUE NONCLUSTERED ($edge_id)
) AS EDGE;
CREATE UNIQUE NONCLUSTERED INDEX [UQ_FromTo]
ON [graph].[isOf] ($from_id, $to_id) ON [PRIMARY];
GO
A sync stored procedure which will populate the nodes and the edge from the "normal" tables that will be executed daily.
Attached parts of it:
PRINT ( 'Sync graph.[Portfolio]' );
INSERT INTO graph.Portfolio ( Id )
SELECT P.[UId]
FROM dbo.Portfolio P
WHERE NOT EXISTS ( SELECT 1
FROM graph.Portfolio G
WHERE G.Id = P.[UId] );
PRINT ( 'Sync graph.[Currency]' );
INSERT INTO graph.Currency ( Id )
SELECT C.[UId]
FROM dbo.Currency C
WHERE NOT EXISTS ( SELECT 1
FROM graph.Currency G
WHERE G.Id = C.[UId] );
PRINT('Sync Portfolio isOf Currency edge');
;
WITH UidCTE
AS ( SELECT P.[UId] AS PortfolioUid ,
C.[UId] AS CurrencyUid
FROM dbo.Portfolio P
JOIN dbo.Currency C ON C.Id = P.CurrencyId )
MERGE graph.isOf AS TGT
USING graph.[Portfolio] AS SourceFrom
JOIN UidCTE CTE ON SourceFrom.Id = CTE.PortfolioUid
JOIN graph.[Currency] AS SourceTo ON CTE.CurrencyUid = SourceTo.Id
ON MATCH(SourceFrom-(TGT)->SourceTo)
WHEN NOT MATCHED BY TARGET THEN
INSERT ( $from_id , $to_id )
VALUES ( SourceFrom.$node_id, SourceTo.$node_id)
WHEN MATCHED AND TGT.[IsActive] = 0 THEN
UPDATE SET TGT.[IsActive] = 1;
and the following script which updates the edge's IsActive column in case the relationship doesn't exist anymore in the "normal" tables(we don't want to delete it from the graph nodes/edges)
;WITH PortfolioIsOfCurrency
AS ( SELECT P.[UId] AS PortfolioUid ,
C.[UId] AS CurrencyUid
FROM dbo.Portfolio P
JOIN dbo.Currency C ON C.Id = P.CurrencyId ) ,
NodeCTE
AS ( SELECT P.$node_id AS FromNode ,
C.$node_id AS ToNode
FROM PortfolioIsOfCurrency CTE
JOIN graph.Portfolio P ON P.Id = CTE.PortfolioUid
JOIN graph.Currency C ON C.Id = CTE.CurrencyUid )
UPDATE ISOF
SET isOf.IsActive = 0
FROM graph.isOf ISOF
WHERE NOT EXISTS ( SELECT 1
FROM NodeCTE N
WHERE N.FromNode = ISOF.$from_id
AND N.ToNode = ISOF.$to_id );
We created a database project in VS 2019 with the following settings:
<DSP>Microsoft.Data.Tools.Schema.Sql.Sql150DatabaseSchemaProvider</DSP>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
<TreatTSqlWarningsAsErrors>False</TreatTSqlWarningsAsErrors>
From SSMS everything works perfect.
The problem is with the last syntax(UPDATE isof.active) I get the following warnings:
Warning SQL71502: Procedure: [graph].[SyncEngagementContentGraphs] has an unresolved reference to object [graph].[isOf].[N]. graph\Stored Procedures\SyncEngagementContentGraphs.sql 57
Warning SQL71502: Procedure: [graph].[SyncEngagementContentGraphs] has an unresolved reference to object [graph].[isOf].[N]. graph\Stored Procedures\SyncEngagementContentGraphs.sql 58
Warning SQL71509: The model already has an element that has the same name NodeCTE.$node_id. graph\Stored Procedures\SyncEngagementContentGraphs.sql 47
Warning SQL71509: The model already has an element that has the same name NodeCTE.$node_id. graph\Stored Procedures\SyncEngagementContentGraphs.sql 48
and if we set TreatTSqlWarningsAsErrors to True these warnings become errors and we cannot leave it like this (set to False) in the long run.
The solution is to define correctly the NodeCTE common table expression with columns names.
This seems to be mandatory in the case of a CTE with graph tables.
The correct query whithout warnings would be:
;WITH PortfolioIsOfCurrency
AS ( SELECT P.[UId] AS PortfolioUid ,
C.[UId] AS CurrencyUid
FROM dbo.Portfolio P
JOIN dbo.Currency C ON C.Id = P.CurrencyId ) ,
**NodeCTE(FromNode, ToNode)**
AS ( SELECT P.$node_id AS FromNode ,
C.$node_id AS ToNode
FROM PortfolioIsOfCurrency CTE
JOIN graph.Portfolio P ON P.Id = CTE.PortfolioUid
JOIN graph.Currency C ON C.Id = CTE.CurrencyUid )
UPDATE ISOF
SET isOf.IsActive = 0
FROM graph.isOf ISOF
WHERE NOT EXISTS ( SELECT 1
FROM NodeCTE N
WHERE N.FromNode = ISOF.$from_id
AND N.ToNode = ISOF.$to_id );
This change is needed just for the VS SqlProject warnings. Both versions work with no problems with SSMS/ADS.

SQL JOIN not returning any results

I have a fairly simple join for three tables that is not returning any results. If I modify slightly I get sometime that appears jumbled (same data values in two fields). There is a Documents table from which I need the filename, a Variable table which has the variable definitions and names, and lastly I have a VariableValue table that the values for the variables are stored in. I am trying to get two values for each filename. Subject and Author. Here is the SQL call.
SELECT DISTINCT Documents.Filename, VariableValue.ValueText AS Author,
VariableValue.ValueText AS Subject
FROM Documents INNER JOIN
VariableValue ON Documents.DocumentID = VariableValue.DocumentID INNER JOIN
Variable AS VV1 ON VariableValue.VariableID = VV1.VariableID INNER JOIN
Variable AS VV2 ON VariableValue.VariableID = VV2.VariableID
WHERE (Documents.Filename LIKE N'ECO-%') AND (Documents.Deleted = 0) AND
(VV1.VariableName = N'Author') AND (VariableValue.ValueText <> '-') AND
(VV2.VariableName = N'Subject')
ORDER BY Author asc
If I remove the (VV2.VariableName = N'Subject') I get the following result:
Filename Author Subject
ECO-27533.docx billpark billpark
ECO-27630.docx billpark billpark
ECO-27683.docx billpark billpark
ECO-27790.docx billpark billpark
ECO-27812.docx billpark billpark
ECO-27975.docx billpark billpark
If I remove the (VV1.VariableName = N'Author') I get the following result:
Filename Author Subject
ECO-28720.docx 24006 LOW PWR BM DUMP 24006 LOW PWR BM DUMP
ECO-28595.docx 24052 PIN THREAD CORRECTION 24052 PIN THREAD CORRECTION
ECO-28517.docx 24087 24087
ECO-28791.docx 25584 REV A TO B 25584 REV A TO B
ECO-28714.docx 25873 PRESSURE RELEAF ASSY 25873 PRESSURE RELEAF ASSY
What I would like is:
Filename Author Subject
ECO-28720.docx billpark LOW PWR BM DUMP
Not sure what subtle thing I am missing?
TIA.
DDL
CREATE TABLE [dbo].[Variable](
[VariableID] [int] IDENTITY(1,1) NOT NULL,
[VariableName] [nvarchar](255) NOT NULL,
[VariableType] [int] NOT NULL,
[IsDeleted] [bit] NOT NULL,
[FlagUnique] [bit] NOT NULL,
[FlagMandatory] [bit] NOT NULL,
[FlagFreeUpdateAllVersion] [bit] NOT NULL CONSTRAINT [DF__Variable__FlagFr__05EEBAAE] DEFAULT ((0)),
[FlagFreeUpdateLatestVersion] [bit] NOT NULL CONSTRAINT [DF__Variable__FlagFr__06E2DEE7] DEFAULT ((0)),
CONSTRAINT [PK_Variable] PRIMARY KEY CLUSTERED
(
[VariableID] 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
AND
CREATE TABLE [dbo].[VariableValue](
[VariableID] [int] NOT NULL,
[DocumentID] [int] NOT NULL,
[ProjectID] [int] NOT NULL,
[RevisionNo] [int] NOT NULL,
[ConfigurationID] [int] NOT NULL,
[ValueText] [nvarchar](max) NOT NULL CONSTRAINT [DF_VariableValue_ValueText] DEFAULT (N''),
[ValueInt] [int] NULL,
[ValueFloat] [float] NULL,
[ValueDate] [datetime] NULL,
[ValueCache] [nvarchar](64) NOT NULL CONSTRAINT [DF_VariableValue_ValueCache] DEFAULT (''),
[IsLongText] [bit] NOT NULL CONSTRAINT [DF_VariableValue_IsLongText] DEFAULT ((0)),
CONSTRAINT [PK_VariableValue] PRIMARY KEY CLUSTERED
(
[VariableID] ASC,
[DocumentID] ASC,
[ProjectID] ASC,
[RevisionNo] ASC,
[ConfigurationID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[VariableValue] WITH NOCHECK ADD CONSTRAINT [FK_VariableValue_DocumentConfiguration] FOREIGN KEY([ConfigurationID])
REFERENCES [dbo].[DocumentConfiguration] ([ConfigurationID])
GO
ALTER TABLE [dbo].[VariableValue] CHECK CONSTRAINT [FK_VariableValue_DocumentConfiguration]
GO
ALTER TABLE [dbo].[VariableValue] WITH NOCHECK ADD CONSTRAINT [FK_VariableValue_Documents] FOREIGN KEY([DocumentID])
REFERENCES [dbo].[Documents] ([DocumentID])
GO
ALTER TABLE [dbo].[VariableValue] CHECK CONSTRAINT [FK_VariableValue_Documents]
GO
ALTER TABLE [dbo].[VariableValue] WITH CHECK ADD CONSTRAINT [FK_VariableValue_Projects] FOREIGN KEY([ProjectID])
REFERENCES [dbo].[Projects] ([ProjectID])
GO
ALTER TABLE [dbo].[VariableValue] CHECK CONSTRAINT [FK_VariableValue_Projects]
GO
ALTER TABLE [dbo].[VariableValue] WITH NOCHECK ADD CONSTRAINT [FK_VariableValue_Variable] FOREIGN KEY([VariableID])
REFERENCES [dbo].[Variable] ([VariableID])
GO
ALTER TABLE [dbo].[VariableValue] CHECK CONSTRAINT [FK_VariableValue_Variable]
GO
VariableValue.ValueText AS Author,
VariableValue.ValueText AS Subject
You're calling the exact same alias.columnname and assigning it to both Author and Subject.
We need to add projectID, revisionNo and ConfigurationID to the results as the PK for VariableValue is a composite key. If we don't include them, then the results could get mixed up for different projects/revsions or configurations.
So unless you have a rule that says only return the latest revision for a document... we may get multiple records back.
SELECT Documents.Filename
, VariableValue.ProjectID
, VariableValue.RevisionNo
, VariableValue.ConfigurationID
, max(Case when VV1.VariableName = N'Author' then VariableValue.ValueText END) as Author
, max(Case when VV1.VariableName = N'Subject' then VariableValue.ValueText END) AS Subject
FROM Documents
INNER JOIN VariableValue
ON Documents.DocumentID = VariableValue.DocumentID
INNER JOIN Variable AS VV1
ON VariableValue.VariableID = VV1.VariableID
WHERE (Documents.Filename LIKE N'ECO-%')
AND (Documents.Deleted = 0)
AND (VariableValue.ValueText <> '-')
AND (VV1.VariableName in (N'Author',N'Subject')
GROUP BY Documents.Filename
, VariableValue.ProjectID
, VariableValue.RevisionNo
, VariableValue.ConfigurationID
ORDER BY Author asc
With a terrific assist from xQbert this code does it.
SELECT DISTINCT Documents.Filename, max(Case when VV1.VariableName = N'Author' then VariableValue.ValueText END) as Author,
max(Case when VV1.VariableName = N'Subject' then VariableValue.ValueText END) AS Description
FROM Documents INNER JOIN
VariableValue ON Documents.DocumentID = VariableValue.DocumentID INNER JOIN
Variable AS VV1 ON VariableValue.VariableID = VV1.VariableID INNER JOIN
Variable AS VV2 ON VariableValue.VariableID = VV2.VariableID
WHERE (Documents.Filename LIKE N'ECO-%') AND (Documents.Deleted = 0) AND (VV1.VariableName in (N'Author',N'Subject') AND (VariableValue.ValueText <> '-'))
Group BY Documents.Filename
ORDER BY Author asc

T-SQL ISNULL() incorrect behaviour with reserved word 'Primary' (SQL Server 2014)

I came across this the other day, and it wasn't a major as I could work around it, but wondered if anyone could offer any insight, or have I found an obscure bug?
We have an old database table that has a column called Primary, which is obviously a reserved word. When running a T-SQL query I came across some weird results which seems to suggest that the ISNULL function is treating the column name as if it were the reserved word. Is it just because it's late on Friday and I'm missing something really obvious here, or is something weird going on here?
Here is some simple SQL to set up a couple of test tables to illustrate it.
CREATE TABLE [dbo].[Customer]
(
[CustomerID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Customer]
PRIMARY KEY CLUSTERED ([CustomerID] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[OrderTaken]
(
[OrderID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](50) NOT NULL,
[CustomerID] [int] NOT NULL,
[Primary] [bit] NOT NULL,
CONSTRAINT [PK_Order]
PRIMARY KEY CLUSTERED ([OrderID] ASC)
) ON [PRIMARY]
ALTER TABLE [dbo].[OrderTaken] WITH CHECK
ADD CONSTRAINT [FK_Order_Customer]
FOREIGN KEY([CustomerID]) REFERENCES [dbo].[Customer] ([CustomerID])
GO
ALTER TABLE [dbo].[OrderTaken] CHECK CONSTRAINT [FK_Order_Customer]
GO
INSERT INTO [dbo].[Customer](Name) VALUES('Bob')
INSERT INTO [dbo].[Customer](Name) VALUES('Dave')
INSERT INTO [dbo].[Customer](Name) VALUES('Fred')
INSERT INTO [dbo].[Customer](Name) VALUES('Paul')
GO
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES ('Order1', 1, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order2', 2, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order3', 2, 1)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order4', 3, 0)
INSERT INTO [dbo].[OrderTaken](Description, CustomerID, [Primary])
VALUES('Order5', 3, 0)
Go
and here is the query
SELECT
C.CustomerID, C.Name,
O.OrderID, ISNULL(O.[OrderID], -1),
O.[Primary], ISNULL(O.[Primary], -1) as Weird
FROM
Customer C
LEFT JOIN
OrderTaken O ON C.CustomerID = O.CustomerID
Notice that for the customer row that doesn't have an Order, O.Primary is NULL , but ISNULL(O.[Primary],-1) returns 1 and not -1
The problem is not in field name, it's in field type - bit.
It cant hold -1 value, only 0 and 1. And when SQL Server tries to change value to -1 it checks that -1 <> 0 and sets 1 (true). See documentation.
So convert the field before checking:
SELECT
C.CustomerID,
C.Name,
O.OrderID,
ISNULL(O.[OrderID],-1),
O.[Primary],
ISNULL(CONVERT(int,O.[Primary]),-1) as Weird
FROM Customer C
LEFT JOIN OrderTaken O
ON C.CustomerID = O.CustomerID
Or change column type to int or tinyint.

Joining master and child with only the row count of child table

Master Table:
CREATE TABLE [dbo].[db_Chat](
[ChatID] [int] IDENTITY(1,1) NOT NULL,
[MemberID] [int] NOT NULL,
[MsgText] [nvarchar](300) COLLATE Chinese_Taiwan_Stroke_CI_AS NOT NULL,
[DateCreated] [smalldatetime] NOT NULL,
CONSTRAINT [PK_db_Chat] PRIMARY KEY CLUSTERED
(
[ChatID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
Child Table:
CREATE TABLE [dbo].[db_Chat_Read](
[ChatReadID] [int] IDENTITY(1,1) NOT NULL,
[MemberID] [int] NOT NULL,
[ChatID] [int] NOT NULL,
[DateCreated] [smalldatetime] NOT NULL,
CONSTRAINT [PK_db_Chat_Read] PRIMARY KEY CLUSTERED
(
[ChatReadID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
I want to join the two tables and show the number of rows of child table, if there is no row selected then it can show zero.
I know the following code works fine.
select c.ChatID, COUNT(*) as ACount from db_chat c
left join db_Chat_Read r
on c.ChatID = r.ChatID
where c.ChatGroupID=2
GROUP BY c.ChatID
But I need something like this in a single SQL code, the following SQL code is invalid, but it is to show what result I want: I need full fields of master table with only Row Count of child table.
select c.*, COUNT(r.*) from db_chat c
left join db_Chat_Read r
on c.ChatID = r.ChatID
where c.ChatGroupID=2
Thank you~!
You can do what you want with a subquery:
select c.*,
(select COUNT(*) from db_Chat_Read r where c.ChatID = r.ChatId
) as ACount
from db_chat c
where c.ChatGroupID = 2;
However, I would recommend putting the columns in the group by.
EDIT:
You can also do this with an additional join:
select c.*, coalesce(ACount, 0) as ACount
from db_chat c left join
(select r.ChatId, count(*) as ACount
from db_Chat_Read r
group by r.ChatId
) r
on c.ChatID = r.ChatID
where c.ChatGroupID = 2;

SQL Server strange duplicate key error

In SQL Server 2008 R2, I have a simple table with the following columns definitions:
Id (PK ,int , not null)
MeterId (FK , int ,not null)
InstallDate(DateTime, not null)
Image(NVarCharMax, null)
Number (int , not null)
Comments(NVarChar(300), null)
And Id column is set as Identity .
When I run:
insert into Transmitters (MeterId, Number, InstallDate)
values (952, 777 , '2013-02-21')
I get the duplicate key error.
There is no other transmitter with id 777 ,
There is a meter with id 952.
This started happening in more than 1 table of my DB.
Any suggestions would be most appriceated.
The entire table script is:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Transmitters](
[Id] [int] IDENTITY(1,1) NOT NULL,
[MeterId] [int] NOT NULL,
[InstallDate] [datetime] NOT NULL,
[Image] [nvarchar](max) NULL,
[Number] [int] NOT NULL,
[Comments] [nvarchar](300) NULL,
CONSTRAINT [PK_Transmitters] PRIMARY KEY CLUSTERED
(
[Id] 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
ALTER TABLE [dbo].[Transmitters] WITH CHECK ADD CONSTRAINT [FK_Transmitter_Meter] FOREIGN KEY([MeterId])
REFERENCES [dbo].[Meter] ([Id])
GO
ALTER TABLE [dbo].[Transmitters] CHECK CONSTRAINT [FK_Transmitter_Meter]
GO
Ok , thanks guys you've been most helpful.
I've checked my identity current value using:
USE Name_Of_The_DB
GO
DBCC CHECKIDENT (‘Name_Of_The_Table’)
GO
It was indeed the cause of the problem that some rows had higher Id values than
the current identity.
Thand I inserted a row to update the current identity value:
set identity_insert YourTable ON
--Insert my row
set identity_insert YourTable OFF
Thanks :)

Resources