Reputation: 3453
I have a large table (100000+ rows) in which are 4 columns of same conceptual value.
Say a record represents a competition between players whose names are in columns A, B, C and D. And A + B plays vs C + D.
When I query that table for all competitions played by a guy named "DOE", I need to inspect the 4 column values for the name:
... Where (Column A like 'DOE%' OR Column B like 'DOE%' OR Column C like 'DOE%' OR Column D like 'DOE%') AND ... Other conditions...
And since the table is huge, I need a way to index on all those 4 columns.
I know I can create a secondary table storing each player name together with his position A, B, C or D and the main table's RowID, but I suspect there should be a better way...
Any clue from a SQLServer guru?
Upvotes: 1
Views: 290
Reputation: 4827
"I know I can create a secondary table storing each player name together
with his position A, B, C or D and the main table's RowID, but I suspect
there should be a better way..."
In a Relational Database this is the better way. Reason is, it makes your application code simpler and your DBA function simpler:
1) Index question? Index on playerID.
2) Query? Select ... from playerGames where playerId = X
3) The current design allows for only one simple query, finding all players in position A, B, C, or D, and this is still easy: Select .... from ... where position='A'
This is why database gurus will often try to point out that normalization is not some chore you do to satisfy some vague theory, but actually normalization makes your entire system simpler.
Upvotes: 1
Reputation: 20387
I would put an index on each column with the ID as an included column as @ttoni stated, and then make a covering index on the id and include the 4 columns, and then run this query:
declare @string varchar(50)
set @string='Karen'
select
a.ID
A,
B,
C,
D
from dbo.Players a
inner join
(
select
ID
from dbo.Players
where A = @string
union all
select
ID
from dbo.Players
where B = @string
union all
select
ID
from dbo.Players
where C = @string
union all
select
ID
from dbo.Players
where D = @string
) b
on a.ID=b.ID
you can switch the equal sign with like and then just add the percent to the end of the variable, it just takes a bit more processing for sql server if you do that.
here's the first index:
CREATE NONCLUSTERED INDEX [IDX_A] ON [dbo].[Players]
(
[A] ASC
)
INCLUDE ( [ID]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
and here's the covering index:
CREATE NONCLUSTERED INDEX [IDX_All] ON [dbo].[Players]
(
[ID] ASC
)
INCLUDE ( [A],
[B],
[C],
[D]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
Upvotes: 0
Reputation: 9391
Just put an index on each column (4 indexes total).
That way the server can query each index and put together the results according to the conditions. This allows for a wide range of queries and is still reasonably fast.
Upvotes: 3