Làm cách nào tôi có thể chọn từ danh sách các giá trị trong SQL Server


216

Tôi có một vấn đề rất đơn giản mà tôi không thể giải quyết. Tôi cần phải làm một cái gì đó như thế này:

select distinct * from (1, 1, 1, 2, 5, 1, 6).

Ai có thể giúp ??

Biên tập

Dữ liệu đến dưới dạng tệp văn bản từ một trong các khách hàng của chúng tôi. Nó hoàn toàn không được định dạng (nó là một dòng văn bản rất dài), nhưng có thể làm như vậy trong Excel. Nhưng nó không thực tế đối với tôi, vì tôi sẽ cần sử dụng các giá trị này trong truy vấn sql của mình. Nó không thuận tiện để làm như vậy mỗi khi tôi cần chạy một truy vấn.


Bạn có muốn chọn từ nhiều bảng hoặc chọn từ một bảng duy nhất nhưng có một giá trị cụ thể để chọn không? một số thứ như một mình id cụ thể
Anirudh Goel

Không phải những gì bạn yêu cầu, nhưng bạn có thể làm điều đó bằng ngôn ngữ khác. Ví dụ: trong PowerShell, bạn có thể làm $d = (1, 1, 1, 2, 5, 1, 6) | sort -Uniqueđể có được các giá trị riêng biệt trong một mảng $d. Dễ dàng mở rộng thành một công cụ tập tin.
Jeppe Stig Nielsen

Là điều quan trọng ở đây để có được một danh sách riêng biệt của các giá trị đó, hoặc để đưa danh sách các giá trị đó vào SQL? Như @JeppeStigNielsen nói, có nhiều cách khác để nhận các giá trị riêng biệt từ danh sách văn bản không liên quan đến SQL. Tôi đến đây để tìm cách lấy danh sách các giá trị thành tập lệnh SQL tham chiếu các bảng khác.
Rikki

Câu trả lời:


81

Cách đơn giản nhất để có được các giá trị riêng biệt của một danh sách dài các văn bản được phân tách bằng dấu phẩy sẽ là sử dụng tìm thay thế bằng UNION để lấy các giá trị riêng biệt.

SELECT 1
UNION SELECT 1
UNION SELECT 1
UNION SELECT 2
UNION SELECT 5
UNION SELECT 1
UNION SELECT 6

Áp dụng cho dòng văn bản được phân cách bằng dấu phẩy

  • Tìm và thay thế mỗi dấu phẩy bằng UNION SELECT
  • Thêm một SELECTở phía trước của tuyên bố

Bây giờ bạn nên có một truy vấn làm việc


3
không, không, tôi có một danh sách hàng trăm giá trị, theo cách thủ công nó sẽ là cực hình
Eedoh

danh sách đó đến từ đâu? Có thể dễ dàng hơn khi chỉ sao chép / dán danh sách đó trong Excel và trích xuất các giá trị riêng biệt ở đó bằng cách sử dụng dấu chéo đơn giản.
Lieven Keersmaekers

btw, tìm và thay thế cũng có thể đưa bạn đi một chặng đường dài. Thay thế mỗi dấu phẩy bằng liên kết chọn , thêm một lựa chọn ở phía trước và bạn sẽ có một truy vấn hoạt động cfr mà công đoàn tôi đã hiển thị.
Lieven Keersmaekers

1
công cụ này bằng cách thay thế dấu phẩy bằng công việc chọn lọc như một sự quyến rũ Cảm ơn rất nhiều :)
Eedoh

5
Vì lý do hiệu suất, tôi muốn giới thiệu Union-All, sau đó Group-By hoặc sử dụng Phân biệt trong lựa chọn bên ngoài của bạn.
MikeTeeVee

427

Chỉ khả dụng trên SQL Server 2008 trở lên là hàm tạo hàng theo dạng này:
Bạn có thể sử dụng

SELECT DISTINCT * FROM (VALUES (1), (1), (1), (2), (5), (1), (6)) AS X(a)

Nhiều người đã viết về, trong số đó:


66
Lưu ý phụ: Xlà bí danh cho tên bảng và alà bí danh cho tên cột;).
shA.t

11
Đây là câu trả lời đúng hơn so với câu trả lời hiện được chọn
TabNotSpaces

1
Đây là cách chung nhất, tôi đã bị làm hỏng bởi sự không lành mạnh (ARRAY []) trong pgsqlvà bây giờ đập đầu để làm cho TỪ chấp nhận các giá trị nhỏ như các bản ghi hàng sqlserver, và đây là. Rất vui khi được biết.
Ben

1
Câu trả lời tốt hơn do bí danh cột và bảng
Alfredo A.

79

Nói chung :

SELECT 
  DISTINCT 
      FieldName1, FieldName2, ..., FieldNameN
FROM
  (
    Values
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN ),
        ( ValueForField1, ValueForField2,..., ValueForFieldN )
  ) AS TempTableName ( FieldName1, FieldName2, ..., FieldNameN )

Trong trường hợp của bạn :

Select 
  distinct
  TempTableName.Field1 
From 
  (
  VALUES
    (1), 
    (1), 
    (1), 
    (2), 
    (5), 
    (1), 
    (6)
  ) AS TempTableName (Field1)

Tôi biết "select *" được coi là hình thức xấu, nhưng có lý do nào để không sử dụng select * trong trường hợp này không? Bởi vì sự trùng lặp đó của FieldName1, FieldName2, ..., FieldNameN thật kỳ cục.
Pxtl

43

Bạn đã thử sử dụng cú pháp sau đây?

select * from (values (1), (2), (3), (4), (5)) numbers(number)

5
một người dùng ẩn danh đề nghị chỉnh sửa mã thành:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612

19

Nếu bạn muốn chỉ chọn một số giá trị nhất định từ một bảng duy nhất, bạn có thể thử điều này

select distinct(*) from table_name where table_field in (1,1,2,3,4,5)

ví dụ:

select first_name,phone_number from telephone_list where district id in (1,2,5,7,8,9)

nếu bạn muốn chọn từ nhiều bảng thì bạn phải đi UNION.

Nếu bạn chỉ muốn chọn các giá trị 1, 1, 1, 2, 5, 1, 6 thì bạn phải làm điều này

select 1 
union select 1 
union select 1 
union select 2 
union select 5 
union select 1 
union select 6

1
Tôi không cần phải chọn từ một bảng, nhưng từ danh sách các giá trị này (trong ngoặc). Đó là vấn đề chính (chọn từ mảng giá trị được phân tách bằng dấu phẩy, không phải từ bảng)
Eedoh

trong trường hợp đó, giống như chúng ta có bảng DUAL trong Oracle, bạn có thể sử dụng tương tự. Nhưng vì không có DUAL nên bạn sẽ phải đi theo con đường hợp nhất. Bạn có thể thử một phương pháp khác, như bạn đã đề cập, bạn có một mảng các giá trị được phân tách bằng dấu phẩy, tại sao bạn không chèn chúng vào một bảng và sau đó sử dụng truy vấn chọn sql gọn gàng, thay vì sử dụng rất nhiều hiệp hội sql.
Anirudh Goel

14

PostgreSQL cung cấp cho bạn 2 cách để làm điều này:

SELECT DISTINCT * FROM (VALUES('a'),('b'),('a'),('v')) AS tbl(col1)

hoặc là

SELECT DISTINCT * FROM (select unnest(array['a','b', 'a','v'])) AS tbl(col1)

sử dụng phương pháp tiếp cận mảng, bạn cũng có thể làm một cái gì đó như thế này:

SELECT DISTINCT * FROM (select unnest(string_to_array('a;b;c;d;e;f;a;b;d', ';'))) AS tbl(col1)

11
Mặc dù câu hỏi không chỉ định MSSQL ...:)
tạm dừng

