请帮我选择前1名
像这样的数据
Code Amp Price
-----------------------
00001 10 1000
00002 75-100 1500
00003 50-60 1200
00004 15 1100
注意:列Amp
的数据类型为VarChar
我想选择Amp 75,我希望得到的价格是1500
所以我使用这句话:
SELECT TOP 1 *
FROM Cable
WHERE (Amp <= '75')
ORDER BY Amp DESC
但我得到的结果价格是1200是代码:00003(错误)的记录,其实我想要的结果是代码:00002,价格是1500
但是如果我想用Amp 76选择,结果是正确的语法:
SELECT TOP 1 *
FROM Cable
WHERE (Amp <= '75')
ORDER BY Amp DESC
我案件的真正选择是什么?请帮帮我
答案 0 :(得分:2)
几乎任何解析/拆分功能都可以,并且与Cross Apply相结合,它就变成了一个小问题
- 没有解析功能很容易
Declare @Cable table (Code varchar(25),Amp varchar(50),Price int)
Insert Into @Cable values
('00001','10', 1000),
('00002','75-100',1500),
('00003','50-60', 1200),
('00004','15', 1100)
Select Top 1 A.*
From @Cable A
Cross Apply [dbo].[udf-Str-Parse](A.Amp,'-') B
Where RetVal<=76 --<< Notice we are testing for 76
Order By Price Desc
返回
Code Amp Price
00002 75-100 1500
感兴趣的UDF
CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(25))
Returns Table
As
Return (
with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
cte3(N) As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)
Select RetSeq = Row_Number() over (Order By A.N)
,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
From cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Much faster than str-Parse, but limited to 8K
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
答案 1 :(得分:1)
如果您必须使用此现有数据类型和表结构,则下面的查询可能适合您。
SELECT TOP 1 *
FROM Cable
WHERE (SUBSTRING(Amp,1,IIF((CHARINDEX('-',Amp)-1)>0,(CHARINDEX('-',Amp)-1),0 ) ) <=75)
ORDER BY Amp DESC
答案 2 :(得分:0)
如果您使用的是SQL Server 2008及更高版本,请尝试以下操作:
SELECT TOP 1 *
FROM Cable
WHERE isnumeric(left(Amp, 2)) = 1 and cast(left(Amp, 2) as int) <= 75
and Price = 1500
ORDER BY Amp DESC
注意:仅当您没有Amp小于10的记录时,此功能才有效。
答案 3 :(得分:0)
问题是SQL Server不会像varchar
那样对int
列进行排序。
排序问题示例:
select *
from (
select '125' as nbr
union all
select '24' as nbr
) as a
order by a.nbr asc
1小于2(每个nbr
中的第一个字符),因此它会认为125&lt; { 24(不是真的),尽管对于24应该首先出现的任何人看起来都很简单,如果列的数据类型是int
,它将如何排序。
需要做的是将amp
列拆分为范围,或最大值和最小值。使用-
作为分隔符,您可以使用charindex
将数字分开,将cast
分割为int
代替。
示例数据设置:
declare @cable table
(
code char(5) not null
, amp varchar(10) not null
, price int not null
)
insert into @cable
values
('00001','10' ,10000),
('00002','75-100' ,15000),
('00003','50-60' ,12000),
('00004','15' ,11000)
<强>答案:强>
declare @amp_nbr int = 75
select top 1 *
from (
select c.code
, cast(iif(charindex('-', c.amp, 0) > 0, left(c.amp, charindex('-', c.amp, 0) - 1), c.amp) as int) as amp_min
, cast(iif(charindex('-', c.amp, 0) > 0, right(c.amp, len(c.amp) - charindex('-', c.amp, 0)), c.amp) as int) as amp_max
, c.price
from @cable as c
) as a
where 1=1
and @amp_nbr between a.amp_min and a.amp_max
order by a.amp_min desc
之后,between
子句中的一个简单where
约束就可以了。
答案 4 :(得分:0)
感谢所有答案。我决定键入所有数据并用两个字段更改它。
00001 10 10 1000 00002 75 100 1500 00003 50 60 1200 00004 15 15 1100
单个值i在字段Amp2中输入相同然后我使用语法: SELECT * FROM电缆WHERE(Amp1和Amp2之间的65)