ฉันจะเลือกจากรายการค่าใน SQL Server ได้อย่างไร


217

ฉันมีปัญหาง่าย ๆ ที่ฉันไม่สามารถแก้ไขได้ ฉันต้องทำสิ่งนี้:

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

ใครช่วยได้บ้าง

แก้ไข

ข้อมูลมาเป็นไฟล์ข้อความจากหนึ่งในลูกค้าของเรา มันไม่มีการจัดรูปแบบทั้งหมด (เป็นข้อความบรรทัดเดียวที่ยาวมาก) แต่อาจทำได้ใน Excel แต่มันไม่เป็นประโยชน์สำหรับฉันเพราะฉันจะต้องใช้ค่าเหล่านี้ในการสืบค้น sql ไม่สะดวกที่จะทำทุกครั้งที่ฉันต้องการเรียกใช้แบบสอบถาม


คุณต้องการเลือกจากหลายตารางหรือเลือกจากตารางเดียว แต่มีค่าเฉพาะให้เลือกหรือไม่ บางสิ่งบางอย่างเช่นเฉพาะ ID คนเดียว
Anirudh Goel

ไม่ใช่สิ่งที่คุณถาม แต่คุณสามารถทำได้ในภาษาอื่น ยกตัวอย่างเช่นใน PowerShell คุณสามารถทำได้เพื่อให้ได้ค่าที่แตกต่างกันในอาร์เรย์$d = (1, 1, 1, 2, 5, 1, 6) | sort -Unique $dง่ายต่อการขยายเป็นเครื่องมือไฟล์ต่อไฟล์
Jeppe Stig Nielsen

เป็นสิ่งสำคัญที่นี่เพื่อรับรายการที่แตกต่างของค่าเหล่านั้นหรือเพื่อรับรายการของค่าลงใน SQL? ดังที่ @JeppeStigNielsen กล่าวว่ามีวิธีอื่นในการรับค่าที่แตกต่างจากรายการข้อความที่ไม่เกี่ยวข้องกับ SQL ฉันมาที่นี่เพื่อค้นหาวิธีรับรายการค่าลงในสคริปต์ SQL ที่อ้างอิงตารางอื่น ๆ
Rikki

คำตอบ:


81

วิธีที่ง่ายที่สุดในการรับค่าที่แตกต่างของรายการแบบยาวของข้อความที่คั่นด้วยจุลภาคคือใช้การค้นหาแทนที่ด้วยUNIONเพื่อรับค่าที่แตกต่าง

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

ใช้กับข้อความที่คั่นด้วยจุลภาคแบบยาว

  • ค้นหาและแทนที่คอมมาทั้งหมดด้วย UNION SELECT
  • เพิ่มSELECTด้านหน้าของคำสั่ง

ตอนนี้คุณควรมีแบบสอบถามที่ใช้งานได้


3
ไม่มีผมมีรายชื่อของหลายร้อยของค่าด้วยตนเองมันจะทรมาน
Eedoh

รายการนั้นมาจากไหน อาจเป็นวิธีที่ง่ายกว่าเพียงแค่คัดลอก / วางรายการนั้นใน Excel และแยกค่าที่แตกต่างกันโดยใช้แท็บไขว้แบบง่าย
Lieven Keersmaekers

btw ค้นหาและแทนที่อาจนำคุณไปไกล แทนที่เครื่องหมายจุลภาคทุกตัวด้วยการเลือก unionเพิ่มการเลือกด้านหน้าและคุณควรมีคิวรีการทำงาน cfr ที่แสดงร่วมกัน
Lieven Keersmaekers

1
สิ่งนี้มีการเปลี่ยนเครื่องหมายจุลภาคกับสหภาพเลือกทำงานเช่นเสน่ห์ขอบคุณมาก :)
Eedoh

5
สำหรับเหตุผลด้านประสิทธิภาพฉันขอแนะนำ Union-All จากนั้นจัดกลุ่มตามหรือใช้ Distinct ในตัวเลือกภายนอกของคุณ
MikeTeeVee

428

มีเฉพาะใน SQL Server 2008 และสูงกว่าเป็นตัวสร้างแถวในแบบฟอร์มนี้:
คุณสามารถใช้

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

หลายคนเขียนเกี่ยวกับในหมู่พวกเขา:


66
หมายเหตุด้านข้าง: Xเป็นนามแฝงสำหรับชื่อตารางและaเป็นนามแฝงสำหรับชื่อคอลัมน์;)
shA.t

11
นี่เป็นคำตอบที่ถูกต้องมากขึ้นเมื่อเทียบกับคำตอบที่เลือกในปัจจุบัน
TabsNotSpaces

1
นี่เป็นวิธีที่ธรรมดาที่สุดฉันถูกนิสัยเสียโดยไม่ถูกต้อง (ARRAY []) ในpgsqlตอนนี้และต่อสู้กับหัวเพื่อให้ FROM ยอมรับค่าเล็กน้อยเป็นเรคคอร์ดแถวsqlserverและนี่ก็คือ มีความสุขที่ได้รู้
Ben

1
คำตอบที่ดีขึ้นเนื่องจากนามแฝงของคอลัมน์และตาราง
อัลเฟรโด A.

79

โดยทั่วไป:

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 )

ในกรณีของคุณ:

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

1
ฉันรู้ว่า "select *" ถือเป็นรูปแบบที่ไม่ดี แต่มีเหตุผลที่จะไม่ใช้ select * ในกรณีนี้หรือไม่? เนื่องจากการทำซ้ำของ FieldName1, FieldName2, ... , FieldNameN นั้นพิลึก
Pxtl

@Pxtl ไม่มีเหตุผลที่จะไม่ใช้ "Select *" ฉันได้เขียนชื่อฟิลด์เหล่านั้นใหม่เพื่อความชัดเจนยิ่งขึ้น นอกจากนี้คุณอาจไม่ต้องการคำหลัก "แตกต่าง"
Ardalan Shahgholi

43

คุณลองใช้ไวยากรณ์ต่อไปนี้หรือไม่

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

5
ผู้ใช้ที่ไม่ระบุชื่อแนะนำให้แก้ไขรหัสเป็น:SELECT DISTINCT table_name.column_name FROM (VALUES (1), (2), (3)) AS table_name(column_name)
Vogel612

19

หากคุณต้องการเลือกเฉพาะค่าบางค่าจากตารางเดียวคุณสามารถลองได้

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

เช่น:

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

หากคุณต้องการเลือกจากหลายตารางคุณจะต้องUNIONเลือก

หากคุณต้องการเลือกค่า 1, 1, 1, 2, 5, 1, 6 คุณต้องทำสิ่งนี้

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

1
ฉันไม่จำเป็นต้องเลือกจากตาราง แต่จากรายการของค่า (ในวงเล็บ) นั่นคือปัญหาหลัก (เลือกจากคั่นด้วยเครื่องหมายจุลภาคอาร์เรย์ของค่าไม่ได้มาจากตาราง)
Eedoh

ในกรณีเช่นเรามีตาราง DUAL ใน Oracle คุณสามารถใช้ประโยชน์ได้เหมือนกัน แต่เนื่องจากไม่มี DUAL คุณจะต้องไปทางสหภาพ คุณสามารถลองใช้วิธีอื่นดังที่คุณกล่าวถึงว่าคุณได้คั่นค่าหลายค่าด้วยเครื่องหมายจุลภาคทำไมคุณไม่แทรกลงในตารางจากนั้นใช้คิวรีเลือก SQL ที่เป็นระเบียบแทนที่จะใช้สหภาพ SQL จำนวนมาก
Anirudh Goel

14

PostgreSQL ให้ 2 วิธีในการทำสิ่งนี้:

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

หรือ

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

การใช้วิธีการเรียงลำดับคุณยังสามารถทำสิ่งนี้:

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

11
แม้ว่าคำถามจะระบุ MSSQL ...:)
halfer

@ halfer คำตอบแรกที่ให้ที่นี่ใช้ได้สำหรับฉันโดยใช้ MSSQL 2016 ในขณะที่คำตอบอื่น ๆ ไม่ได้ 7 ปีต่อมา
dustytrash

9

สิ่งนี้ใช้ได้กับ SQL Server 2005 และหากมีจำนวนมากที่สุด:

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 เรียบร้อย แต่ถูก จำกัด ไว้ที่จำนวนแถวใน syscomments cross ที่รวมเข้ากับตัวเอง ในกรณีของฉันที่จะ 294849. (และคุณลืมที่แตกต่างกัน.)
Lieven Keersmaekers

คุณสามารถข้ามการเข้าร่วมได้อีกครั้ง แต่การแทนที่เครื่องหมายจุลภาคนั้นเป็นวิธีที่เร็วกว่ามาก
LukLed

ใช่วิธีนี้ดีเช่นกัน แต่ฉันชอบทางออกของ Lieven เพราะความเรียบง่าย
Eedoh

3

ฉันรู้ว่านี่เป็นหัวข้อเก่า ๆ แต่ฉันค้นหาสิ่งที่คล้ายกันและเกิดขึ้นกับสิ่งนี้

เนื่องจากคุณมีสตริงที่คั่นด้วยเครื่องหมายจุลภาคคุณสามารถใช้ string_split

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

สิ่งนี้ควรกลับมา

1
2
5
6

การแยกสตริงใช้สองพารามิเตอร์อินพุตสตริงและอักขระตัวคั่น

คุณสามารถเพิ่มทางเลือกโดยที่ statement ใช้valueเป็นชื่อคอลัมน์

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

ผลิต

2
5
6

ดูเหมือนว่าจะต้องใช้ MSSQL 2016 หรือใหม่กว่า: docs.microsoft.com/en-us/sql/t-sql/functions/…
Jonathan

1
@Sam ใช่นี่คือ SQL Server ตามแท็กของคำถามเดิม
NapkinBob

1
@ โจนาธานใช่ตามอายุของคำถามมันไม่ได้ช่วยโปสเตอร์ต้นฉบับ แต่ฉันคิดว่ามีคนอาจสะดุดเมื่อฉันทำและคิดว่ามีประโยชน์
NapkinBob

2

หากคุณต้องการอาร์เรย์ให้แยกคอลัมน์อาเรย์ด้วยเครื่องหมายจุลภาค:

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

0

อีกวิธีที่คุณสามารถใช้คือแบบสอบถามแบบนี้:

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);


-2

เทคนิคที่ได้ผลสำหรับฉันคือการค้นหาตารางที่คุณรู้ว่ามีจำนวนเรคคอร์ดอยู่ในนั้นรวมถึงเพียงฟิลด์ Row_Number ในผลลัพธ์ของคุณ

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

จะส่งคืนชุดผลลัพธ์ที่มี 10,000 ชุดจาก 1 ถึง 10,000 ใช้ในแบบสอบถามอื่นเพื่อให้ผลลัพธ์ที่คุณต้องการ


-4

ใช้Inฟังก์ชันSQL

บางสิ่งเช่นนี้

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

ทำงานได้ดีใน ArcGIS


1
SELECT นี้สร้างข้อผิดพลาดทางไวยากรณ์กับ SQL Server
JohnH
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.