เลือกจากอะไร?


94

เป็นไปได้ไหมที่จะมีคำสั่งเช่น

SELECT "Hello world"
WHERE 1 = 1

ใน SQL?

สิ่งสำคัญที่ฉันอยากรู้คือฉันสามารถเลือกจากอะไรได้ไหมคือไม่มีคำสั่ง FROM


3
ดูความคิดเห็นของคุณใน @Rafael Belliard คุณอาจจะดีกว่าถ้าถามว่าคุณต้องการทำอะไร คุณต้องการส่งคืนสตริงหากมีค่าสำหรับตารางที่กำหนดหรือไม่
Jim L

ใช่นั่นคือสิ่งที่ฉันต้องการจริงๆ ฉันรู้ว่าฉันสามารถทำมันได้ผมก็สงสัยว่าถ้าผมจำเป็นต้องมีFROM NULLระหว่างและSELECT WHEREการใช้ถ้อยคำที่คลุมเครือส่วนใหญ่เป็นเพราะเป็นการบ้านและฉันไม่ต้องการให้ใครมาบอกคำตอบถ้าความรู้สึกของฉันผิด
Ritwik Bose

คำตอบ:


143

ไม่สอดคล้องกันระหว่างผู้ขาย - Oracle, MySQL และ DB2 รองรับ dual:

SELECT 'Hello world'
  FROM DUAL

... ในขณะที่ SQL Server, PostgreSQL และ SQLite ไม่ต้องการFROM DUAL:

SELECT 'Hello world'

MySQL รองรับทั้งสองวิธี


3
ฉันสงสัยมาตลอด เหตุใดจึงเลือกใช้คำว่าคู่สำหรับตารางผี
Alex Blakemore

5
@ อเล็กซ์: "ตาราง DUAL เดิมมีสองแถวอยู่ในนั้น (ด้วยเหตุนี้จึงเป็นชื่อ) แต่ต่อมามีเพียงแถวเดียว"
กบฏ

8
บน DB2 dual เรียกว่า 'sysibm.sysdummy1'
Danubian Sailor

1
ใน Postgresql คุณสามารถสร้างตารางดัมมี่ที่เรียกDUALและดำเนินการสืบค้นจากตารางที่เหมือนผีได้
Stephan

1
@AlexBlakemore "ฉันสร้างตาราง DUAL เป็นออบเจ็กต์พื้นฐานใน Oracle Data Dictionary มันไม่ได้ตั้งใจให้มองเห็นได้ แต่ใช้ในมุมมองที่คาดว่าจะถูกสอบถามแทนแนวคิดคือคุณสามารถเข้าร่วม ตาราง DUAL และสร้างสองแถวในผลลัพธ์สำหรับทุกๆหนึ่งแถวในตารางของคุณจากนั้นโดยใช้ GROUP BY การรวมผลลัพธ์สามารถสรุปได้เพื่อแสดงจำนวนพื้นที่จัดเก็บสำหรับขอบเขตข้อมูลและสำหรับขอบเขต INDEX ชื่อ DUAL ดูเหมือนจะเหมาะกับกระบวนการสร้างคู่แถวจากแถวเดียว "( en.wikipedia.org/wiki/DUAL_table )
คลิกตกลง


16

ลองทำตามนี้

โสด:

SELECT *  FROM (VALUES ('Hello world')) t1 (col1) WHERE 1 = 1

หลาย:

SELECT *  FROM (VALUES ('Hello world'),('Hello world'),('Hello world')) t1 (col1) WHERE 1 = 1

รายละเอียดเพิ่มเติมที่นี่: http://modern-sql.com/use-case/select-without-from


1
คำตอบที่สอดคล้องกับ ANSI SQL เท่านั้น! (สำหรับคำถามที่ไม่ระบุ dbms)
jarlh

มีจุดประสงค์เพื่อWHERE 1 = 1อะไร? บน PostgreSQL ทำงานได้โดยไม่ต้องใช้มัน หรือเกี่ยวข้องกับ DMBS อื่น?
Frankie Drake

เท่านั้นSELECT * FROM (VALUES ("Hello world")) t1 (col1)ยังสบายดี Whereเพียงแค่ตอบคำถามนี้
chuongtv

