2011-08-03 9 views
5

मान लीजिए कि आप स्तंभों, तिथि, ग्रुप, एक्स और वाईक्या सीटीई के बजाए ओवर क्लॉज का उपयोग कर टीएसक्यूएल में सहसंबंध की गणना करने का कोई तरीका है?

CREATE TABLE #sample 
    (
    [Date] DATETIME, 
    GroupID INT, 
    X  FLOAT, 
    Y  FLOAT 
) 

DECLARE @date DATETIME = getdate() 

INSERT INTO #sample VALUES(@date, 1, 1,3) 
INSERT INTO #sample VALUES(DATEADD(d, 1, @date), 1, 1,1) 
INSERT INTO #sample VALUES(DATEADD(d, 2, @date), 1, 4,2) 
INSERT INTO #sample VALUES(DATEADD(d, 3, @date), 1, 3,3) 
INSERT INTO #sample VALUES(DATEADD(d, 4, @date), 1, 6,4) 
INSERT INTO #sample VALUES(DATEADD(d, 5, @date), 1, 7,5) 
INSERT INTO #sample VALUES(DATEADD(d, 6, @date), 1, 1,6) 

के साथ एक मेज है और आप प्रत्येक समूह के लिए एक्स और वाई के सहसंबंध की गणना करना चाहते हैं।

;WITH DataAvgStd 
    AS (SELECT GroupID, 
       AVG(X) AS XAvg, 
       AVG(Y) AS YAvg, 
       STDEV(X) AS XStdev, 
       STDEV(Y) AS YSTDev, 
       COUNT(*) AS SampleSize 
     FROM #sample 
     GROUP BY GroupID), 
    ExpectedVal 
    AS (SELECT s.GroupID, 
       SUM((X - XAvg) * (Y - YAvg)) AS ExpectedValue 
     FROM #sample s 
       JOIN DataAvgStd das 
        ON s.GroupID = das.GroupID 
     GROUP BY s.GroupID) 
SELECT das.GroupID, 
     ev.ExpectedValue/(das.SampleSize - 1)/(das.XStdev * das.YSTDev) 
     AS 
     Correlation 
FROM DataAvgStd das 
     JOIN ExpectedVal ev 
     ON das.GroupID = ev.GroupID 

DROP TABLE #sample 

ऐसा लगता है कि वहाँ पर उपयोग करने के लिए एक तरह से और विभाजन किसी भी सबक्वेरी के बिना एक ही बार में यह करने के लिए किया जाना चाहिए: वर्तमान में मैं सीटीई जो एक छोटे से गंदा मिल का उपयोग करें।

SELECT GroupID, CORR(X, Y) OVER(PARTITION BY GroupID) 
FROM #sample 
GROUP BY GroupID 
+0

मुझे यह देखने में दिलचस्पी होगी कि कोई भी व्यवहार्य समाधान के साथ आता है, हालांकि, मैं हमेशा अपने सभी डेटा को व्यापार परत पर खींचता हूं और वहां सहसंबंध करता हूं। हम जो भी हम "ऋणात्मक सहसंबंध" कहते हैं, हम भी करते हैं - जहां हम सकारात्मक मूल्यों को छोड़ते हैं और केवल नकारात्मक मानों को शामिल करते हैं - यह देखना दिलचस्प होगा कि यह SQL में व्यवहार्य है या नहीं। –

+0

आपके द्वारा पोस्ट किया गया कोड विभिन्न कारणों से निष्पादित नहीं हुआ था। मैंने इसे बदल दिया है, इसलिए यह वास्तव में चलता है कि आप यह सत्यापित करना चाहते हैं कि यह अभी भी जो कुछ भी आप कर रहे थे ... –

+0

यदि एक्स या वाई निरर्थक हैं, तो आपको "# से नमूना" को "# से नमूना" के साथ बदलना होगा जहां एक्स है नल और वाई पूर्ण नहीं है ", अन्यथा आप गलत सहसंबंध –

उत्तर

5

कोरलेशन के इस सूत्र का उपयोग करके आप सभी नेस्टेड प्रश्नों से बच नहीं सकते हैं भले ही आप over() का उपयोग करें। बात यह है कि आप एक ही प्रश्न में दोनों समूहों का उपयोग नहीं कर सकते हैं और आप नेस्टेड एग्रीगेशन फ़ंक्शंस भी नहीं कर सकते हैं उदा। sum(x - avg(x))। तो आप अपने डेटा के अनुसार, सर्वोत्तम मामले परिदृश्य में, आपको कम से कम with रखना होगा।

आपका कोड है कि

