我试图在SQL中使用alpha;但是,我希望它只基于单词的开头。我在Microsoft SQL Server 2005上使用T-SQL。
我当前的SQL是:
SELECT * FROM table WHERE LEFT(word,1) BETWEEN 'a' AND 't
但是,这只适用于第一个字母。我想扩展它以适应任何词语的开头。例如,在'a'和'ter'之间。 现在,我正在动态构建它,所以我可以这样做:
SELECT * FROM table WHERE LEFT(word,1) >= 'a' AND LEFT(word,3) <= 'ter'
但是,我想知道在SQL中是否有一种更简单的方法可以在它之间建立一个动态的开头词。
EDIT :::
跟进问题,小于检查值长度的单词应该被认为小于中间。例如,我不像mem那么单词&lt; 'mem'应该包括我。
EDIT ::: 正如建议的那样尝试使用填充。以下确实有效;然而,添加的'a'可能会导致问题。例如,如果我们想要'a'和'mera'之间的单词并且被检查的单词是'mer',那么这将被包括在内,因为'mer'的左边裁剪变成了带有添加字符的'mera'。我想要一个不包含此问题的解决方案。
DECLARE @lb varchar(50)
DECLARE @ub varchar(50)
SET @lb='ly'
SET @ub='z'
SELECT name
FROM table
WHERE
LEFT(
CASE
WHEN LEN(name) < LEN(@lb) THEN name+REPLICATE('a',LEN(@lb)-LEN(name))
ELSE name
END,
LEN(@lb)
) >= @lb
AND
LEFT(CASE
WHEN LEN(name) < LEN(@ub) THEN name+REPLICATE('a',LEN(@ub)-LEN(name))
ELSE name
END,
LEN(@ub)
) <= @ub
EDIT ::: 尝试解决方案,虽然CASE很重。 Mack的解决方案更好,尽管这也有效。 LEFT('andy',200000)将返回'andy',而不是像OO语言那样的错误,我没想到的行为。
DECLARE @lb varchar(50)
DECLARE @ub varchar(50)
SET @lb='a'
SET @ub='lyar'
SELECT *
FROM testtable
WHERE
CASE
WHEN LEN(word) < LEN(@lb) THEN 0
WHEN LEFT(word, LEN(@lb)) >= @lb THEN 1
ELSE 0
END = 1
AND
CASE
WHEN LEN(word) < LEN(@ub) THEN
CASE
WHEN LEFT(@ub,LEN(word)) = word THEN 1
ELSE 0
END
WHEN LEFT(word, LEN(@ub)) <= @ub THEN 1
ELSE 0
END = 1
提前致谢!
答案 0 :(得分:2)
这应该有效:
SELECT * FROM table WHERE LEFT(word,3) BETWEEN 'a' AND 'ter'
没有理由为什么BETWEEN不能将你的三个字母的数据字符串与一个字母的'a'进行比较。任何'axx'本身都会“大于”只是'a',因此将被包括在内。
答案 1 :(得分:1)
如果我理解你,你就是想把它变成一个过程。如果是这样的话,你所拥有的东西将在一个过程中工作,几乎没有变化。类似下面的内容(未经测试)...
CREATE PROC myProc(@low varchar(30), @high varchar(30)) AS
SELECT * FROM table WHERE
(LEN(word) >= LEN(@low)
AND
(LEN(word) >= LEN(@high)
AND
(LEFT(word, LEN(@low)) >= @low)
AND
LEFT(word, LEN(@high)) <= @high
当'word'比任何一个参数都短时,还有其他条件可以排除记录。否则,您将在LEFT功能上出错。这可能不是100%,但应该让你接近。
答案 2 :(得分:1)
您需要使用STUFF功能来明确地实现您的目标。 如果您按照链接说明它会删除字符串末尾的指定数量的字符,并将其替换为另一个字符串。结合LEN功能,我们可以帮助您上路。
--Test Data
DECLARE @table AS TABLE (word char(10))
INSERT INTO @table VALUES ('me')
INSERT INTO @table VALUES ('mem')
INSERT INTO @table VALUES ('tap')
INSERT INTO @table VALUES ('t')
DECLARE @minword char(5)
DECLARE @maxword char(5)
SET @minword='ai'
SET @maxword='t'
--SET @maxword='tb'--(remove the rem at the start of this line to unlock an extra test for comparison...)
--Query
SELECT word
FROM @table
WHERE STUFF(word, LEN(word)+1, 5, 'aaaaa') BETWEEN STUFF(@minword, LEN(@minword)+1, 5, 'aaaaa')
AND STUFF(@maxword, LEN(@maxword)+1, 5, 'aaaaa')
基于修订要求的替代解决方案:
DECLARE @testtable AS TABLE (word varchar(20))
INSERT INTO @testtable VALUES ('ly')
INSERT INTO @testtable VALUES ('Ly')
INSERT INTO @testtable VALUES ('Zoo')
INSERT INTO @testtable VALUES ('r')
INSERT INTO @testtable VALUES ('traci')
DECLARE @minword varchar(20)
DECLARE @maxword varchar(20)
SET @minword='ly'
SET @maxword='zol'
SELECT word, LEFT(word,LEN(@minword)), LEFT(word,LEN(@maxword)), @minword, @maxword
FROM @testtable
WHERE LEFT(word,LEN(@minword))>=@minword
AND LEFT(word,LEN(@maxword))<=@maxword
答案 3 :(得分:0)
我相信我找到了一个有效的解决方案。我不确定这里的速度牺牲,但数据库仍然很小,所以在我的具体情况下这不是问题。
我正在使用C#来构建带参数的SQL字符串。 @lb是下限单词部分。 @rb是上限单词部分。 where子句是包含的,但可以根据需要轻松更改为exclusive。
SELECT * FROM table
WHERE
CASE
WHEN LEN(word) < LEN(@lb) THEN 0
WHEN LEFT(word, LEN(@lb)) >= @lb THEN 1
ELSE 0
END = 1
AND
CASE
WHEN LEN(word) < LEN(@rb) THEN 1
WHEN LEFT(word, LEN(@rb)) <= @rb THEN 1
ELSE 0
END = 1