@chuongtv เลือกหลายแถวได้อย่างไร?
Hector

@Hector เพียงทำตามการแทรกโครงสร้างของ SQL แบบนี้SELECT * FROM (VALUES ('Hello world'),('Hello world'),('Hello world')) t1 (col1) WHERE 1 = 1
chuongtv

8

นี่คือรายการที่สมบูรณ์ที่สุดของการสนับสนุนฐานข้อมูลของ dual จากhttps://blog.jooq.org/tag/dual-table/ :

ใน RDBMS อื่น ๆ อีกมากมายไม่จำเป็นต้องมีตารางจำลองเนื่องจากคุณสามารถออกแถลงการณ์ดังนี้:

SELECT 1;
SELECT 1 + 1;
SELECT SQRT(2);

นี่คือ RDBMS ซึ่งโดยทั่วไปแล้วข้างต้นเป็นไปได้:

  • H2
  • MySQL
  • Ingres
  • Postgres
  • SQLite
  • เซิร์ฟเวอร์ SQL
  • Sybase ASE

ใน RDBMS อื่น ๆ จำเป็นต้องมีตารางดัมมี่เช่นเดียวกับใน Oracle ดังนั้นคุณจะต้องเขียนสิ่งเหล่านี้:

SELECT 1       FROM DUAL;
SELECT 1 + 1   FROM DUAL;
SELECT SQRT(2) FROM DUAL;

นี่คือ RDBMS และตารางจำลองตามลำดับ:

  • DB2: SYSIBM.DUAL
  • ดาร์บี้: SYSIBM.SYSDUMMY1
  • H2: รองรับ DUAL
  • HSQLDB: INFORMATION_SCHEMA.SYSTEM_USERS
  • MySQL: รองรับ DUAL
  • Oracle: DUAL
  • Sybase SQL ทุกที่: SYS.DUMMY

Ingres ไม่มี DUAL แต่จริงๆแล้วต้องการเช่นเดียวกับใน Ingres คุณไม่สามารถมีคำสั่ง WHERE GROUP BY หรือ HAVING ได้โดยไม่ต้องมีคำสั่งจาก FROM



5

คุณสามารถ. ฉันใช้บรรทัดต่อไปนี้ในแบบสอบถาม StackExchange Data Explorer :

SELECT
(SELECT COUNT(*) FROM VotesOnPosts WHERE VoteTypeName = 'UpMod' AND UserId = @UserID AND PostTypeId = 2) AS TotalUpVotes,
(SELECT COUNT(*) FROM Answers WHERE UserId = @UserID) AS TotalAnswers

Data Exchange ใช้ Transact-SQL (ส่วนขยายที่เป็นกรรมสิทธิ์ของ SQL Server ไปยัง SQL)

คุณสามารถลองด้วยตัวเองโดยเรียกใช้แบบสอบถามเช่น:

SELECT 'Hello world'

การแลกเปลี่ยนข้อมูลคือ Azure โดยใช้ SQL Server
OMG Ponies

2

คิดว่าคงไม่ไหว ในทางทฤษฎี: เลือกดำเนินการสองประเภท:

  • แคบ / ขยายเซต (เซต - ทฤษฎี);

  • การทำแผนที่ผลลัพธ์

อันแรกสามารถมองเห็นได้ว่าเป็นการลดลงในแนวนอนตรงข้ามกับ where-clause ซึ่งสามารถมองเห็นได้ว่าเป็นแนวตั้งที่ลดลง ในทางกลับกันการรวมสามารถเพิ่มชุดในแนวนอนซึ่งการรวมกันสามารถเพิ่มชุดในแนวตั้งได้

               augmentation          diminishing
horizontal     join/select              select   
vertical          union            where/inner-join

อันที่สองคือการทำแผนที่ การทำแผนที่เป็นตัวแปลงมากกว่า ใน SQL ใช้ฟิลด์บางฟิลด์และส่งคืนฟิลด์เป็นศูนย์หรือมากกว่า ในการเลือกคุณสามารถใช้ฟังก์ชันการรวมบางอย่างเช่น sum, avg เป็นต้นหรือนำค่าคอลัมน์ทั้งหมดมาแปลงเป็นสตริง ใน C # linq เราบอกว่าการเลือกยอมรับวัตถุประเภท T และส่งคืนวัตถุประเภท U

select 'howdy' from <table_name>ผมคิดว่าความสับสนมาจากข้อเท็จจริงที่ว่าคุณสามารถทำได้: คุณลักษณะนี้คือการทำแผนที่ซึ่งเป็นส่วนแปลงของสิ่งที่เลือก คุณไม่ได้พิมพ์บางอย่าง แต่กำลังแปลง! ในตัวอย่างของคุณ:

SELECT "
WHERE 1 = 1

คุณกำลังแปลง nothing / null เข้าไป"Hello world"และคุณ จำกัด ชุดของ nothing / no table ให้เป็นแถวเดียวซึ่ง imho ไม่สมเหตุสมผลเลย

คุณอาจสังเกตเห็นว่าถ้าคุณไม่ จำกัด จำนวนคอลัมน์"Hello world"จะถูกพิมพ์สำหรับแต่ละแถวที่มีอยู่ในตาราง ฉันหวังว่าคุณจะเข้าใจว่าทำไมในตอนนี้ "Hello world"คุณเลือกที่จะใช้เวลาอะไรจากคอลัมน์ที่มีอยู่และสร้างหนึ่งคอลัมน์ที่มีข้อความ:

ดังนั้นคำตอบของฉันคือไม่ คุณไม่สามารถละทิ้ง from-clause ได้เนื่องจากการเลือกจำเป็นต้องมีตารางคอลัมน์เพื่อดำเนินการเสมอ


2

ใน Standard SQL ไม่มี WHEREประโยคหมายถึงการแสดงออกของตาราง

จากข้อมูลจำเพาะ SQL-92:

7.6 "ที่ข้อ"

ฟังก์ชัน

ระบุตารางที่ได้มาจากการประยุกต์ใช้ "เงื่อนไขการค้นหา" กับผลลัพธ์ของ "from clause" ที่นำหน้า

ในทางกลับกัน:

7.4 "จากข้อ"

ฟังก์ชัน

ระบุตารางที่ได้มาจากตารางที่มีชื่ออย่างน้อยหนึ่งตาราง

วิธีมาตรฐานในการทำ (เช่นควรใช้กับผลิตภัณฑ์ SQL ใด ๆ ):

SELECT DISTINCT 'Hello world' AS new_value
  FROM AnyTableWithOneOrMoreRows
 WHERE 1 = 1;

... สมมติว่าคุณต้องการเปลี่ยนWHEREอนุประโยคให้มีความหมายมากขึ้นมิฉะนั้นจะสามารถละเว้นได้


ข้อผิดพลาด: ไม่มีคอลัมน์ "hello world" ใน my_table Query ล้มเหลว PostgreSQL กล่าวว่าไม่มีคอลัมน์ "hello world" ใน my_table
Pål Brattberg

@ PålBrattberg: ควรเป็นเครื่องหมายคำพูดเดียวตอนนี้ได้รับการแก้ไขแล้ว
2559

ตารางใดที่ใช้ในแง่ของเวลาในการประมวลผล? หรือข้อเท็จจริงที่ว่า SELECT ไม่ได้อ้างอิงคอลัมน์ใด ๆ ทำให้ตารางจริงไม่เกี่ยวข้อง?
Allen Gould

@AllenGould: มันจะเป็น 'ขึ้นอยู่กับผู้ขาย' แต่มีการลัดวงจรที่ชัดเจนซึ่งสามารถใช้ประโยชน์ได้เช่นกรณีหนึ่งคือที่เครื่องมือเพิ่มประสิทธิภาพรับรู้ว่าSELECTประโยคประกอบด้วยค่าคงที่เท่านั้นและนั่นAnyTableWithOneOrMoreRowsคือตารางที่จัดเก็บดังนั้นจึงใช้สถิติเพื่อตรวจสอบว่าตารางมี ศูนย์แถว
60

2

มีความเป็นไปได้อื่น - แบบสแตนด์อโลนVALUES():

VALUES ('Hello World');

เอาท์พุต:

column1
Hello World

จะมีประโยชน์เมื่อคุณต้องการระบุค่าหลายค่าอย่างกะทัดรัด:

VALUES (1, 'a'), (2, 'b'), (3, 'c');

เอาท์พุต:

column1     column2
      1     a
      2     b
      3     c

การสาธิต DBFiddle

ไวยากรณ์นี้รองรับโดย SQLite / PostgreSQL / DB LUW / MariaDB 10.3



1

ใน Firebird คุณสามารถทำได้:

select "Hello world" from RDB$DATABASE;

RDB $ DATABASE คือตารางพิเศษที่มีหนึ่งแถวเสมอ


0

ฉันรู้ว่านี่เป็นคำถามเก่า แต่วิธีแก้ปัญหาที่ดีที่สุดสำหรับคำถามของคุณคือการใช้แบบสอบถามย่อยจำลอง:

SELECT 'Hello World'
FROM (SELECT name='Nothing') n
WHERE 1=1

ด้วยวิธีนี้คุณสามารถมี WHERE และประโยคใดก็ได้ (เช่น Joins หรือ Apply เป็นต้น) หลังคำสั่ง select เนื่องจากแบบสอบถามย่อยแบบจำลองบังคับให้ใช้คำสั่ง FROM โดยไม่เปลี่ยนแปลงผลลัพธ์


1
คุณยังคงSELECTไม่มีFROMในแบบสอบถามย่อยของคุณดังนั้นจะยังคงล้มเหลวใน Oracle เป็นต้น
Pere

ใน Oracle นั้นง่ายกว่าด้วยซ้ำเพราะคุณสามารถSELECT 'Hello' FROM dual WHERE 1=1ข้ามแบบสอบถามย่อยได้
DomingoR

OP ถามว่าเป็นไปได้ไหมที่จะมีคำสั่ง (กล่าวคือ a SELECT) โดยไม่มีFROMประโยค คุณยังไม่ได้อ่านคำถาม?
Pere

ผมไม่อ่านคำถาม แต่ถ้าคุณเป็นมือใหม่โดยสิ้นเชิงใน SQL (หรือยังไม่ได้อ่านคำตอบอื่น ๆ ) คุณรู้ว่าคุณไม่สามารถมีได้โดยไม่ต้องWHERE FROMด้วยเหตุนี้ฉันจึงตอบกลับข้อความแรกของคำถาม OP
DomingoR

ฉันมีประสบการณ์มากกว่า 15 ปีใน SQL ปริญญาคอมพิวเตอร์และจำไม่ได้ว่าตอนนี้มีWHERESQL มาตรฐานหรือไม่ ฉันอ่านคำตอบอื่น ๆ ด้วย อย่างไรก็ตามสิ่งที่เหมาะสมคือคุณไม่สามารถมีได้SELECTโดยไม่มีFROMไม่ใช่ " WHEREไม่มีFROM" (?) คำถามของคุณทำงานที่ไหน @DomingoR? มันยังคงมีSELECTโดยไม่มีFROM(ในแบบสอบถามย่อย) ดังนั้นจึงล้มเหลวใน DBMS ที่ไม่อนุญาตให้มีการสืบค้นโดยไม่มีFROMและทำงานเฉพาะกับสิ่งที่เบี่ยงเบนจาก SQL มาตรฐานและอนุญาตให้ไม่มีFROMในSELECT. ดังนั้นคำตอบของคุณจึงไม่มีประโยชน์
Pere

0

ฉันใช้ firebird ก่อนอื่นสร้างตารางคอลัมน์เดียวชื่อ "NoTable" แบบนี้

CREATE TABLE NOTABLE 
(
  NOCOLUMN              INTEGER
);
INSERT INTO NOTABLE VALUES (0); -- You can put any value

ตอนนี้คุณสามารถเขียนสิ่งนี้ได้

select 'hello world' as name

จากที่น่าสังเกต

คุณสามารถเพิ่มคอลัมน์ใดก็ได้ที่คุณต้องการให้แสดง


0

สำหรับ DB2:

`VALUES('Hello world')`

คุณสามารถทำหลาย "แถว" ได้เช่นกัน:

`VALUES('Hello world'),('Goodbye world');`

คุณสามารถใช้ในการรวมได้ตราบเท่าที่ประเภทตรงกัน:

VALUES(1,'Hello world')
UNION ALL
VALUES(2,'Goodbye world');
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.