WYBRAĆ z niczego?

91

Czy można mieć takie oświadczenie

SELECT "Hello world"
WHERE 1 = 1

w SQL?

Najważniejsze, co chcę wiedzieć, to czy mogę WYBIERAĆ z niczego, tj. Nie mam klauzuli FROM.

Ritwik Bose
źródło
3
Patrząc na swój komentarz na temat @Rafael Belliard, być może lepiej będzie, jeśli zapytasz, co tak naprawdę chcesz robić. Czy chcesz zwrócić jakiś ciąg, jeśli na przykład istnieją wartości dla danej tabeli?
Jim L,
Tak, dokładnie tego chciałem. Wiem, że mogę to zrobić, bardziej zastanawiałem się, czy potrzebuję FROM NULLmiędzy SELECTa WHERE. Niejasne sformułowania, głównie dlatego, że to praca domowa i nie chciałem, aby ktoś przyszedł i powiedział mi odpowiedź, jeśli moje przeczucia były złe.
Ritwik Bose

Odpowiedzi:

141

To nie jest spójne u różnych dostawców - Oracle, MySQL i DB2 obsługują podwójnie:

SELECT 'Hello world'
  FROM DUAL

... podczas gdy SQL Server, PostgreSQL i SQLite nie wymagają FROM DUAL:

SELECT 'Hello world'

MySQL obsługuje oba sposoby.

Kucyki OMG
źródło
2
Zawsze się zastanawiałem. Dlaczego wybór terminu dual dla tabeli fantomowej?
Alex Blakemore
5
@Alex: "Oryginalna tabela DUAL miała w sobie dwa wiersze (stąd jej nazwa), ale później miała tylko jeden wiersz."
buntownik
7
W systemie DB2 dual nazywa się „sysibm.sysdummy1”
Danubian Sailor
1
W Postgresql można utworzyć fałszywą tabelę o nazwie DUALi wykonywać zapytania z tabeli podobnej do fantomu.
Stephan
1
@AlexBlakemore "Stworzyłem tabelę DUAL jako obiekt bazowy w słowniku Oracle Data Dictionary. Nigdy nie miał być widoczny, ale zamiast tego został użyty w widoku, który miał być zapytany. Pomysł polegał na tym, że możesz wykonać JOIN, aby tabelę DUAL i utwórz dwa wiersze w wyniku dla każdego wiersza w tabeli. Następnie za pomocą funkcji GROUP BY można podsumować wynikowe łączenie, aby pokazać ilość miejsca dla zakresu DATA i dla zakresu INDEKSU. Nazwa DUAL wydawała się odpowiednia dla procesu tworzenia pary wierszy tylko z jednego ”( en.wikipedia.org/wiki/DUAL_table )
Kliknij OK
29

W Oracle :

SELECT 'Hello world' FROM dual

Podwójny odpowiednik w SQL Server :

SELECT 'Hello world' 
buntownik
źródło
1
Czy mógłbym umieścić takie oświadczenie WHERE (SELECT ... )po nim?
Ritwik Bose
15

Spróbuj tego.

Pojedynczy:

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

Wielo:

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

więcej szczegółów tutaj: http://modern-sql.com/use-case/select-without-from

chuongtv
źródło
1
Jedyna odpowiedź zgodna z ANSI SQL! (Na pytanie bez określonych dbms.)
jarlh
Jaki jest cel WHERE 1 = 1? Na PostgreSQL działa bez niego. A może dotyczy innego DMBS?
Frankie Drake
Tylko SELECT * FROM (VALUES ("Hello world")) t1 (col1)nadal dobrze. Whereodpowiedz tylko na to pytanie.
chuongtv
@chuongtv Jak wybrać wiele wierszy?
Hector
@Hector Po prostu postępuj zgodnie ze strukturą wstawiania SQL. w ten sposóbSELECT * FROM (VALUES ('Hello world'),('Hello world'),('Hello world')) t1 (col1) WHERE 1 = 1
chuongtv
8

Oto najpełniejsza lista obsługi bazy danych dual z https://blog.jooq.org/tag/dual-table/ :

W wielu innych RDBMS nie ma potrzeby stosowania fikcyjnych tabel, ponieważ można wydawać takie instrukcje:

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

Są to RDBMS, w których powyższe jest ogólnie możliwe:

  • H2
  • MySQL
  • Ingres
  • Postgres
  • SQLite
  • SQL Server
  • Sybase ASE

W innych RDBMS wymagane są fikcyjne tabele, tak jak w Oracle. Dlatego musisz napisać takie rzeczy:

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

Oto RDBMS i odpowiadające im fikcyjne tabele:

  • DB2: SYSIBM.DUAL
  • Derby: SYSIBM.SYSDUMMY1
  • H2: Opcjonalnie obsługuje DUAL
  • HSQLDB: INFORMATION_SCHEMA.SYSTEM_USERS
  • MySQL: Opcjonalnie obsługuje DUAL
  • Wyrocznia: DUAL
  • Sybase SQL Anywhere: SYS.DUMMY

Ingres nie ma DUAL, ale w rzeczywistości by go potrzebował, ponieważ w Ingres nie możesz mieć klauzuli WHERE, GROUP BY lub HAVING bez klauzuli FROM.

Vadzim
źródło
6

W SQL Server wpisz:

Select 'Your Text'

Nie ma potrzeby stosowania klauzuli FROMlub WHERE.

RollTide
źródło
5

Możesz. Używam następujących wierszy w kwerendzie 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

Wymiana danych używa języka Transact-SQL (zastrzeżone rozszerzenia SQL Server do SQL).

Możesz spróbować samemu, uruchamiając zapytanie takie jak:

SELECT 'Hello world'
palswim
źródło
Data Exchange to Azure, oparta na SQL Server.
OMG Kucyki
2

Myślę, że to niemożliwe. Teoretycznie: funkcja select wykonuje dwa rodzaje rzeczy:

  • zawęzić / poszerzyć zbiór (teoria mnogości);

  • mapowanie wyniku.

Pierwsza może być postrzegana jako poziome zmniejszanie, w przeciwieństwie do klauzuli gdzie, które można postrzegać jako pionowe zmniejszanie. Z drugiej strony złączenie może zwiększyć zestaw w poziomie, podczas gdy połączenie może zwiększyć zestaw w pionie.

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

Drugi to mapowanie. Mapowanie jest bardziej konwerterem. W SQL zajmuje kilka pól i zwraca zero lub więcej pól. W polu wyboru możesz użyć niektórych funkcji agregujących, takich jak suma, średnia itp. Lub wziąć wszystkie wartości kolumn i przekonwertować je na ciąg. W C # linq mówimy, że selekcja akceptuje obiekt typu T i zwraca obiekt typu U.

Myślę, że zamieszanie chodzi o fakt, że można zrobić: select 'howdy' from <table_name>. Ta funkcja to mapowanie, część konwertera zaznaczania. Nie drukujesz czegoś, tylko konwertujesz! W twoim przykładzie:

SELECT "
WHERE 1 = 1

konwertujesz nic / wartość null na "Hello world"i zawężasz zbiór nic / brak tabeli do jednego wiersza, co nie ma żadnego sensu.

Możesz zauważyć, że jeśli nie ograniczysz liczby kolumn, "Hello world"zostanie wydrukowany dla każdego dostępnego wiersza w tabeli. Mam nadzieję, że już teraz rozumiesz, dlaczego. Twój wybór nie pobiera nic z dostępnych kolumn i tworzy jedną kolumnę z tekstem:"Hello world" .

Więc moja odpowiedź brzmi NIE. Nie można po prostu pominąć klauzuli from, ponieważ funkcja select zawsze wymaga kolumn tabeli.

Andries
źródło
2

W standardowym SQL nie. WHEREKlauzula oznacza wyrażenie stołowego.

Ze specyfikacji SQL-92:

7.6 "klauzula gdzie"

Funkcjonować

Określ tabelę utworzoną przez zastosowanie „warunku wyszukiwania” do wyniku poprzedniej klauzuli „from”.

Z kolei:

7.4 „z klauzuli”

Funkcjonować

Określ tabelę pochodzącą z jednej lub więcej nazwanych tabel.

Standardowy sposób na zrobienie tego (tzn. Powinien działać na każdym produkcie SQL):

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

... zakładając, że chcesz zmienić WHEREklauzulę na coś bardziej znaczącego, w przeciwnym razie można ją pominąć.

onedaywhen
źródło
BŁĄD: kolumna "hello world" nie istnieje w my_table Zapytanie nie powiodło się PostgreSQL powiedział: kolumna "hello world" nie istnieje w my_table
Pål Brattberg
@ PålBrattberg: powinny być pojedynczymi cudzysłowami, teraz naprawione.
onedaywhen
Czy ma znaczenie, który stół jest używany pod względem czasu przetwarzania? A może fakt, że SELECT nie odwołuje się do żadnej z kolumn, sprawia, że ​​rzeczywista tabela jest nieistotna?
Allen Gould
@AllenGould: byłby `` zależny od dostawcy '', ale istnieją oczywiste zwarcia, które można wykorzystać, np. W jednym przypadku optymalizator rozpoznaje SELECTklauzulę zawierającą tylko stałe i AnyTableWithOneOrMoreRowsjest to tabela przechowywana, dlatego wykorzystuje tylko statystyki do sprawdzenia, czy tabela ma zero wierszy.
kiedy
2

Jest jeszcze jedna możliwość - samodzielna VALUES():

VALUES ('Hello World');

Wynik:

column1
Hello World

Jest to przydatne, gdy musisz określić wiele wartości w zwięzły sposób:

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

Wynik:

column1     column2
      1     a
      2     b
      3     c

DBFiddle Demo

Ta składnia jest obsługiwana przez SQLite / PostgreSQL / DB LUW / MariaDB 10.3.

Łukasz Szozda
źródło
2

W przypadku ClickHouse nic nie jest system.one

SELECT 1 FROM system.one
simPod
źródło
1

W Firebird możesz to zrobić:

select "Hello world" from RDB$DATABASE;

RDB $ DATABASE to specjalna tabela, która zawsze ma jeden wiersz.

Robyn
źródło
0

Wiem, że to stare pytanie, ale najlepszym sposobem obejścia tego pytania jest użycie fikcyjnego podzapytania:

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

W ten sposób możesz mieć WHERE i dowolną klauzulę (taką jak Joins lub Apply itp.) Po instrukcji select, ponieważ fikcyjne podzapytanie wymusza użycie klauzuli FROM bez zmiany wyniku.

DomingoR
źródło
1
Nadal masz w podzapytaniu SELECTbez a FROM, więc w Oracle nadal nie powiedzie się itd.
Pere
W Oracle jest jeszcze prostsze, ponieważ możesz po prostu SELECT 'Hello' FROM dual WHERE 1=1pominąć podzapytanie.
DomingoR
PO zapytał, czy możliwe jest posiadanie oświadczenia (a SELECT) bez FROMklauzuli. Nie przeczytałeś pytania?
Pere
Przeczytałem pytanie, ale jeśli nie jesteś całkowicie niedoświadczony w SQL (lub nie czytałeś innych odpowiedzi), wiesz, że nie możesz mieć WHEREbez FROM. Mając to na uwadze, odpowiedziałem na pierwsze stwierdzenie pytania PO.
DomingoR
Cóż, mam ponad 15-letnie doświadczenie w SQL, dyplom z informatyki i nie pamiętam, czy teraz mam WHEREstandardowy SQL. Czytałem też inne odpowiedzi. Swoją drogą: właściwe jest to, że nie możesz mieć a SELECTbez aFROM , a nie „ WHEREbez FROM” (?). Gdzie działa Twoje zapytanie, @DomingoR? Nadal ma a SELECTbez a FROM(w podzapytaniu), więc zawodzi na tych DBMS, które nie pozwalają na tworzenie zapytań bez a FROMi działają tylko na tych, które odbiegają od standardowego SQL i pozwalają nie mieć FROMw SELECT. Więc twoja odpowiedź nic nie da.
Pere
0

Używam firebird. Przede wszystkim utwórz tabelę z jedną kolumną o nazwie „NoTable” w ten sposób

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

teraz możesz to napisać

select 'hello world' as name

od godnych uwagi

możesz dodać dowolną kolumnę, która ma być wyświetlana

Yous Athmane
źródło
0

W przypadku DB2:

`VALUES('Hello world')`

Możesz też zrobić wiele „wierszy”:

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

Możesz ich nawet używać w połączeniach, o ile typy są zgodne:

VALUES(1,'Hello world')
UNION ALL
VALUES(2,'Goodbye world');
Brad Mace
źródło