अंक तालिकाएं "अमूल्य" क्यों हैं?


112

हमारे निवासी डेटाबेस विशेषज्ञ हमें बता रहे हैं कि नंबर टेबल अमूल्य हैं । मुझे समझ में नहीं आता क्यों। यहाँ एक संख्या तालिका है:

USE Model
GO

CREATE TABLE Numbers
(
    Number INT NOT NULL,
    CONSTRAINT PK_Numbers 
        PRIMARY KEY CLUSTERED (Number)
        WITH FILLFACTOR = 100
)

INSERT INTO Numbers
SELECT
    (a.Number * 256) + b.Number AS Number
FROM 
    (
        SELECT number
        FROM master..spt_values
        WHERE 
            type = 'P'
            AND number <= 255
    ) a (Number),
    (
        SELECT number
        FROM master..spt_values
        WHERE 
            type = 'P'
            AND number <= 255
    ) b (Number)
GO

ब्लॉग पोस्ट के अनुसार, दिया गया तर्क है

नंबर टेबल वास्तव में अमूल्य हैं। मैं उन सभी का उपयोग स्ट्रिंग हेरफेर, खिड़की के कार्यों का अनुकरण करने, बहुत सारे डेटा के साथ परीक्षण तालिकाओं को आबाद करने, कर्सर के तर्क को समाप्त करने और कई अन्य कार्यों के लिए करता हूं जो उनके बिना अविश्वसनीय रूप से कठिन होंगे।

लेकिन मुझे समझ में नहीं आता है कि वे उपयोग क्या हैं, बिल्कुल - क्या आप कुछ सम्मोहक, विशिष्ट उदाहरण प्रदान कर सकते हैं जहां "नंबर टेबल" आपको SQL सर्वर में एक टन का काम बचाता है - और हमें उनके पास क्यों होना चाहिए?


3
एक संख्या तालिका के लिए कई उपयोग के मामलों को एक पुनरावर्ती CTE द्वारा समान रूप से संतुष्ट किया जा सकता है जो कि मक्खी पर आपके लिए आवश्यक संख्या उत्पन्न करता है। हालाँकि, CTE दृष्टिकोण के लिए एक प्रदर्शन दंड के साथ-साथ कुछ अन्य सीमाएँ भी हैं
निक चामास

4
@ निक: मैं कहूंगा कि एक भौतिक तालिका के आधार पर एक सीटीई-आधारित फ्लाई-संख्या केवल एक कार्यान्वयन विवरण है कि आप संख्या तालिका कैसे बनाते हैं। आलू बनाम आलू ...
रेमस रूसु २५'१२

1
@Remus - हाँ। मैं सिर्फ जेफ के लिए इस विकल्प को इंगित करना चाहता था।
निक चम्मास

2
मेरे पास SO stackoverflow.com/search?q=user%3A27535+%2B%22numbers+table%22 पर एक अंक तालिका का उपयोग करके एक दर्जन उत्तर हैं ।
gbn

जवाबों:


82

जब आपको 'लापता डेटा' को प्रोजेक्ट करने की आवश्यकता होती है, तो मैंने कई उपयोग किए हैं। उदाहरण के लिए। आपके पास एक समय श्रृंखला (उदाहरण के लिए एक एक्सेस लॉग) है और आप पिछले 30 दिनों के लिए प्रति दिन हिट की संख्या दिखाना चाहते हैं (एनालिटिक्स डैशबोर्ड के बारे में सोचें)। यदि आप करते हैं तो select count(...) from ... group by dayआपको हर दिन के लिए गिनती मिल जाएगी, लेकिन परिणाम में प्रत्येक दिन के लिए एक पंक्ति होगी जो आपके पास वास्तव में कम से कम एक पहुंच थी। दूसरी ओर यदि आप पहली बार अपनी संख्या तालिका ( select dateadd(day, -number, today) as day from numbers) से दिनों की एक तालिका प्रोजेक्ट करते हैं और फिर आप काउंट्स (या बाहरी आवेदन, जो भी आप कल्पना करते हैं) के साथ जुड़ जाते हैं, तो आपको एक परिणाम मिलेगा जिसमें 0 दिनों के लिए गिनती हो। कोई पहुंच नहीं था। यह तो केवल एक उदाहरण है। बेशक, कोई यह तर्क दे सकता है कि आपके डैशबोर्ड की प्रस्तुति परत लापता दिनों को संभाल सकती है और सिर्फ इसके बजाय एक 0 दिखा सकती है, लेकिन कुछ उपकरण (जैसे। SSRS) बस इसे संभालने में सक्षम नहीं होंगे।

अन्य उदाहरण मैंने देखा है कि सभी प्रकार की विंडो गणनाओं को करने के लिए इसी तरह की श्रृंखला की चालें (दिनांक / समय +/- संख्या) का उपयोग किया जाता है। सामान्य तौर पर, जब भी एक अनिवार्य भाषा में आप एक अच्छी तरह से ज्ञात पुनरावृत्तियों के साथ लूप के लिए उपयोग करेंगे, तो एसक्यूएल की घोषित और निर्धारित प्रकृति एक अंक तालिका के आधार पर एक चाल का उपयोग कर सकती है।

Btw, मैं तथ्य यह है कि यहां तक कि एक संख्या तालिका इसे का उपयोग हालांकि बाहर कॉल करने के लिए की जरूरत महसूस महसूस करता है जरूरी प्रक्रियात्मक निष्पादन की तरह, यह मानते हुए इसके बारे में भ्रम में गिर नहीं है है जरूरी। मुझे एक उदाहरण देने दें:

int x;
for (int i=0;i<1000000;++i)
  x = i;
printf("%d",x);

यह कार्यक्रम 999999 का उत्पादन करेगा, इसकी बहुत अधिक गारंटी है।

संख्या तालिका का उपयोग करके SQL सर्वर में समान प्रयास करें। पहले 1,000,000 संख्याओं की एक तालिका बनाएँ:

create table numbers (number int not null primary key);
go

declare @i int = 0
    , @j int = 0;

set nocount on;
begin transaction
while @i < 1000
begin
    set @j = 0;
    while @j < 1000
    begin
        insert into numbers (number) 
            values (@j*1000+@i);
        set @j += 1;
    end
    commit;
    raiserror (N'Inserted %d*1000', 0, 0, @i)
    begin transaction;
    set @i += 1;
end
commit
go

अब 'लूप के लिए' करते हैं:

declare @x int;
select @x = number 
from numbers with(nolock);
select @x as [@x];

परिणाम है:

@x
-----------
88698

अब आप एक WTF पल होने हैं कर रहे हैं (के बाद सभी number है संकुल प्राथमिक कुंजी!), चाल कहा जाता है आवंटन आदेश स्कैन और मैं सम्मिलित नहीं किया @j*1000+@iदुर्घटना से ... तुम भी एक अनुमान उद्यम और कहते हैं कि परिणाम है क्योंकि है था सकता है समानांतरवाद और वह कभी-कभी सही उत्तर हो सकता है।

इस पुल के नीचे कई ट्रोल हैं और मैंने कुछ ऑन SQL सर्वर बूलियन ऑपरेटर शॉर्ट-सर्किट और टी-एसक्यूएल कार्यों का उल्लेख किया है, जो निश्चित रूप से निष्पादन का एक निश्चित क्रम नहीं है


55

मुझे कई स्थितियों में एक नंबर टेबल काफी उपयोगी लगी है।

पर मुझे एक सहायक संख्या तालिका का उपयोग करने पर विचार क्यों करना चाहिए? , 2004 में लिखा, मैं कुछ उदाहरण दिखाता हूं:

  • तार लगाना
  • पहचान का अंतराल
  • जनरेटिंग डेट रेंज (जैसे कि एक कैलेंडर टेबल को पॉप्युलेट करना, जो अमूल्य भी हो सकती है)
  • समय स्लाइस पैदा करना
  • आईपी ​​रेंज उत्पन्न करना

पर बुरी आदतों को लात मारने: लूप का उपयोग कर बड़े तालिकाओं को भरने के लिए , मैं कैसे एक संख्या तालिका पंक्तियों का एक बहुत डालने (के रूप में थोड़ी देर के पाश का उपयोग करने का घुटने झटका दृष्टिकोण के खिलाफ) से कम काम करने के लिए इस्तेमाल किया जा सकता दिखा।

पूर्णांक की एक सूची संसाधित करने पर : मेरा दृष्टिकोण और बंटवारे की सूची पर: कस्टम सीमांकक, डुप्लिकेट को रोकने और आदेश को बनाए रखने के लिए , मैं दिखाता हूं कि स्ट्रिंग को विभाजित करने के लिए संख्या तालिका का उपयोग कैसे करें (जैसे अल्पविराम से अलग मूल्यों का एक सेट) और एक प्रदर्शन प्रदान करें इस और अन्य तरीकों के बीच तुलना। बंटवारे और अन्य स्ट्रिंग हैंडलिंग पर अधिक जानकारी:

और SQL सर्वर नंबर तालिका में, समझाया - भाग 1 , मैं अवधारणा के बारे में कुछ पृष्ठभूमि देता हूं और विशिष्ट अनुप्रयोगों को विस्तृत करने के लिए स्टोर में भविष्य के पोस्ट हैं।

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

@ @ की तरह, मेरे पास स्टैक ओवरफ्लो पर और इस साइट पर कुछ उत्तर हैं जो एक संख्या तालिका का भी उपयोग करते हैं।

अंत में, मेरे पास बिना लूपिंग के सेट जनरेट करने के बारे में ब्लॉग पोस्टों की एक श्रृंखला है, जो कि अधिकांश अन्य तरीकों की तुलना में संख्या तालिका का उपयोग करने के प्रदर्शन का लाभ दिखाती है (रेमुस की चतुर्भुज एक तरफ)


26

यहाँ एक बढ़िया उदाहरण है जिसका उपयोग मैंने हाल ही में एडम मैकहानिक से किया है:

CREATE FUNCTION dbo.GetSubstringCount
(
    @InputString TEXT, 
    @SubString VARCHAR(200),
    @NoisePattern VARCHAR(20)
)
RETURNS INT
WITH SCHEMABINDING
AS
BEGIN
    RETURN 
    (
        SELECT COUNT(*)
        FROM dbo.Numbers N
        WHERE
            SUBSTRING(@InputString, N.Number, LEN(@SubString)) = @SubString
            AND PATINDEX(@NoisePattern, SUBSTRING(@InputString, N.Number + LEN(@SubString), 1)) = 0
            AND 0 = 
                CASE 
                    WHEN @NoisePattern = '' THEN 0
                    ELSE PATINDEX(@NoisePattern, SUBSTRING(@InputString, N.Number - 1, 1))
                END
    )
END

मैंने CTEसहसंबंधित सीमांकित डेटा के साथ काम करने के लिए प्रतिस्थापन का एक विशिष्ट उदाहरण खोजने के लिए (यानी "इस स्ट्रिंग में 3 पाइप खोजें") के साथ कुछ इसी तरह का उपयोग किया :

declare @TargetStr varchar(8000), 
@SearchedStr varchar(8000), 
@Occurrence int
set @TargetStr='a'
set @SearchedStr='abbabba'
set @Occurrence=3;

WITH Occurrences AS (
SELECT Number,
       ROW_NUMBER() OVER(ORDER BY Number) AS Occurrence
FROM master.dbo.spt_values
WHERE Number BETWEEN 1 AND LEN(@SearchedStr) AND type='P'
  AND SUBSTRING(@SearchedStr,Number,LEN(@TargetStr))=@TargetStr)
SELECT Number
FROM Occurrences
WHERE Occurrence=@Occurrence

यदि आपके पास संख्या तालिका नहीं है, तो विकल्प किसी प्रकार के लूप का उपयोग करना है। मूल रूप से, एक अंक तालिका आपको कर्सर या लूप के बिना सेट-आधारित पुनरावृत्ति करने की अनुमति देती है।


5
और इनलाइन TVFs में स्ट्रिंग हेरफेर करने के खतरे के बारे में अनिवार्य चेतावनी: टी-एसक्यूएल फ़ंक्शन निष्पादन का एक निश्चित आदेश नहीं देते हैं
रेमस रुसानु

12

जब भी मुझे Enumerable.Range के SQL समकक्ष की आवश्यकता होती है मैं एक संख्या तालिका का उपयोग करूंगा। उदाहरण के लिए, मैंने इस साइट पर एक उत्तर में इसका उपयोग किया है: क्रमपरिवर्तन की संख्या की गणना

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.