August 28, 2018 at 11:35 am
I have the following t-sql 2012 where I would like to be able to select lots of @calendarID values that are 4 numbers long:
declare @calendarID varchar(04)= '8214'
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term WITH (NOLOCK)
WHERE (Term.startDate IS NOT NULL)
AND Term.calendarID in (@calendarID)
group by term.name, Term.seq
ORDER BY TermName, seq
The above sql works for one calendarID value but I would like to have up to 20 values entered for @calendarID.
Thus can you tell me what I can change in the sql to make it work correctly?
August 28, 2018 at 12:29 pm
wendy elizabeth - Tuesday, August 28, 2018 11:35 AMI have the following t-sql 2012 where I would like to be able to select lots of @calendarID values that are 4 numbers long:
declare @calendarID varchar(04)= '8214'
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term WITH (NOLOCK)
WHERE (Term.startDate IS NOT NULL)
AND Term.calendarID in (@calendarID)
group by term.name, Term.seq
ORDER BY TermName, seqThe above sql works for one calendarID value but I would like to have up to 20 values entered for @calendarID.
Thus can you tell me what I can change in the sql to make it work correctly?
If you were using SQL Server 2016 or higher you could use the STRING_SPLIT function. But it's not available in 2012 so you will need to add your own function.
I use this one:-- Splits a string into rows
CREATE FUNCTION [dbo].[chrSplitList]
(
@list nvarchar(MAX),
@separator nvarchar(MAX) = ';'
)
RETURNS @table TABLE (Value nvarchar(4000))
AS BEGIN
DECLARE @position INT, @previous INT
SET @list = @list + @separator
SET @previous = 1
SET @position = CHARINDEX(@separator, @list)
WHILE @position > 0 BEGIN
IF @position - @previous > 0
INSERT INTO @table VALUES (SUBSTRING(@list, @previous, @position - @previous))
IF @position >= LEN(@list) BREAK
SET @previous = @position + LEN(@separator)
SET @position = CHARINDEX(@separator, @list, @previous)
END
RETURN
END
GO
If you install the function above then the following query should return the results you want.declare @calendarID varchar(100)= '8214,8145,8767'
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term
inner join dbo.chrSplitList(@calendarID,',') X
on x.Value = Term.calendarID
WHERE (Term.startDate IS NOT NULL)
group by term.name, Term.seq
ORDER BY TermName, seq
August 28, 2018 at 1:23 pm
Jonathan AC Roberts - Tuesday, August 28, 2018 12:29 PMwendy elizabeth - Tuesday, August 28, 2018 11:35 AMI have the following t-sql 2012 where I would like to be able to select lots of @calendarID values that are 4 numbers long:
declare @calendarID varchar(04)= '8214'
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term WITH (NOLOCK)
WHERE (Term.startDate IS NOT NULL)
AND Term.calendarID in (@calendarID)
group by term.name, Term.seq
ORDER BY TermName, seqThe above sql works for one calendarID value but I would like to have up to 20 values entered for @calendarID.
Thus can you tell me what I can change in the sql to make it work correctly?
If you were using SQL Server 2016 or higher you could use the STRING_SPLIT function. But it's not available in 2012 so you will need to add your own function.
I use this one:-- Splits a string into rows
CREATE FUNCTION [dbo].[chrSplitList]
(
@list nvarchar(MAX),
@separator nvarchar(MAX) = ';'
)
RETURNS @table TABLE (Value nvarchar(4000))
AS BEGINDECLARE @position INT, @previous INT
SET @list = @list + @separator
SET @previous = 1
SET @position = CHARINDEX(@separator, @list)
WHILE @position > 0 BEGIN
IF @position - @previous > 0
INSERT INTO @table VALUES (SUBSTRING(@list, @previous, @position - @previous))
IF @position >= LEN(@list) BREAK
SET @previous = @position + LEN(@separator)
SET @position = CHARINDEX(@separator, @list, @previous)
END
RETURN
END
GO
If you install the function above then the following query should return the results you want.declare @calendarID varchar(100)= '8214,8145,8767'
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term
inner join dbo.chrSplitList(@calendarID,',') X
on x.Value = Term.calendarID
WHERE (Term.startDate IS NOT NULL)
group by term.name, Term.seq
ORDER BY TermName, seq
You've got the right idea, but the fastest string splitter on the planet is a better choice, and can be found
here: http://www.sqlservercentral.com/articles/72993/
Go to the end of the article to find the link.
Thus the following query:DECLARE @calendarID AS varchar(100) = '8214,8145,8767';
SELECT DISTINCT
T.name AS TermName,
T.seq AS Seq
FROM Term AS T
INNER JOIN dbo.Delimited8K_LEAD(@calendarID, ',') AS S
ON T.calendarID = S.Item
WHERE T.startDate IS NOT NULL
GROUP BY
T.name,
T.seq
ORDER BY
T.Name,
T.seq;
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
August 29, 2018 at 12:49 am
For an ad-hoc query, you can just use a table or table variable:
Declare @CalendarIDs Table(ID VarChar(4))
Insert Into @CalendarIDs Values('8403','8404','8405')
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term
WHERE (Term.startDate IS NOT NULL)
AND Term.calendarID in @CalendarIDs
group by term.name, Term.seq
ORDER BY TermName, seq
If this needs to end up as a parameter to a stored procedure, then look into Table Valued Parameters. And as an aside, don't put the nolock hint on queries unless you entirely understand how horribly wrong it can cause your answers to be, you almost certainly don't need it.
September 10, 2018 at 10:48 am
andycadley - Wednesday, August 29, 2018 12:49 AMFor an ad-hoc query, you can just use a table or table variable:Declare @CalendarIDs Table(ID VarChar(4))
Insert Into @CalendarIDs Values('8403','8404','8405')
SELECT DISTINCT term.name AS TermName, Term.seq AS Seq
from Term AS Term
WHERE (Term.startDate IS NOT NULL)
AND Term.calendarID in @CalendarIDs
group by term.name, Term.seq
ORDER BY TermName, seqIf this needs to end up as a parameter to a stored procedure, then look into Table Valued Parameters. And as an aside, don't put the nolock hint on queries unless you entirely understand how horribly wrong it can cause your answers to be, you almost certainly don't need it.
Andy,
Be aware that table variables are bad news for query estimates, and thus for query plans. They don't ever get statistics, and are always assumed to have exactly 1 row. Much better off using a temp table for any data that has more than one row.
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
September 10, 2018 at 11:16 am
As is often the case with SQL Server, it depends. For small numbers of rows, statistics likely won't make any difference and can indeed hurt query performance due to SQL Server's habit of "resurrecting" dropped temp tables along with their statistics, if you run the query a lot with high variance in your parameters.
I suspect having a long string of Values to parse is liable to cause a performance problem long before a table variable becomes an issue in an ad-hoc query like that (although it helps if you get the syntax correct, unlike in my example!)
Your milage may vary, performance can go down as well as up, conditions apply etc.... 😉
September 10, 2018 at 11:26 am
Is this procedure for an SSRS report? If so, are the values from a multi-select parameter?
If that;s the case, the values will be passed in as a comma-separated list.
'1234,4567,8978'
You would probably get your best results by using the DelimitedSplit8k function.
Michael L John
If you assassinate a DBA, would you pull a trigger?
To properly post on a forum:
http://www.sqlservercentral.com/articles/61537/
September 11, 2018 at 6:34 am
andycadley - Monday, September 10, 2018 11:16 AMAs is often the case with SQL Server, it depends. For small numbers of rows, statistics likely won't make any difference and can indeed hurt query performance due to SQL Server's habit of "resurrecting" dropped temp tables along with their statistics, if you run the query a lot with high variance in your parameters.I suspect having a long string of Values to parse is liable to cause a performance problem long before a table variable becomes an issue in an ad-hoc query like that (although it helps if you get the syntax correct, unlike in my example!)
Your milage may vary, performance can go down as well as up, conditions apply etc.... 😉
Yep, your mileage may vary, "it depends", etc., are all certainly a part of my SQL vocabulary. However, I have to ask the question... Why take an absolutely unnecessary risk of throwing off the query optimizer's estimates? It's totally unnecessary, and adds risk. To me, NOT doing that is in the "no brainer" category. After all, we all have the occasional syntax issue, and SQL is already challenging enough without adding needless risk to the equation. As long as we are all still in the "human beings make mistakes" category, I'll stay away from table variables as often as possible.
Steve (aka sgmunson) 🙂 🙂 🙂
Rent Servers for Income (picks and shovels strategy)
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply