2015-06-18 9 views
5

Ich habe eine BIGINT-Spalte, die ich teilweise angleichen möchte.SQL Like/Contains auf BIGINT Spalte

z.B. @search = 1 sollte alle Datensätze zurückgeben, bei denen die erste Zahl 1 ist (1, 11, 100 usw.). Grundsätzlich das gleiche wie ein VARCHAR LIKE.

Ich habe versucht:

DECLARE @search VARCHAR 
SET @search = '1' 

und

SET @search = '1%' 

und gebraucht:

SELECT 
    id FROM table 
WHERE 
    CAST(id AS varchar) LIKE @search 

eine %-@search Hinzufügen hilft nicht. Irgendwelche Ideen, wie man das erreicht?

EDIT: Es scheint die Variable zu sein. Wenn ich die Zeichenfolge in der WHERE-Klausel fest codiere, bekomme ich die Ergebnisse, nach denen ich suche.

SELECT id FROM table WHERE CAST(id AS VARCHAR) LIKE '14%' 

Das gibt mir alle Datensätze mit einem id von 14 * (14, 140, 1400 usw.).

+1

können Sie Ihren Code mit dem hinzugefügten '%' veröffentlichen? – Tim3880

+0

Hinzugefügt mehr Details. Entschuldigung, sollte es von Anfang an gehabt haben. – hsimah

+1

Welche Ergebnisse erhalten Sie, wenn Sie nur CAST (ID als Varchar) FROM Tabelle auswählen? –

Antwort

6

Versuchen Sie stattdessen:

DECLARE @search VARCHAR(10) 
SET @search = '1' 

SELECT id FROM table WHERE CAST(id AS VARCHAR(10)) LIKE @search + '%' 

Wann VARCHAR Gießen, sollten Sie immer die Länge angeben. Wenn Sie keine Länge definieren, wird SQL-Server eine für Sie zuweisen. Manchmal ist es 1 andere es wird 30 sein. Lesen Sie this für weitere Informationen.

+0

Danke für die Antwort. Das funktioniert für @search = '1', aber wenn ich '@search = '14' verwende, bekomme ich immer noch 1, 10, 11 usw. Irgendwelche Ideen? – hsimah

+1

Siehe meine Bearbeitung. Sie müssen eine Länge in Ihrer Deklaration angeben. –

+0

Als ich eine ähnliche Antwort kommentierte, ist SQL nicht meine Stärke. Wenn ich eine Größe für den Suchbegriff deklariere, funktioniert es tatsächlich. Vielen Dank für die Lösung. – hsimah

0

helfen Dies kann:

like 1% entspricht: etwas größer oder gleich 10, wenn Sie numerische vergleichen. So können Sie auf folgende ähnliche tun:

SELECT 
    id FROM table 
WHERE 
    id >= @search*10 [email protected] is of course int 
+0

Die Abfrage im OP verwendet den Operator 'LIKE', um ihn mit dem String' '1%' 'zu vergleichen. Das '%' - Zeichen ist eine Platzhalter in SQL Server. –

+0

Ich weiß, was 'like' ist, ich habe versucht, es' cast' 'int' nicht' varchar' zu haben, Der Vergleich wäre sehr schlecht in der Leistung. Es werden auch keine Indizes verwendet. – ANewGuyInTown

+0

Hoppla. Ich habe etwas anderes gedacht, ich werde meinen Beitrag bearbeiten. – ANewGuyInTown

2

Problem ist mit Ihrem @search. Versuchen Sie, wie unten statt

create table aaa (id bigint); 
insert into aaa values(1),(11),(100),(111),(1111),(2222); 

Auswahlabfrage

SELECT 
    id FROM aaa 
WHERE 
    CAST(id AS varchar(1000)) LIKE '1%'; 

(OR) wie unten

DECLARE @search VARCHAR; 
SET @search = '1'; 

SELECT 
    id FROM aaa 
WHERE 
    CAST(id AS varchar(1000)) LIKE @search + '%'; 
+0

Danke für die Antwort. Das funktioniert für '@search = '1'', aber wenn ich' @search =' 14 'verwende, bekomme ich immer noch 1, 10, 11 usw. Irgendwelche Ideen? – hsimah

+1

das ist wegen der Zeile 'DECLARE @search VARCHAR;' ohne jede Größenangabe nimmt es immer erstes Zeichen, das in diesem Fall 1 ist. – Rahul

+0

Ich verstehe. SQL ist nicht meine Stärke, also fangen mich diese Arten von Fallen immer auf. Wenn ich die Größe deklariere, funktioniert es tatsächlich. Ich danke dir sehr. – hsimah

3

Statt den LIKE Betreiber mit der LEFT Funktion Versuchen Sie es mit. Dadurch wird der linke Teil einer Zeichenfolge mit der angegebenen Anzahl von Zeichen zurückgegeben.

SELECT id 
FROM table 
WHERE LEFT(CAST(id AS varchar), 1) = '1' 

Ich bin nicht sicher, aber ich habe davon ausgehen, habe dies wird besonders eine bessere Leistung als mit dem LIKE Operator, da Sie wissen, Sie wollen nur auf die Anfangszeichen zu vergleichen. Die Verwendung einer Funktion in der WHERE-Klausel kann häufig zu Leistungseinbußen führen, da die Abfrage eventuell vorhandene Indizes für die Spalte nicht nutzen kann. In diesem Fall jedoch die Abfrage Aufruf der CAST-Funktion, so ist der Vorteil des Index bereits verloren.

Bearbeiten: Wenn der Vergleich für eine variable Anzahl von Ziffern erforderlich ist, können Sie mithilfe der LEN-Funktion die Anzahl der Zeichen für die zurückzugebende LEFT-Funktion ermitteln.

SELECT id 
FROM table 
WHERE LEFT(CAST(id AS varchar),LEN(@search)) = @search 
+0

Danke für die Antwort. Der Suchbegriff wird von einer Benutzereingabe kommen, also ist die Länge so lang wie die Zeichenfolge, die sie vom Frontend liefern. Ich könnte aber eine Länge der Saite bekommen und diese benutzen. Gute alternative Antwort. – hsimah

+0

Wir sind auf Zeit für diese Veröffentlichung gedrängt, aber ich werde einige Performance-Statistiken über diese vs akzeptierte Antwort nächste Woche laufen lassen. – hsimah

+0

Ich wäre an Ihren Ergebnissen interessiert, wenn Sie die Möglichkeit haben, die Leistung der beiden Ansätze zu bewerten. Die Verwendung einer Funktion in der WHERE-Klausel kann häufig zu Leistungseinbußen führen, da die Abfrage eventuell vorhandene Indizes für die Spalte nicht nutzen kann. In diesem Fall wird die Spalte jedoch durch die Abfrage in ein Varchar umgewandelt, sodass der Vorteil des Index bereits verloren ist. –

3

Nicht ein wie aber sollte es tun. Ersetzen Sie x durch ID.

WHERE 
(x >= 1000000000000000000 AND x < 2000000000000000000) OR 
(x >= 100000000000000000 AND x < 200000000000000000) OR 
(x >= 10000000000000000 AND x < 20000000000000000) OR 
(x >= 1000000000000000 AND x < 2000000000000000) OR 
(x >= 100000000000000 AND x < 200000000000000) OR 
(x >= 10000000000000 AND x < 20000000000000) OR 
(x >= 1000000000000 AND x < 2000000000000) OR 
(x >= 100000000000 AND x < 200000000000) OR 
(x >= 10000000000 AND x < 20000000000) OR 
(x >= 1000000000 AND x < 2000000000) OR 
(x >= 100000000 AND x < 200000000) OR 
(x >= 10000000 AND x < 20000000) OR 
(x >= 1000000 AND x < 2000000) OR 
(x >= 100000 AND x < 200000) OR 
(x >= 10000 AND x < 20000) OR 
(x >= 1000 AND x < 2000) OR 
(x >= 100 AND x < 200) OR 
(x >= 10 AND x < 20) OR 
(x = 1) 
+0

Ich vermute, das wird eine bessere Leistung als die 'CAST' basierten Lösungen haben, da ein Index verwendet werden kann (wenn es existiert). Die "CAST" -Lösungen müssen jede BIGINT-Zeile umwandeln, um das Prädikat zu bewerten. – g2server

1

Es gibt einen Weg, dies zu VARCHAR(30) ohne Umwandlung zu tun - aber ich habe es nicht testen, ob die Leistung tatsächlich besser ist. LOG10() ist nicht billig, aber ganzzahlige Division ist. Das Testen ist also gerechtfertigt.

Gegeben:

create table aaa (id bigint); 
insert into aaa values(1),(11),(100),(111),(1111),(2222),(1234),(4531),(1345134),(64513),(6451999123); 

declare @want int = 64 -- and these are your starting digits 

Die verrückt math:

select id 
from dbo.aaa 
WHERE id/(CASE WHEN (LOG10(id) -CEILING(LOG10(@want))) > 1 
    THEN POWER(10 , CEILING(log10(id-1)-CEILING(LOG10(@want)))) 
    ELSE 1 END) = @want; 

Grundsätzlich ist das Paar von LOG10() bestimmt die Anzahl der Ziffern rechts zu verschieben (durch ganzzahlige Division), so dass nur die gewünschte Anzahl von Ziffern bleiben.

+0

Wow. Diese Art von Mathe schmerzt meinen Kopf! Interessante Lösung, aber sehr neuartig. – hsimah