एसक्यूएल चयन संख्या पर्वतमाला


19

मुझे पंक्तियों के रूप में संख्याओं की एक सीमा को प्राप्त करना काफी कठिन लगा MySQL

उदाहरण के लिए सीमा 1-5 से प्राप्त की जाती है:

SELECT 1 
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5

में परिणाम होगा:

1
2
3
4
5

0-99 के लिए मैं दो 0-9 तालिकाओं को पार कर सकता हूं:

CREATE TABLE nums as
SELECT 0 as num
UNION
SELECT 1 
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6 
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9
;

Select n.num*10+nums.num v 
From nums n cross join nums

मैं इन सभी को लिखने से थक गया हूं UNIONऔर कोड को सिकोड़ने का तरीका ढूंढ रहा हूं ।

किसी भी विचार यह कैसे गोल्फ (उदाहरण के लिए 0-1,000,000 रेंज) के लिए MySQL या किसी SQL सिंटैक्स में गोल्फ ?

इसके लिए अतिरिक्त अंक दिए गए हैं:

  • एकल कथन
  • कोई प्रक्रिया नहीं
  • कोई चर नहीं
  • कोई डीडीएल बयान नहीं
  • केवल DQL बयान

2
यह निश्चित नहीं है कि यह मेटा में है, या dba.stackexchange.com में है या शायद SQL थ्रेड में गोल्फिंग के लिए टिप्स में है
ब्राडकास्ट

8
मतदाताओं को बंद करने के लिए: यह एक विषय पर चुनौती है; ऐसे सवाल जो गोल्फिंग कोड से संबंधित चुनौतियां नहीं हैं, उन्हें विषय-विषयक टिप्स प्रश्न माना जाता है।
हाइपरएन्यूट्रीनो

3
मैं एसओ से इस जवाब को पसंद करता हूं । Hackish सबसे अच्छा है, लेकिन आप सब के बाद एक गोल्फ समाधान के लिए कहा।
अरनुलद

@ अर्नुलद यह कमाल है!
डिमगोल्ड

2
यदि "किसी भी SQL" में PostgreSQL शामिल है, तो देखें generate_series()। हमारे यहां उपयोग के कुछ उदाहरण हैं।
मैनटवर्क

जवाबों:


9

SQL बोलियों के लिए जो रिसाइकल CTEs जैसे साइक्लाइट का समर्थन करते हैं , आप निम्न की तरह कुछ कर सकते हैं:

WITH RECURSIVE f(x) AS
(
  SELECT 1 UNION ALL SELECT x + 1 FROM f LIMIT 1000000
)
SELECT x
FROM f;

यह किसी भी मौजूदा तालिका पर निर्भर नहीं करता है और आप वांछित के रूप में सीमा खंड को बदल सकते हैं। मैंने मूल रूप से StackOverflow पर इसका एक संस्करण देखा।


2
अति उत्कृष्ट। यहाँ एक गोल्फ संस्करण है जो MS SQL में काम करता है: WITH t AS(SELECT 1n UNION ALL SELECT n+1FROM t WHERE n<36)SELECT n FROM t विभिन्न अंत बिंदुओं के लिए, बस 1और 36जो भी आप चाहते हैं उसे बदलें ।
ब्रैड

1
उफ़, यदि आप MS SQL में 100 से अधिक पंक्तियाँ चाहते हैं, तो आपको option (maxrecursion 0)मेरे उपरोक्त कथन के अंत में जोड़ने की आवश्यकता हो सकती है , अन्यथा यह 100 से अधिक पुनरावृत्ति के लिए त्रुटिपूर्ण है। (या तो maxrecursionविशिष्ट मान पर सेट है, या अनंत की अनुमति देने के लिए 0) ।
ब्रैडेक

6

इसी के लिए @ BradC की विधि

मैंने MS SQL का उपयोग किया, जिसमें [master]2048 के माध्यम से -1 की संख्या सीमा के साथ एक तालिका है । आप BETWEENअपनी सीमा बनाने के लिए ऑपरेटर का उपयोग कर सकते हैं ।

SELECT DISTINCT(number)
FROM master..[spt_values] 
WHERE number BETWEEN 1 AND 5

