2015-06-18 13 views
5

Tôi có cột BIGINT mà tôi muốn thực hiện đối sánh từng phần.SQL Thích/Chứa trên cột LỚN

ví dụ: @search = 1 phải trả về tất cả các bản ghi trong đó số đầu tiên là 1 (1, 11, 100 v.v.). Về cơ bản giống như một Varchar LIKE.

Tôi đã thử:

DECLARE @search VARCHAR 
SET @search = '1' 

SET @search = '1%' 

Và sử dụng:

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

Thêm một %-@search không giúp. Bất kỳ ý tưởng làm thế nào để thực hiện điều này?

EDIT: nó có vẻ là biến. Nếu tôi mã cứng chuỗi trong mệnh đề WHERE tôi nhận được kết quả mà tôi đang tìm kiếm.

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

này mang lại cho tôi tất cả hồ sơ với một id 14 * (14, 140, 1400 vv).

+1

bạn có thể đăng mã của mình bằng '%' được thêm vào không? – Tim3880

+0

Đã thêm chi tiết. Xin lỗi, nên đã có nó ngay từ đầu. – hsimah

+1

Bạn nhận được kết quả gì khi bạn chỉ chọn bảng CAST (id as Varchar) FROM? –

Trả lời

6

Hãy thử điều này thay vì:

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

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

Khi đúc để VARCHAR, bạn nên luôn luôn xác định độ dài. Nếu bạn không xác định độ dài, SQL-Server sẽ chỉ định một cho bạn. Đôi khi nó sẽ là 1 người khác, nó sẽ là 30. Đọc this để biết thêm thông tin.

+0

Cảm ơn bạn đã trả lời. Điều này làm việc cho @search = '1' nhưng khi tôi sử dụng '@search = '14' tôi vẫn nhận được 1, 10, 11, v.v. Bất kỳ ý tưởng nào? – hsimah

+1

Xem chỉnh sửa của tôi. Bạn phải chỉ định độ dài trong tuyên bố của mình. –

+0

Như tôi đã nhận xét về một câu trả lời tương tự, SQL không phải là sở trường của tôi. Khi tôi khai báo kích thước cho cụm từ tìm kiếm, nó thực sự hoạt động. Cảm ơn bạn rất nhiều vì giải pháp. – hsimah

0

này có thể giúp:

like 1% tương đương với: bất cứ điều gì lớn hơn hoặc bằng 10, nếu bạn đang so sánh số. Vì vậy, bạn có thể muốn làm tương tự như sau:

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

truy vấn trong OP đang sử dụng toán tử 'LIKE' để so sánh với chuỗi' '1%' '. Ký tự '%' là một thẻ tự nhiên trong SQL Server. –

+0

Tôi biết những gì 'like' là, tôi đã cố gắng không có nó' cast' 'int' để' varchar', Việc so sánh sẽ rất kém hiệu suất. Nó sẽ không sử dụng bất kỳ 'chỉ mục' nào. – ANewGuyInTown

+0

Rất tiếc. Tôi đã suy nghĩ điều gì khác, tôi sẽ chỉnh sửa bài đăng của mình. – ANewGuyInTown

2

Sự cố xảy ra với @search của bạn. Hãy thử như dưới đây thay vì

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

Chọn Query

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

(OR) như dưới đây

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

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

Cảm ơn bạn đã trả lời. Điều này làm việc cho '@search = '1'' nhưng khi tôi sử dụng' @search =' 14 'tôi vẫn nhận được 1, 10, 11, v.v. Bất kỳ ý tưởng nào? – hsimah

+1

đó là vì dòng 'DECLARE @search VARCHAR;' không có bất kỳ đặc tả kích thước nào, nó luôn lấy ký tự đầu tiên là 1 trong trường hợp này. – Rahul

+0

Tôi hiểu. SQL không phải là sở trường của tôi, vì vậy những loại gotchas này luôn bắt tôi. Khi tôi tuyên bố kích thước nó thực sự làm việc. Cảm ơn bạn rất nhiều. – hsimah

3

Thay vì sử dụng các nhà điều hành LIKE thử sử dụng các chức năng LEFT. Điều này sẽ trả về phần bên trái của chuỗi ký tự với số ký tự được chỉ định.

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

Tôi không chắc chắn, nhưng tôi đã có giả định này là sẽ có hiệu suất tốt hơn so với sử dụng các nhà điều hành LIKE, đặc biệt là kể từ khi bạn biết bạn chỉ muốn so sánh với các nhân vật bắt đầu. Thường thì việc sử dụng hàm trong mệnh đề WHERE thường có thể gây ra hiệu suất kém do truy vấn không thể tận dụng bất kỳ chỉ mục nào có thể tồn tại trên cột. Tuy nhiên trong trường hợp này truy vấn gọi hàm CAST, vì vậy lợi ích của chỉ mục đã bị mất.

Chỉnh sửa: Nếu so sánh cần cho số chữ số thay đổi, thì bạn có thể sử dụng hàm LEN để xác định số ký tự cho hàm LEFT để trả về.

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

Cảm ơn câu trả lời. Cụm từ tìm kiếm sẽ đến từ đầu vào của người dùng, do đó độ dài sẽ dài bằng chuỗi mà họ cung cấp từ giao diện người dùng. Tôi có thể nhận được một chiều dài của chuỗi và sử dụng điều đó, mặc dù. Câu trả lời thay thế tốt. – hsimah

+0

Chúng tôi được đẩy thời gian cho bản phát hành này, nhưng tôi sẽ chạy một số thống kê hiệu suất về câu trả lời này so với chấp nhận vào tuần tới. – hsimah

+0

Tôi muốn được quan tâm để biết kết quả của bạn nếu bạn có cơ hội để đánh giá hiệu suất của hai phương pháp tiếp cận. Thường thì việc sử dụng hàm trong mệnh đề WHERE thường có thể gây ra hiệu suất kém do truy vấn không thể tận dụng bất kỳ chỉ mục nào có thể tồn tại trên cột. Tuy nhiên, trong trường hợp này truy vấn đang truyền cột đến một varchar, vì vậy lợi ích của chỉ mục đã bị mất. –

3

Không thích nhưng phải làm. Thay thế x bằng 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

Tôi đoán điều này sẽ có hiệu suất tốt hơn so với các giải pháp dựa trên 'CAST' vì chỉ mục có thể được sử dụng (nếu nó tồn tại). Các giải pháp 'CAST' sẽ phải truyền trên mọi hàng BIGINT để đánh giá vị từ. – g2server

1

Có cách để thực hiện việc này mà không cần chuyển đổi thành VARCHAR(30) - nhưng tôi đã không kiểm tra xem hiệu suất có thực sự tốt hơn hay không. LOG10() không phải là rẻ, nhưng phân chia số nguyên là. Vì vậy, thử nghiệm được bảo hành.

Given:

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 

Toán học điên:

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; 

Về cơ bản, các cặp LOG10() xác định số chữ số để chuyển ngay (thông qua phân chia số nguyên) để chỉ những số mong muốn của chữ số vẫn còn.

+0

Chà. Đó là loại toán học đau đầu của tôi! Tuy nhiên, giải pháp thú vị lại rất mới lạ. – hsimah

Các vấn đề liên quan