2010-05-27 48 views
13

Có cách nào thanh lịch trong SQL Server để tìm tất cả các ký tự riêng biệt trong một cột varchar (50) đơn, trên tất cả các hàng không?SQL: cách lấy tất cả các ký tự riêng biệt trong một cột, trên tất cả các hàng

Tiền thưởng điểm nếu nó có thể được thực hiện mà không con trỏ :)

Ví dụ, nói dữ liệu của tôi chứa 3 hàng:

productname 
----------- 
product1 
widget2 
nicknack3 

Việc kiểm kê riêng biệt của nhân vật sẽ là "productwigenka123"

+0

Thứ tự của các ký tự có quan trọng không? –

+0

Không, các ký tự có thể được trả về theo thứ tự bất kỳ. – frankadelic

Trả lời

2

Cho rằng cột của bạn là VARCHAR, nó có nghĩa là nó chỉ có thể lưu trữ các ký tự từ mã 0 đến 255, trên bất kỳ trang mã nào bạn có. Nếu bạn chỉ sử dụng phạm vi mã ASCII 32-128, thì bạn chỉ có thể thấy nếu bạn có bất kỳ ký tự nào 32-128, từng cái một. Các truy vấn sau đây không rằng, nhìn vào sys.objects.name:

with cteDigits as (
    select 0 as Number 
    union all select 1 as Number 
    union all select 2 as Number 
    union all select 3 as Number 
    union all select 4 as Number 
    union all select 5 as Number 
    union all select 6 as Number 
    union all select 7 as Number 
    union all select 8 as Number 
    union all select 9 as Number) 
, cteNumbers as (
    select U.Number + T.Number*10 + H.Number*100 as Number 
    from cteDigits U 
    cross join cteDigits T 
    cross join cteDigits H) 
, cteChars as (
    select CHAR(Number) as Char 
    from cteNumbers 
    where Number between 32 and 128) 
select cteChars.Char as [*] 
from cteChars 
cross apply (
    select top(1) * 
    from sys.objects 
    where CHARINDEX(cteChars.Char, name, 0) > 0) as o 
for xml path(''); 
1

Nếu bạn có bảng Số hoặc Tally chứa danh sách số nguyên tuần tự, bạn có thể làm một cái gì đó như:

Select Distinct '' + Substring(Products.ProductName, N.Value, 1) 
From dbo.Numbers As N 
    Cross Join dbo.Products 
Where N.Value <= Len(Products.ProductName) 
For Xml Path('') 

Nếu bạn đang sử dụng SQL Server 2005 và xa hơn nữa, bạn có thể tạo bảng số của bạn một cách nhanh chóng bằng cách sử dụng CTE:

With Numbers As 
    (
    Select Row_Number() Over (Order By c1.object_id) As Value 
    From sys.columns As c1 
     Cross Join sys.columns As c2 
    ) 
Select Distinct '' + Substring(Products.ProductName, N.Value, 1) 
From Numbers As N 
    Cross Join dbo.Products 
Where N.Value <= Len(Products.ProductName) 
For Xml Path('') 
17

Dưới đây là một truy vấn mà trả về từng nhân vật như một hàng riêng biệt, cùng với số lần xuất hiện . Giả sử bảng của bạn được gọi là 'Sản phẩm'

WITH ProductChars(aChar, remain) AS (
    SELECT LEFT(productName,1), RIGHT(productName, LEN(productName)-1) 
     FROM Products WHERE LEN(productName)>0 
    UNION ALL 
    SELECT LEFT(remain,1), RIGHT(remain, LEN(remain)-1) FROM ProductChars 
     WHERE LEN(remain)>0 
) 
SELECT aChar, COUNT(*) FROM ProductChars 
GROUP BY aChar 

Để kết hợp chúng tất cả để một hàng duy nhất, (như đã nêu trong câu hỏi), thay đổi thức SELECT để

SELECT aChar AS [text()] FROM 
    (SELECT DISTINCT aChar FROM ProductChars) base 
FOR XML PATH('') 

Trên đây sử dụng một đẹp Hack Tôi đã tìm thấy here, mô phỏng số GROUP_CONCAT từ MySQL.

Mức đệ quy đầu tiên không được kiểm soát để truy vấn không trả lại chuỗi trống trong đầu ra.

+0

Nhận "Tuyên bố đã chấm dứt. Đợt đệ quy tối đa 100 đã cạn kiệt trước khi hoàn thành câu lệnh". – Riga

3

Sử dụng này (sẽ làm việc trên bất kỳ RDBMS CTE có khả năng):

create table prod as 
select x.v from (values('product1'),('widget2'),('nicknack3')) as x(v); 

Query Kiểm tra:

with a as 
(
    select v, '' as x, 0 as n from prod 
    union 
    select v, substring(v,n+1,1) as x, n+1 as n from a where n < len(v) 
) 
select v, x, n from a -- where n > 0 
order by v, n 

Truy vấn cuối cùng:

with a as 
(
    select v, '' as x, 0 as n from prod 
    union 
    select v, substring(v,n+1,1) as x, n+1 as n from a where n < len(v) 
) 
select distinct x from a where n > 0 
order by x 

Phiên bản Oracle:

with a(v,x,n) as 
(
    select v, '' as x, 0 as n from prod 
    union all 
    select v, substr(v,n+1,1) as x, n+1 as n from a where n < length(v) 
) 
select distinct x from a where n > 0 
Các vấn đề liên quan