यदि आप इसे गोल्फ करना चाहते हैं, तो आप कर सकते हैं:

SELECT TOP 5 ROW_NUMBER()OVER(ORDER BY number)FROM master..spt_values

1
गोल्फ के लिए आप 2 बाइट WHERE number>0AND number<21
बचाते हैं

आप विशिष्ट का उपयोग क्यों करते हैं? बेमानी लगता है।
मैजिक ऑक्टोपस Urn

1
@MagicOctopusUrn क्योंकि उस तालिका में डुप्लिकेट नंबर हैं।
ओलिवर

1
हां, आपको या तो DISTINCT का उपयोग करना होगा या WHERE टाइप करना होगा = 'P'। भेद थोड़ा छोटा है।
ब्रैड

1
@ ब्रैडक, याSELECT DISTINCT(number+2)... WHERE number<19
पीटर टेलर

5

PostgreSQL, 35 बाइट्स

PostgreSQL में यह आसान है:

SELECT * FROM generate_series(1,5)

यदि आपको इसका नाम चाहिए:

SELECT num FROM generate_series(1,5)AS a(num)

आप इसे टाइमस्टैम्प के साथ भी कर सकते हैं। https://www.postgresql.org/docs/9.5/static/functions-srf.html


2
मुझे लगता है कि मैं पोस्टग्रेज करने जा रहा हूं
डिमगोल्ड

4

इस पोस्ट से बढ़िया विकल्प (@Arnauld द्वारा पाया गया):

SELECT id%1000001 as num
FROM <any_large_table>
GROUP BY num

मेरे लिए - यह चुनौती को हल करता है।


ऐसा लगता है कि मौजूदा तालिका में पहले idसे ही बहुत बड़े मूल्यों के माध्यम से आबादी वाले क्षेत्र पर भरोसा किया जा रहा है। इतना सुंदर डेटाबेस विशिष्ट, और आप एक पंक्ति याद कर सकते हैं अगर, कहते हैं, किसी ने उत्पाद ID = 4021 को हटा दिया।
ब्रैड

हां, लेकिन यह वास्तव में अपेक्षाकृत छोटी पर्वतमाला (दिनों के लिए 1-7, महीनों के लिए 1-12 के लिए अच्छा है ...)
डिमगोल्ड

4

PostgreSQL विशिष्ट

generate_series()एक सेट उत्पन्न करता है, इसलिए आप इसे न केवल fromक्लॉज़ में रख सकते हैं , बल्कि कहीं भी एक सेट हो सकता है:

psql=# select generate_series(10, 20, 3);
 generate_series 
-----------------
              10
              13
              16
              19
(4 rows)

आप सीधे सेट पर भी ऑपरेशन कर सकते हैं:

psql=# select 2000 + generate_series(10, 20, 3) * 2;
 ?column? 
----------
     2020
     2026
     2032
     2038
(4 rows)

यदि कई सेटों की लंबाई समान है, तो आप उन्हें समानांतर में बदल सकते हैं:

psql=# select generate_series(1, 3), generate_series(4, 6);
 generate_series | generate_series 
-----------------+-----------------
               1 |               4
               2 |               5
               3 |               6
(3 rows)

अलग-अलग लंबाई वाले सेट के लिए कार्टेशियन उत्पाद तैयार किया जाता है:

psql=# select generate_series(1, 3), generate_series(4, 5);
 generate_series | generate_series 
-----------------+-----------------
               1 |               4
               2 |               5
               3 |               4
               1 |               5
               2 |               4
               3 |               5
(6 rows)

लेकिन यदि आप उन्हें fromक्लॉज में इस्तेमाल करते हैं , तो आपको कार्टेसियन उत्पाद भी समान लंबाई के सेट के लिए मिलते हैं:

psql=# select * from generate_series(1, 2), generate_series(3, 4) second;
 generate_series | second 
-----------------+--------
               1 |      3
               1 |      4
               2 |      3
               2 |      4
(4 rows)

यह टाइमस्टैम्प का सेट भी उत्पन्न कर सकता है। उदाहरण के लिए आप २०००-०६-३० को जन्मे हैं और जानना चाहते हैं कि आपने अपना जन्मदिन किस वर्ष में मनाया है:

psql=# select to_char(generate_series, 'YYYY - Day') from generate_series('2000-06-30', current_date, interval '1 year') where to_char(generate_series, 'D') in ('1', '7');
     to_char      
------------------
 2001 - Saturday 
 2002 - Sunday   
 2007 - Saturday 
 2012 - Saturday 
 2013 - Sunday   
(5 rows)

3

MS SQL के masterनाम से डेटाबेस में एक undocumented सिस्टम टेबल है spt_values। अन्य बातों के अलावा, इसमें 0 से 2047 तक की संख्या शामिल है:

--returns 0 to 2,047
SELECT number n 
FROM master..spt_values
WHERE TYPE='P'

केवल अपने आप से एक अंक तालिका के रूप में उपयोगी है, लेकिन CTE में आप कुछ बड़ी संख्याएँ बहुत जल्दी प्राप्त कर सकते हैं:

--returns 0 to 4,194,304
WITH x AS(SELECT number n FROM master..spt_values WHERE TYPE='P')
SELECT 2048*x.a+*y.a
FROM x,x y
ORDER BY 1

3

(ये MS-SQL में काम करते हैं, निश्चित नहीं कि वे mySQL या अन्य प्लेटफ़ॉर्म के लिए काम करते हैं।)

छोटे सेटों के लिए (ऑर्डर या गैर-ऑर्डर किए गए), VALUESकंस्ट्रक्टर का उपयोग करें :

--Generates 0-9
SELECT a 
FROM(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))x(a)

(यह किसी भी चीज के लिए काम करता है, हालांकि तार सभी दोहराया एकल उद्धरण के साथ बहुत लंबा हो सकता है।)

फिर आप एक नामांकित सीटीई (सामान्य टेबल एक्सप्रेशन) का उपयोग करके क्रॉस-गुणा कर सकते हैं ताकि आपको इसे दोहराना न पड़े:

--Generates 0-999
WITH x AS(SELECT a FROM(VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))x(a))
SELECT 100*x.a+10*y.a+z.a 
FROM x,x y,x z
ORDER BY 1

वहाँ अन्य तकनीकों के टन हैं, "एसक्यूएल एक नंबर तालिका उत्पन्न" के लिए देखें, हालांकि अधिकांश गोल्फिंग के लिए अनुकूलित नहीं हैं।


1
क्या यह काम limit Yमनमानी रेंज बनाने के लिए होगा ?
रॉड

1
@ रास MS-SQL में आपको उपयोग करना होगाSELECT TOP 250 ...
ब्रैड

ओह, मैंने
रॉड

MySQL पर काम नहीं करता है, लेकिन फिर भी उपयोगी है :)
Dimgold

2

एक और विकल्प, यह MS SQL 2016 और इसके बाद के संस्करण के लिए विशिष्ट है:

SELECT value v
FROM STRING_SPLIT('1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16', ',')

मुझे इसकी संभावना स्ट्रिंग्स की सूचियों के लिए और अधिक आसान लगेगी, लेकिन मैं उन तरीकों को देख सकता हूं जो संख्याओं के साथ भी उपयोगी होंगे।


2

टी-एसक्यूएल, 98 बाइट्स

WITH H AS(SELECT 0i UNION ALL SELECT i+1FROM H WHERE i<99)SELECT H.i+1e4*A.i+B.i*1e2FROM H,H A,H B
  • ✓ एकल कथन
  • ✓ कोई प्रक्रिया नहीं
  • Ables कोई चर नहीं
  • ✓ कोई डीडीएल बयान नहीं
  • ✓ केवल DQL बयान

यह langelgjm के उत्तर का एक अच्छा साफ T-SQL संस्करण है । घातांक एक साफ सुथरी चाल है, साथ ही।
ब्रैड

1

SQL सर्वर के लिए एक और ...

WITH 
    cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)),   -- 10
    cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),                             -- 100
    cte_Tally (n) AS (
        SELECT TOP (<how many ROWS do you want?>)
            ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
        FROM
            cte_n2 a CROSS JOIN cte_n2 b                                                    -- 10,000
        )
SELECT 
    t.n
FROM
    cte_Tally t;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.