;WITH DataAvgStd 
    AS (SELECT GroupID, 
       STDEV(X) over(partition by GroupID) AS XStdev, 
       STDEV(Y) over(partition by GroupID) AS YSTDev, 
       COUNT(*) over(partition by GroupID) AS SampleSize, 
       (X - AVG(X) over(partition by GroupID)) * (Y - AVG(Y) over(partition by GroupID)) AS ExpectedValue 
     FROM #sample s)   
SELECT distinct GroupID, 
     SUM(ExpectedValue) over(partition by GroupID)/(SampleSize - 1)/(XStdev * YSTDev) AS Correlation 
FROM DataAvgStd 

एक विकल्प के रूप Wikipedia का वर्णन करता है सहसंबंध के लिए एक equilevant सूत्र का उपयोग करने के लिए है की तरह कुछ की तरह दिखाई देगा।

इस रूप में

SELECT GroupID, 
     Correlation=(COUNT(*) * SUM(X * Y) - SUM(X) * SUM(Y))/
        (SQRT(COUNT(*) * SUM(X * X) - SUM(X) * SUM(x)) 
        * SQRT(COUNT(*) * SUM(Y* Y) - SUM(Y) * SUM(Y))) 
FROM #sample s 
GROUP BY GroupID; 
+0

दूसरा सूत्र जिसका आप उल्लेख करते हैं, यह विकिपीडिया लेख में कहां है? मुझे यह बिल्कुल नहीं दिख रहा है। – bpeikes

+0

@bpeikes यह 'पियरसन के उत्पाद-पल गुणांक' अनुभाग में अंतिम सूत्र है। – Athafoud

1

एसक्यूएल प्राप्त नेस्टिंग समुच्चय या विंडोइंग काम करता है, इसलिए सीटीई या व्युत्पन्न तालिकाओं के लिए जरूरत के बारे में थोड़ा अजीब है: आदर्श रूप में TSQL तो आप लिख सकते हैं एक समारोह होगा।

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

एक समान सीएलआर कुल बनाने पर http://www.sqlservercentral.com/articles/SQLCLR/71942/ पर एक अच्छा ट्यूटोरियल है।

+1

हाँ के साथ समाप्त हो सकते हैं।मुझे नहीं पता कि कोई भी "व्यापार" परत में ऐसा क्यों करना चाहेगा। सहसंबंधों की गणना करने के लिए आपको डेटाबेस से डेटा का एक टन खींचना होगा। जो मैं वास्तव में समझ में नहीं आता यह है कि एसक्यूएल सर्वर के पास एक अंतर्निहित के रूप में नहीं है। ऐसा लगता है कि SQL सर्वर संख्याओं को अनुकूलित करने के लिए एक बेहतर काम कर सकता है। – bpeikes

1

लिखा जा सकता है दोनों calcs के लिए एक एकल-पास समाधान:

एक नमूना के लिए एक और एक पूरी जनसंख्या के लिए एक पियर्सन सहसंबंध गुणांक के दो जायके, कर रहे हैं। ये सरल, एकल पास, दोनों के लिए सही सूत्रों रहे हैं, और मेरा मानना ​​है कि:

-- Methods for calculating the two Pearson correlation coefficients 
SELECT 
     -- For Population 
     (avg(x * y) - avg(x) * avg(y))/
     (sqrt(avg(x * x) - avg(x) * avg(x)) * sqrt(avg(y * y) - avg(y) * avg(y))) 
     AS correlation_coefficient_population, 
     -- For Sample 
     (count(*) * sum(x * y) - sum(x) * sum(y))/
     (sqrt(count(*) * sum(x * x) - sum(x) * sum(x)) * sqrt(count(*) * sum(y * y) - sum(y) * sum(y))) 
     AS correlation_coefficient_sample 
    FROM (
     -- The following generates a table of sample data containing two columns with a luke-warm and tweakable correlation 
     -- y = x for 0 thru 99, y = x - 100 for 100 thru 199, etc. Execute it as a stand-alone to see for yourself 
     -- x and y are CAST as DECIMAL to avoid integer math, you should definitely do the same 
     -- Try TOP 100 or less for full correlation (y = x for all cases), TOP 200 for a PCC of 0.5, TOP 300 for one near 0.33, etc. 
     -- The superfluous "+ 0" is where you could apply various offsets to see that they have no effect on the results 
     SELECT TOP 200 
       CAST(ROW_NUMBER() OVER (ORDER BY [object_id]) - 1 + 0 AS DECIMAL) AS x, 
       CAST((ROW_NUMBER() OVER (ORDER BY [object_id]) - 1) % 100 AS DECIMAL) AS y 
      FROM sys.all_objects 
    ) AS a 

जैसा कि मैंने टिप्पणी में बताया गया है, आप के साथ सभी के लिए टॉप 100 या पूर्ण सहसंबंध के लिए कम (y = एक्स उदाहरण कोशिश कर सकते हैं मामले); शीर्ष 200 उपज सहसंबंध 0.5 के करीब है; शीर्ष 300, लगभग 0.33; इत्यादि। अगर आपको पसंद है तो ऑफसेट जोड़ने के लिए एक जगह ("+ 0") है; spoiler चेतावनी, इसका कोई प्रभाव नहीं है। सुनिश्चित करें कि आप अपने मूल्यों को DECIMAL के रूप में CASTIMAL - पूर्णांक गणित इन कैल्क्स को महत्वपूर्ण रूप से प्रभावित कर सकते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे