Click here to monitor SSC
SQLServerCentral is supported by Redgate
 
Log in  ::  Register  ::  Not logged in
 
 
 


Better Way to Perform this Query


Better Way to Perform this Query

Author
Message
AndrewSQLDBA
AndrewSQLDBA
Ten Centuries
Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)

Group: General Forum Members
Points: 1008 Visits: 3427
Hello Everyone
I hope that everyone is having a very good day.

I need to write a query to select row counts, but this seems like a lot of scanning of the rows. Is there a better way to write a query that does this? There are approx 5 million rows in the table


DECLARE @abc int
DECLARE @def int
DECLARE @ghi int
DECLARE @jkl int
DECLARE @mno int
DECLARE @pqr int
DECLARE @stu int
DECLARE @vw int
DECLARE @xzy int


SET @abc = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%abc%')
SET @def = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%def%')
SET @ghi = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%ghi%')
SET @jkl = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%jkl%')
SET @mno = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%mno%')
SET @pqr = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%pqr%')
SET @stu = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%stu%')
SET @vw = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%vw%')
SET @xzy = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%xyz%')



Thank You in advance for all your help, advice and suggestions.

Andrew SQLDBA
Peter Brinkhaus
Peter Brinkhaus
SSCommitted
SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)SSCommitted (1.7K reputation)

Group: General Forum Members
Points: 1677 Visits: 7082
You can try something like this (requires only a single table scan):


SELECT
@abc = COUNT(CASE WHEN ColumnName LIKE '%abc%' THEN 1 END),
@def = COUNT(CASE WHEN ColumnName LIKE '%def%' THEN 1 END),
@ghi = COUNT(CASE WHEN ColumnName LIKE '%ghi%' THEN 1 END),
@jkl = COUNT(CASE WHEN ColumnName LIKE '%jkl%' THEN 1 END),
@mno = COUNT(CASE WHEN ColumnName LIKE '%mno%' THEN 1 END),
@pqr = COUNT(CASE WHEN ColumnName LIKE '%pqr%' THEN 1 END),
@stu = COUNT(CASE WHEN ColumnName LIKE '%stu%' THEN 1 END),
@vw = COUNT(CASE WHEN ColumnName LIKE '%vw%' THEN 1 END),
@xzy = COUNT(CASE WHEN ColumnName LIKE '%xyz%' THEN 1 END)
FROM
TableName


AndrewSQLDBA
AndrewSQLDBA
Ten Centuries
Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)Ten Centuries (1K reputation)

Group: General Forum Members
Points: 1008 Visits: 3427
Thank You Peter

Very handy to know.

Andrew SQLDBA
Alan.B
Alan.B
SSCrazy
SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)

Group: General Forum Members
Points: 2242 Visits: 7426
AndrewSQLDBA (1/9/2013)
Hello Everyone
I hope that everyone is having a very good day.

I need to write a query to select row counts, but this seems like a lot of scanning of the rows. Is there a better way to write a query that does this? There are approx 5 million rows in the table


DECLARE @abc int
DECLARE @def int
DECLARE @ghi int
DECLARE @jkl int
DECLARE @mno int
DECLARE @pqr int
DECLARE @stu int
DECLARE @vw int
DECLARE @xzy int


SET @abc = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%abc%')
SET @def = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%def%')
SET @ghi = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%ghi%')
SET @jkl = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%jkl%')
SET @mno = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%mno%')
SET @pqr = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%pqr%')
SET @stu = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%stu%')
SET @vw = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%vw%')
SET @xzy = (SELECT COUNT(*) FROM TableName WHERE ColumnName LIKE '%xyz%')



Its worth noting that the following is sargable.
LIKE '%abc%'

Question:
Are you really trying to find columnNames with abc in their name, def in their name, etc... Or are you trying to get a count of all columns whose name begins with [a-c] for @abc; a count of names beginning with [d-f] for @def, etc, etc... If that's what you are looking for, you can try the query below. It's a way to pass a variable or parameter to NTILE and do what you are doing dynamically (for the most part, some assembly required).


DECLARE @groups int = 9;
;WITH
asciichar(n,c) AS
( SELECT (65), CHAR(65)
UNION ALL
SELECT n+1, CHAR(n+1) FROM asciichar WHERE n+1<=90),
groups AS
( SELECT NTILE(@groups) OVER (ORDER BY n) AS groupid, * FROM asciichar ),
ntileMatrix AS
( SELECT groupid,
MIN(c) OVER (PARTITION BY groupid)+'-'+
MAX(c) OVER (PARTITION BY groupid) AS [group],
n AS [ASCII],
c AS [CHAR]
FROM groups ),
people AS
( SELECT LEFT(LastName,1) AS c1, LastName+', '+FirstName AS Name
FROM AdventureWorks2008R2.person.person )
SELECT nm.[group], p.Name
FROM ntileMatrix nm
CROSS JOIN people p
WHERE [CHAR]=c1



The code above will produce this (truncated for reading):

group Name
----- -------------------------------------
A-C Abbas, Syed
A-C Abel, Catherine
A-C Abercrombie, Kim
....
Y-Z Zukowski, Jake
Y-Z Zwilling, Michael
Y-Z Zwilling, Michael


You can change it to this:

DECLARE @groups int = 9;
;WITH
asciichar(n,c) AS
( SELECT (65), CHAR(65)
UNION ALL
SELECT n+1, CHAR(n+1) FROM asciichar WHERE n+1<=90),
groups AS
( SELECT NTILE(@groups) OVER (ORDER BY n) AS groupid, * FROM asciichar ),
ntileMatrix AS
( SELECT groupid,
MIN(c) OVER (PARTITION BY groupid)+'-'+
MAX(c) OVER (PARTITION BY groupid) AS [group],
n AS [ASCII],
c AS [CHAR]
FROM groups ),
people AS
( SELECT LEFT(LastName,1) AS c1, LastName+', '+FirstName AS Name
FROM AdventureWorks2008R2.person.person ),
Totals AS
(
SELECT nm.[group], p.Name
FROM ntileMatrix nm
CROSS JOIN people p
WHERE [CHAR]=c1 )
SELECT [group], COUNT([group]) AS groupCount
FROM Totals
GROUP BY [group]



To get this:


group groupCount
----- -----------
A-C 3502
D-F 1111
G-I 2572
J-L 2347
M-O 2061
P-R 3195
S-U 2800
V-X 1552
Y-Z 832


Again, some assembly required for what you are doing....

What's cool is you can change the parameter or variable to dynamically change your groups like so:


DECLARE @groups int = 3;



and get this:


group groupCount
----- -----------
A-I 7185
J-R 7603
S-Z 5184


Edit: Typo's

-- Alan Burstein



Best practices for getting help on SQLServerCentral
Need to split a string? Try DelimitedSplit8K or DelimitedSplit8K_LEAD (SQL 2012+)
Need a pattern-based splitter? Try PatternSplitCM
Need to remove or replace those unwanted characters? Try PatExclude8K and PatReplace8K.

"I can't stress enough the importance of switching from a 'sequential files' mindset to 'set-based' thinking. After you make the switch, you can spend your time tuning and optimizing your queries instead of maintaining lengthy, poor-performing code. " -- Itzek Ben-Gan 2001
dwain.c
dwain.c
SSCarpal Tunnel
SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)

Group: General Forum Members
Points: 4259 Visits: 6431
Alan - That's a very intriguing use of NTILE!

I would recommend, however that you change the way you construct your asciichar table:



;WITH asciichar(n, c) AS (
SELECT n=64+number, CHAR(64+number)
FROM [master].dbo.spt_values Tally
WHERE [Type] = 'P' AND Number BETWEEN 1 AND 26)
SELECT *
FROM asciichar





My mantra: No loops! No CURSORs! No RBAR! Hoo-uh!

My thought question: Have you ever been told that your query runs too fast?

My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.


Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Learn to understand recursive CTEs by example.
Splitting strings based on patterns can be fast!
My temporal SQL musings: Calendar Tables, an Easter SQL, Time Slots and Self-maintaining, Contiguous Effective Dates in Temporal Tables
Jeff Moden
Jeff Moden
SSC-Forever
SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)

Group: General Forum Members
Points: 45147 Visits: 39923
Alan.B (1/9/2013)
[quote]AndrewSQLDBA (1/9/2013)
Its worth noting that the following is sargable.
LIKE '%abc%'



Did you mean "NOT" SARGable because it sure doesn't look SARGable from here. ;-) And, I agree... nice use of NTILE.

--Jeff Moden

RBAR is pronounced ree-bar and is a Modenism for Row-By-Agonizing-Row.
First step towards the paradigm shift of writing Set Based code:
Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column.
Although they tell us that they want it real bad, our primary goal is to ensure that we dont actually give it to them that way.
Although change is inevitable, change for the better is not.
Just because you can do something in PowerShell, doesnt mean you should. Wink

Helpful Links:
How to post code problems
How to post performance problems
Forum FAQs
dwain.c
dwain.c
SSCarpal Tunnel
SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)SSCarpal Tunnel (4.3K reputation)

Group: General Forum Members
Points: 4259 Visits: 6431
Jeff Moden (1/9/2013)
Alan.B (1/9/2013)
[quote]AndrewSQLDBA (1/9/2013)
Its worth noting that the following is sargable.
LIKE '%abc%'



Did you mean "NOT" SARGable because it sure doesn't look SARGable from here. ;-)


Is that because of the % at the beginning of the string?


My mantra: No loops! No CURSORs! No RBAR! Hoo-uh!

My thought question: Have you ever been told that your query runs too fast?

My advice:
INDEXing a poor-performing query is like putting sugar on cat food. Yeah, it probably tastes better but are you sure you want to eat it?
The path of least resistance can be a slippery slope. Take care that fixing your fixes of fixes doesn't snowball and end up costing you more than fixing the root cause would have in the first place.


Need to UNPIVOT? Why not CROSS APPLY VALUES instead?
Since random numbers are too important to be left to chance, let's generate some!
Learn to understand recursive CTEs by example.
Splitting strings based on patterns can be fast!
My temporal SQL musings: Calendar Tables, an Easter SQL, Time Slots and Self-maintaining, Contiguous Effective Dates in Temporal Tables
Jeff Moden
Jeff Moden
SSC-Forever
SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)SSC-Forever (45K reputation)

Group: General Forum Members
Points: 45147 Visits: 39923
Yes.

It would also give the wrong answer, IMHO.

--Jeff Moden

RBAR is pronounced ree-bar and is a Modenism for Row-By-Agonizing-Row.
First step towards the paradigm shift of writing Set Based code:
Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column.
Although they tell us that they want it real bad, our primary goal is to ensure that we dont actually give it to them that way.
Although change is inevitable, change for the better is not.
Just because you can do something in PowerShell, doesnt mean you should. Wink

Helpful Links:
How to post code problems
How to post performance problems
Forum FAQs
Alan.B
Alan.B
SSCrazy
SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)

Group: General Forum Members
Points: 2242 Visits: 7426
dwain.c (1/9/2013)
Alan - That's a very intriguing use of NTILE!

I would recommend, however that you change the way you construct your asciichar table:



;WITH asciichar(n, c) AS (
SELECT n=64+number, CHAR(64+number)
FROM [master].dbo.spt_values Tally
WHERE [Type] = 'P' AND Number BETWEEN 1 AND 26)
SELECT *
FROM asciichar




Thank you, and thank you. I'm still just learning Windows functions (have been studying them for ~6 months now give or take.) For me it's been easy to find a uses for ROW_NUMBER , RANK and DENSE_RANK but this was a rare case where I found some use for NTILE; this was originally a dynamic SQL query.

I agree that I should have used a tally table. I've been writing CTE's for counting for awhile and can do so while sleeping. I still fumble around with the tally table and, in this case was in a hury to post my code. I just updated my query to include the tally table as you showed above: 303 reads is now 146 reads. :-)

-- Alan Burstein



Best practices for getting help on SQLServerCentral
Need to split a string? Try DelimitedSplit8K or DelimitedSplit8K_LEAD (SQL 2012+)
Need a pattern-based splitter? Try PatternSplitCM
Need to remove or replace those unwanted characters? Try PatExclude8K and PatReplace8K.

"I can't stress enough the importance of switching from a 'sequential files' mindset to 'set-based' thinking. After you make the switch, you can spend your time tuning and optimizing your queries instead of maintaining lengthy, poor-performing code. " -- Itzek Ben-Gan 2001
Alan.B
Alan.B
SSCrazy
SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)SSCrazy (2.2K reputation)

Group: General Forum Members
Points: 2242 Visits: 7426
Jeff Moden (1/9/2013)
Alan.B (1/9/2013)
[quote]AndrewSQLDBA (1/9/2013)
Its worth noting that the following is sargable.
LIKE '%abc%'


Did you mean "NOT" SARGable because it sure doesn't look SARGable from here. ;-) And, I agree... nice use of NTILE.


Thank you very much Jeff. One year ago I had never heard of windows functions, set-based SQL, or a tally table. I think I'm starting to get it and hope to someday be able to write queries like you, Dwain, Lynn and others on SSC.

Yes - I meant NOT SARGable.

-- Alan Burstein



Best practices for getting help on SQLServerCentral
Need to split a string? Try DelimitedSplit8K or DelimitedSplit8K_LEAD (SQL 2012+)
Need a pattern-based splitter? Try PatternSplitCM
Need to remove or replace those unwanted characters? Try PatExclude8K and PatReplace8K.

"I can't stress enough the importance of switching from a 'sequential files' mindset to 'set-based' thinking. After you make the switch, you can spend your time tuning and optimizing your queries instead of maintaining lengthy, poor-performing code. " -- Itzek Ben-Gan 2001
Go


Permissions

You can't post new topics.
You can't post topic replies.
You can't post new polls.
You can't post replies to polls.
You can't edit your own topics.
You can't delete your own topics.
You can't edit other topics.
You can't delete other topics.
You can't edit your own posts.
You can't edit other posts.
You can't delete your own posts.
You can't delete other posts.
You can't post events.
You can't edit your own events.
You can't edit other events.
You can't delete your own events.
You can't delete other events.
You can't send private messages.
You can't send emails.
You can read topics.
You can't vote in polls.
You can't upload attachments.
You can download attachments.
You can't post HTML code.
You can't edit HTML code.
You can't post IFCode.
You can't post JavaScript.
You can post emoticons.
You can't post or upload images.

Select a forum

































































































































































SQLServerCentral


Search