@halfer Câu trả lời đầu tiên được đưa ra ở đây có hiệu quả với tôi, sử dụng MSSQL 2016 trong khi các câu trả lời khác thì không. 7 năm sau
Dustytrash

9

Điều này hoạt động trên SQL Server 2005 và nếu có số lượng tối đa:

SELECT * 
FROM
  (SELECT ROW_NUMBER() OVER(ORDER BY a.id) NUMBER
  FROM syscomments a
  CROSS JOIN syscomments b) c
WHERE c.NUMBER IN (1,4,6,7,9)

2
+1 gọn gàng nhưng nó bị giới hạn ở số lượng hàng trong syscomments được nối với chính nó. Trong trường hợp của tôi đến 294849. (và bạn đã quên khác biệt.)
Lieven Keersmaekers

Bạn có thể tham gia chéo một lần nữa, nhưng thay thế dấu phẩy là giải pháp nhanh hơn nhiều.
LukLed

Vâng, cách này cũng tốt, nhưng tôi thích giải pháp của Lieven hơn, vì đơn giản.
Eedoh

3

Tôi biết đây là một chủ đề khá cũ, nhưng tôi đã tìm kiếm một cái gì đó tương tự và đã đưa ra cái này.

Cho rằng bạn có một chuỗi được phân tách bằng dấu phẩy, bạn có thể sử dụng string_split

select distinct value from string_split('1, 1, 1, 2, 5, 1, 6',',')

Điều này sẽ trở lại

1
2
5
6

Phân tách chuỗi có hai tham số, đầu vào chuỗi và ký tự phân cách.

bạn có thể thêm một câu lệnh tùy chọn trong đó sử dụng valuelàm tên cột

select distinct value from string_split('1, 1, 1, 2, 5, 1, 6',',')
where value > 1

sản xuất

2
5
6

Điều này dường như yêu cầu MSSQL 2016 trở lên: docs.microsoft.com/en-us/sql/t-sql/fifts/ trộm
Jonathan

1
@Sam Có, đây là SQL Server, theo các thẻ của câu hỏi ban đầu
NapkinBob

1
@Jonathan Vâng, với độ tuổi của câu hỏi, Nó sẽ không giúp ích cho poster gốc, nhưng tôi đoán rằng ai đó có thể vấp phải nó, như tôi đã làm, và thấy nó hữu ích.
NapkinBob

2

Nếu bạn cần một mảng, hãy tách các cột mảng bằng dấu phẩy:

SELECT * FROM (VALUES('WOMENS'),('MENS'),('CHILDRENS')) as X([Attribute])
,(VALUES(742),(318)) AS z([StoreID])

0

Một cách khác mà bạn có thể sử dụng là một truy vấn như thế này:

SELECT DISTINCT
    LTRIM(m.n.value('.[1]','varchar(8000)')) as columnName
FROM 
    (SELECT CAST('<XMLRoot><RowData>' + REPLACE(t.val,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
     FROM (SELECT '1, 1, 1, 2, 5, 1, 6') AS t(val)
    ) dt
  CROSS APPLY 
    x.nodes('/XMLRoot/RowData') m(n);

0

Chọn id người dùng từ danh sách id người dùng:

SELECT * FROM my_table WHERE user_id IN (1,3,5,7,9,4);

-2

Một kỹ thuật đã làm việc với tôi là truy vấn một bảng mà bạn biết có số lượng lớn các bản ghi trong đó, bao gồm cả trường Row_Number trong kết quả của bạn

Select Top 10000 Row_Number() OVER (Order by fieldintable) As 'recnum' From largetable

sẽ trả về một tập kết quả gồm 10000 bản ghi từ 1 đến 10000, sử dụng điều này trong một truy vấn khác để cung cấp cho bạn kết quả mong muốn


-4

Sử dụng Inhàm SQL

Một cái gì đó như thế này:

SELECT * FROM mytable WHERE:
"VALUE" In (1,2,3,7,90,500)

Điều trị trong ArcGIS


1
CHỌN này tạo ra lỗi cú pháp với SQL Server.
JohnH
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.