简体   繁体   English

使用HAVING搜索字符串的一部分

[英]Using HAVING to search for part of a string

I was wondering if it's ok to use sql HAVING to find certain rows in a table. 我想知道是否可以使用sql HAVING在表中查找某些行。

Example: 例:

I have a table with three columns -> ID (int, primary key), type and size (varchar) 我有一个包含三列的表-> ID(int,主键),类型和大小(varchar)

One row looks like this: 一行看起来像这样:

ID     type          size 
1      15; 16; 17    4; 8

And to select a row that has a type 15 i use the following query 并选择具有类型15的行,请使用以下查询

SELECT * FROM tableName WHERE type HAVING "15"

Is it ok to do it this way, or is there a better way? 这样可以行吗,还是有更好的方法?

Thank you in advance! 先感谢您!

Your syntax would not work in most databases. 您的语法不适用于大多数数据库。 It would happen to work in MySQL, because MySQL allows having clauses for non-aggregation queries. 它会发生在工作中的MySQL,因为MySQL允许具有非聚集查询条款。

Even in MySQL, the clause would do nothing, because "15" is simply a number. 即使在MySQL中,该子句也不起作用,因为“ 15”只是一个数字。 In a boolean context, non-zero numbers are interpreted as "true" and zeros as "false". 在布尔上下文中,非零数字解释为“ true”,零数字解释为“ false”。 What you want to use is where : 你想用的是where

select *
from table
where type = 15;

Alas, this will not work for you because you have a messed up data structure. las,这对您不起作用,因为您的数据结构混乱。 You should not be storing lists in strings. 您不应该将列表存储在字符串中。 You should be storing them in junction tables (you can Google the term to learn more about it). 您应该将它们存储在联结表中(可以使用Google术语来了解更多信息)。 So, the best way is to store the data correctly. 因此,最好的方法是正确存储数据。

If you have to use this data structure (say, you are on a deserted island and they won't send you food unless you write queries on such a database), then you can use like or find_in_set() . 如果您必须使用此数据结构(例如,您在一个荒岛上,除非您在这样的数据库上编写查询,否则它们不会向您发送食物),则可以使用likefind_in_set() The first is easier in this case: 在这种情况下,第一个比较容易:

where concat('; ', type, '; ') like '%; 15; %'

No, you will have to do a LIKE 不,你必须做个LIKE

CREATE TABLE #test(
ID int, 
[type] varchar(255), 
[size] varchar(255)
);

insert into #test VALUES(1, '15; 16; 17;', '4; 8;')

select * from #test where [type] like '%15%'

Returns 退货

ID   type       Size
1   15; 16; 17; 4; 8;

Or you could combine an IN statement with a Split function: 或者,您可以将IN语句与Split函数结合使用:

Usage 用法

declare @val varchar(255);
set @val = 15

select * from #test t where @val in (select Value from [dbo].udf_Split(t.[type], ';') as i)

Function 功能

CREATE Function [dbo].[udf_Split]
(   
    @DelimitedList nvarchar(max)
    , @Delimiter nvarchar(2)
)
RETURNS TABLE 
AS
RETURN 
    (
    With CorrectedList As
        (
        Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            + @DelimitedList
            + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            As List
            , Len(@Delimiter) As DelimiterLen
        )
        , Numbers As 
        (
        Select TOP( Coalesce(DataLength(@DelimitedList)/2,0) ) Row_Number() Over ( Order By c1.object_id ) As Value
        From sys.columns As c1
            Cross Join sys.columns As c2
        )
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
        , Substring (
                    CL.List
                    , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen     
                    , CharIndex(@Delimiter, CL.list, N.Value + 1)                           
                        - ( CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen ) 
                    ) As Value
    From CorrectedList As CL
        Cross Join Numbers As N
    Where N.Value <= DataLength(CL.List) / 2
        And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
    )

Returns 退货

ID   type       Size
1   15; 16; 17; 4; 8;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM