I have to execute queries to select rows where the composite key is lexicographically less than or greater than some given tuple of values:
SELECT TOP 100
*
FROM PALISBSD
WHERE (recbsd_key_bsd_key_bsd1_bsd_jar < '03'
OR (recbsd_key_bsd_key_bsd1_bsd_jar = '03'
AND (recbsd_key_bsd_key_bsd1_bsd_pro < 'L'
OR (recbsd_key_bsd_key_bsd1_bsd_pro = 'L'
AND (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst < 'C'
OR (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst = 'C'
AND (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl < '00017004'
OR (recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl = '00017004'
AND (recbsd_key_bsd_key_bsd1_bsd_linr < '0001'
OR (recbsd_key_bsd_key_bsd1_bsd_linr = '0001'
AND (recbsd_key_bsd_key_bsd1r_bsd_sa < 'D'
OR (recbsd_key_bsd_key_bsd1r_bsd_sa = 'D'
AND (recbsd_key_bsd_key_bsd1r_bsd_an < 'PTZ')))))))))))))
ORDER BY recbsd_key_bsd_key_bsd1_bsd_jar DESC,
recbsd_key_bsd_key_bsd1_bsd_pro DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_kst DESC,
recbsd_key_bsd_key_bsd1_bsd_az1_bsd_azl DESC,
recbsd_key_bsd_key_bsd1_bsd_linr DESC,
recbsd_key_bsd_key_bsd1r_bsd_sa DESC,
recbsd_key_bsd_key_bsd1r_bsd_an DESC;
A clustered index exists that contains all the columns named here, in exactly this order. However its often not used to perform a seek. In fact I can accelerate a lot, but not all of my queries by providing the WITH (FORCESEEK)
hint or by prefixing the where term with something like recbsd_key_bsd_key_bsd1_bsd_jar <= '03' AND
.
My question is: Is there a better way to express lexicographical comparison, so MS SQL Server will better utilize the indices for the comparison? In Postgres this would be expressed via tuple comparison (col1, col2) < ('FOO', 'BAR')
, but no such feature exists in MS SQL Server.
Edit: I cannot create a concatenated computed column, because the key might contain non-character fields as well.