दिलचस्प पोस्ट
कौन सा Iomanip manipulators 'चिपचिपा' रहे हैं? मैं आईफोन वेब अनुप्रयोग में पोर्ट्रेट मोड को अभिविन्यास कैसे लॉक कर सकता हूं? दोहरे उद्धरण चिह्नों के बीच एम्बेडेड डबल कोट्स के साथ स्ट्रिंग का मिलान कैसे करें? जांच कैसे करें कि क्या क्लिक ईवेंट पहले ही बाध्य है – JQuery जावास्क्रिप्ट नेस्टेड फ़ंक्शन पांडस आईएलओक बनाम ix बनाम लोक स्पष्टीकरण? JQuery AJAX के साथ क्रॉस-डोमेन समापन बिंदु लोड करना ऐस्डर्स फ़ोल्डर या कच्चे फ़ोल्डर से एंड्रॉइड में वीडियो कैसे खेलेंगे? निजी स्थिर सदस्यों को प्रारंभ करना कैसे एक अल्पविराम से अलग स्ट्रिंग विभाजित करने के लिए? जावास्क्रिप्ट में आपको टाइमस्टैम्प कैसे मिलता है? समय पर firebase ट्रिगर के लिए बादल कार्य? "आधुनिक" रेगेक्सस की मान्यता शक्ति ग्रिड लेआउट पर इशारे का पता लगाने में झंकार मशीन कहां है? कॉन्फ़िगर?

एसक्यूएल सर्वर में औसत गणना करने के लिए फ़ंक्शन

एमएसडीएन के मुताबिक, मध्य औसत ट्रांसएक्ट-एससीएल में एक समग्र कार्य के रूप में उपलब्ध नहीं है। हालांकि, मैं यह जानना चाहूंगा कि क्या यह कार्यक्षमता बनाना संभव है ( एकत्रित कार्य, उपयोगकर्ता परिभाषित कार्य, या कुछ अन्य विधि का उपयोग करके)।

ऐसा करने के लिए सबसे अच्छा तरीका क्या होगा (यदि संभव हो) – एक कुल क्वेरी में एक औसत मूल्य (एक संख्यात्मक डेटा प्रकार संभालने) की गणना करने की अनुमति दें?

वेब के समाधान से एकत्रित समाधान "एसक्यूएल सर्वर में औसत गणना करने के लिए फ़ंक्शन"

नाटकीय रूप से अलग प्रदर्शन के साथ ऐसा करने के कई तरीके हैं http://sqlblog.com/blogs/adam_machanic/archive/2006/12/18/medians-row-numbers-and-performance.aspx से यहां एक विशेष रूप से अच्छी तरह से अनुकूलित समाधान है। निष्पादन के दौरान वास्तविक आई / ओएस उत्पन्न होने पर यह एक महत्वपूर्ण इष्टतम समाधान है – यह अन्य समाधानों की तुलना में अधिक महंगा लग रहा है लेकिन यह वास्तव में बहुत तेज है।

उस पेज में अन्य समाधानों और पेर्फ परीक्षण विवरणों की चर्चा भी शामिल है। मध्य स्तंभ के समान मूल्य के साथ कई पंक्तियों के मामले में एक अनन्य स्तंभ के उपयोग को नोट करें।

सभी डेटाबेस प्रदर्शन परिदृश्यों के साथ-साथ वास्तविक हार्डवेयर पर वास्तविक डेटा के साथ एक समाधान का परीक्षण करने का प्रयास करें- आपको कभी नहीं पता होगा कि जब आपके परिवेश में एसक्यूएल सर्वर के अनुकूलक या विशिष्टता में कोई परिवर्तन होता है तो सामान्य रूप से तेज़ समाधान धीमा हो जाएगा

SELECT CustomerId, AVG(TotalDue) FROM ( SELECT CustomerId, TotalDue, ROW_NUMBER() OVER ( PARTITION BY CustomerId ORDER BY TotalDue ASC, SalesOrderId ASC) AS RowAsc, ROW_NUMBER() OVER ( PARTITION BY CustomerId ORDER BY TotalDue DESC, SalesOrderId DESC) AS RowDesc FROM Sales.SalesOrderHeader SOH ) x WHERE RowAsc IN (RowDesc, RowDesc - 1, RowDesc + 1) GROUP BY CustomerId ORDER BY CustomerId; 

यदि आप SQL 2005 या बेहतर उपयोग कर रहे हैं तो यह तालिका में एक एकल स्तंभ के लिए एक अच्छा, सरल-औसत माध्य गणना है:

 SELECT ( (SELECT MAX(Score) FROM (SELECT TOP 50 PERCENT Score FROM Posts ORDER BY Score) AS BottomHalf) + (SELECT MIN(Score) FROM (SELECT TOP 50 PERCENT Score FROM Posts ORDER BY Score DESC) AS TopHalf) ) / 2 AS Median 

SQL सर्वर 2012 में आपको PERCENTILE_CONT का उपयोग करना चाहिए:

 SELECT SalesOrderID, OrderQty, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY OrderQty) OVER (PARTITION BY SalesOrderID) AS MedianCont FROM Sales.SalesOrderDetail WHERE SalesOrderID IN (43670, 43669, 43667, 43663) ORDER BY SalesOrderID DESC 

यह भी देखें: http://blog.sqlauthority.com/2011/11/20/sql-server-introduction-to-percentile_cont-analytic-functions-introduced-in-sql-server-2012/

मेरा मूल त्वरित उत्तर था:

 select max(my_column) as [my_column], quartile from (select my_column, ntile(4) over (order by my_column) as [quartile] from my_table) i --where quartile = 2 group by quartile 

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

जब आप एक योजना की व्याख्या करते हैं, तो 60% काम डेटा को छांटना है जो इस तरह की स्थिति पर निर्भर आंकड़ों की गणना करते समय अपरिहार्य है।

मैंने निम्नलिखित टिप्पणियों में रॉबर्ट स्वीव्काक-रोबाज़ से उत्कृष्ट सुझाव का पालन करने के लिए उत्तर में संशोधन किया है:

 ;with PartitionedData as (select my_column, ntile(10) over (order by my_column) as [percentile] from my_table), MinimaAndMaxima as (select min(my_column) as [low], max(my_column) as [high], percentile from PartitionedData group by percentile) select case when b.percentile = 10 then cast(b.high as decimal(18,2)) else cast((a.low + b.high) as decimal(18,2)) / 2 end as [value], --b.high, a.low, b.percentile from MinimaAndMaxima a join MinimaAndMaxima b on (a.percentile -1 = b.percentile) or (a.percentile = 10 and b.percentile = 10) --where b.percentile = 5 

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

और भी बेहतर:

 SELECT @Median = AVG(1.0 * val) FROM ( SELECT o.val, rn = ROW_NUMBER() OVER (ORDER BY o.val), cc FROM dbo.EvenRows AS o CROSS JOIN (SELECT c = COUNT(*) FROM dbo.EvenRows) AS c ) AS x WHERE rn IN ((c + 1)/2, (c + 2)/2); 

मास्टर खुद से, इज़जिक बेन-गण !

एमएस SQL ​​सर्वर 2012 (और बाद में) PERCENTILE_DISC फ़ंक्शन है जो सॉर्ट किए गए मानों के लिए एक विशिष्ट प्रतिशत्य की गणना करता है। PERCENTILE_DISC (0.5) मध्यस्थ की गणना करेगा- https://msdn.microsoft.com/en-us/library/hh231327.aspx

मध्यस्थ के लिए एक सेट आधारित समाधान की तलाश करते समय मैं इस पृष्ठ पर आया था यहाँ कुछ समाधानों को देखने के बाद, मैं निम्नलिखित के साथ आया था उम्मीद है कि मदद करता है / काम करता है

 DECLARE @test TABLE( i int identity(1,1), id int, score float ) INSERT INTO @test (id,score) VALUES (1,10) INSERT INTO @test (id,score) VALUES (1,11) INSERT INTO @test (id,score) VALUES (1,15) INSERT INTO @test (id,score) VALUES (1,19) INSERT INTO @test (id,score) VALUES (1,20) INSERT INTO @test (id,score) VALUES (2,20) INSERT INTO @test (id,score) VALUES (2,21) INSERT INTO @test (id,score) VALUES (2,25) INSERT INTO @test (id,score) VALUES (2,29) INSERT INTO @test (id,score) VALUES (2,30) INSERT INTO @test (id,score) VALUES (3,20) INSERT INTO @test (id,score) VALUES (3,21) INSERT INTO @test (id,score) VALUES (3,25) INSERT INTO @test (id,score) VALUES (3,29) DECLARE @counts TABLE( id int, cnt int ) INSERT INTO @counts ( id, cnt ) SELECT id, COUNT(*) FROM @test GROUP BY id SELECT drv.id, drv.start, AVG(t.score) FROM ( SELECT MIN(ti)-1 AS start, t.id FROM @test t GROUP BY t.id ) drv INNER JOIN @test t ON drv.id = t.id INNER JOIN @counts c ON t.id = c.id WHERE ti = ((c.cnt+1)/2)+drv.start OR ( ti = (((c.cnt+1)%2) * ((c.cnt+2)/2))+drv.start AND ((c.cnt+1)%2) * ((c.cnt+2)/2) <> 0 ) GROUP BY drv.id, drv.start 

सरल, तेज, सटीक

 SELECT x.Amount FROM (SELECT amount, Count(1) OVER (partition BY 'A') AS TotalRows, Row_number() OVER (ORDER BY Amount ASC) AS AmountOrder FROM facttransaction ft) x WHERE x.AmountOrder = Round(x.TotalRows / 2.0, 0) 

यदि आप SQL सर्वर में समेकित फ़ंक्शन का उपयोग करना चाहते हैं, तो यह ऐसा करने के तरीके है। इसे इस तरह से करने से साफ प्रश्नों को लिखने में सक्षम होने का लाभ होता है। ध्यान दें इस प्रक्रिया को काफी आसानी से एक प्रतिशत मूल्य का आकलन करने के लिए अनुकूलित किया जा सकता है।

एक नया विज़ुअल स्टूडियो प्रोजेक्ट बनाएं और लक्ष्य ढांचे को .NET 3.5 पर सेट करें (यह एसक्यूएल 2008 के लिए है, यह SQL 2012 में अलग हो सकता है)। फिर एक क्लास फ़ाइल बनाएं और निम्नलिखित कोड, या सी # समकक्ष डाल दें:

 Imports Microsoft.SqlServer.Server Imports System.Data.SqlTypes Imports System.IO <Serializable> <SqlUserDefinedAggregate(Format.UserDefined, IsInvariantToNulls:=True, IsInvariantToDuplicates:=False, _ IsInvariantToOrder:=True, MaxByteSize:=-1, IsNullIfEmpty:=True)> Public Class Median Implements IBinarySerialize Private _items As List(Of Decimal) Public Sub Init() _items = New List(Of Decimal)() End Sub Public Sub Accumulate(value As SqlDecimal) If Not value.IsNull Then _items.Add(value.Value) End If End Sub Public Sub Merge(other As Median) If other._items IsNot Nothing Then _items.AddRange(other._items) End If End Sub Public Function Terminate() As SqlDecimal If _items.Count <> 0 Then Dim result As Decimal _items = _items.OrderBy(Function(i) i).ToList() If _items.Count Mod 2 = 0 Then result = ((_items((_items.Count / 2) - 1)) + (_items(_items.Count / 2))) / 2@ Else result = _items((_items.Count - 1) / 2) End If Return New SqlDecimal(result) Else Return New SqlDecimal() End If End Function Public Sub Read(r As BinaryReader) Implements IBinarySerialize.Read 'deserialize it from a string Dim list = r.ReadString() _items = New List(Of Decimal) For Each value In list.Split(","c) Dim number As Decimal If Decimal.TryParse(value, number) Then _items.Add(number) End If Next End Sub Public Sub Write(w As BinaryWriter) Implements IBinarySerialize.Write 'serialize the list to a string Dim list = "" For Each item In _items If list <> "" Then list += "," End If list += item.ToString() Next w.Write(list) End Sub End Class 

फिर इसे संकलित करें और अपने SQL सर्वर मशीन पर DLL और PDB फ़ाइल की प्रतिलिपि बनाएँ और SQL सर्वर में निम्न कमांड चलाएं:

 CREATE ASSEMBLY CustomAggregate FROM '{path to your DLL}' WITH PERMISSION_SET=SAFE; GO CREATE AGGREGATE Median(@value decimal(9, 3)) RETURNS decimal(9, 3) EXTERNAL NAME [CustomAggregate].[{namespace of your DLL}.Median]; GO 

तब आप मध्य की गणना करने के लिए एक क्वेरी लिख सकते हैं: SELECT dbo.Median (Field) FROM Table

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

शिकायत जो मुझे प्रतिशतता के बारे में मिलती है वह यह है कि यह आपको डेटासेट से एक वास्तविक मूल्य नहीं देते। डाटासेट उपयोग Percentile_Disc का एक वास्तविक मूल्य है जो एक "औसत" पर पहुंचने के लिए।

 SELECT SalesOrderID, OrderQty, PERCENTILE_DISC(0.5) WITHIN GROUP (ORDER BY OrderQty) OVER (PARTITION BY SalesOrderID) AS MedianCont FROM Sales.SalesOrderDetail WHERE SalesOrderID IN (43670, 43669, 43667, 43663) ORDER BY SalesOrderID DESC 

निम्न क्वेरी एक कॉलम में मानों की सूची से मध्य वापस लौटाता है। यह एक समेकित कार्य के साथ या इसके साथ प्रयोग नहीं किया जा सकता, लेकिन आप इन्हें भीतरी चयन में एक WHERE क्लॉज के साथ उप-क्वेरी के रूप में उपयोग कर सकते हैं।

SQL सर्वर 2005+:

 SELECT TOP 1 value from ( SELECT TOP 50 PERCENT value FROM table_name ORDER BY value )for_median ORDER BY value DESC 

एसक्यूएल में औसत गणना के लिए अन्य समाधान देखेंः " MySQL के साथ माध्यिका की गणना करने का आसान तरीका " (समाधान ज्यादातर विक्रेता-स्वतंत्र हैं)।

यूडीएफ में लिखिए

  Select Top 1 medianSortColumn from Table T Where (Select Count(*) from Table Where MedianSortColumn < (Select Count(*) From Table) / 2) Order By medianSortColumn 

एक निरंतर चर / माप के लिए 'col1' 'table1' से

 select col1 from (select top 50 percent col1, ROW_NUMBER() OVER(ORDER BY col1 ASC) AS Rowa, ROW_NUMBER() OVER(ORDER BY col1 DESC) AS Rowd from table1 ) tmp where tmp.Rowa = tmp.Rowd 

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

यहां मेरे परिणाम से एक टुकड़ा है:

 KEY VALUE ROWA ROWD 13 2 22 182 13 1 6 183 13 1 7 184 13 1 8 185 13 1 9 186 13 1 10 187 13 1 11 188 13 1 12 189 13 0 1 190 13 0 2 191 13 0 3 192 13 0 4 193 13 0 5 194 

मैंने इस समाधान के आधार के रूप में जस्टिन के कोड का इस्तेमाल किया यद्यपि एकाधिक व्युत्पन्न तालिकाओं के उपयोग को उतना कुशल नहीं किया जाता है, फिर भी यह मेरी ओर से पंक्ति क्रम की समस्या का समाधान करता है। किसी भी सुधार के स्वागत के रूप में मैं टी एसक्यूएल में अनुभवी नहीं हूँ

 SELECT PKEY, cast(AVG(VALUE)as decimal(5,2)) as MEDIANVALUE FROM ( SELECT PKEY,VALUE,ROWA,ROWD, 'FLAG' = (CASE WHEN ROWA IN (ROWD,ROWD-1,ROWD+1) THEN 1 ELSE 0 END) FROM ( SELECT PKEY, cast(VALUE as decimal(5,2)) as VALUE, ROWA, ROW_NUMBER() OVER (PARTITION BY PKEY ORDER BY ROWA DESC) as ROWD FROM ( SELECT PKEY, VALUE, ROW_NUMBER() OVER (PARTITION BY PKEY ORDER BY VALUE ASC,PKEY ASC ) as ROWA FROM [MTEST] )T1 )T2 )T3 WHERE FLAG = '1' GROUP BY PKEY ORDER BY PKEY 

मैं अपने आप में एक समाधान तैयार करना चाहता था, लेकिन मेरे दिमाग में फिसलकर रास्ते पर गिर गया। मुझे लगता है कि यह काम करता है, लेकिन सुबह में मुझे इसकी व्याख्या करने के लिए मत पूछो। : पी

 DECLARE @table AS TABLE ( Number int not null ); insert into @table select 2; insert into @table select 4; insert into @table select 9; insert into @table select 15; insert into @table select 22; insert into @table select 26; insert into @table select 37; insert into @table select 49; DECLARE @Count AS INT SELECT @Count = COUNT(*) FROM @table; WITH MyResults(RowNo, Number) AS ( SELECT RowNo, Number FROM (SELECT ROW_NUMBER() OVER (ORDER BY Number) AS RowNo, Number FROM @table) AS Foo ) SELECT AVG(Number) FROM MyResults WHERE RowNo = (@Count+1)/2 OR RowNo = ((@Count+1)%2) * ((@Count+2)/2) 
 --Create Temp Table to Store Results in DECLARE @results AS TABLE ( [Month] datetime not null ,[Median] int not null ); --This variable will determine the date DECLARE @IntDate as int set @IntDate = -13 WHILE (@IntDate < 0) BEGIN --Create Temp Table DECLARE @table AS TABLE ( [Rank] int not null ,[Days Open] int not null ); --Insert records into Temp Table insert into @table SELECT rank() OVER (ORDER BY DATEADD(mm, DATEDIFF(mm, 0, DATEADD(ss, SVR.close_date, '1970')), 0), DATEDIFF(day,DATEADD(ss, SVR.open_date, '1970'),DATEADD(ss, SVR.close_date, '1970')),[SVR].[ref_num]) as [Rank] ,DATEDIFF(day,DATEADD(ss, SVR.open_date, '1970'),DATEADD(ss, SVR.close_date, '1970')) as [Days Open] FROM mdbrpt.dbo.View_Request SVR LEFT OUTER JOIN dbo.dtv_apps_systems vapp on SVR.category = vapp.persid LEFT OUTER JOIN dbo.prob_ctg pctg on SVR.category = pctg.persid Left Outer Join [mdbrpt].[dbo].[rootcause] as [Root Cause] on [SVR].[rootcause]=[Root Cause].[id] Left Outer Join [mdbrpt].[dbo].[cr_stat] as [Status] on [SVR].[status]=[Status].[code] LEFT OUTER JOIN [mdbrpt].[dbo].[net_res] as [net] on [net].[id]=SVR.[affected_rc] WHERE SVR.Type IN ('P') AND SVR.close_date IS NOT NULL AND [Status].[SYM] = 'Closed' AND SVR.parent is null AND [Root Cause].[sym] in ( 'RC - Application','RC - Hardware', 'RC - Operational', 'RC - Unknown') AND ( [vapp].[appl_name] in ('3PI','Billing Rpts/Files','Collabrent','Reports','STMS','STMS 2','Telco','Comergent','OOM','C3-BAU','C3-DD','DIRECTV','DIRECTV Sales','DIRECTV Self Care','Dealer Website','EI Servlet','Enterprise Integration','ET','ICAN','ODS','SB-SCM','SeeBeyond','Digital Dashboard','IVR','OMS','Order Services','Retail Services','OSCAR','SAP','CTI','RIO','RIO Call Center','RIO Field Services','FSS-RIO3','TAOS','TCS') OR pctg.sym in ('Systems.Release Health Dashboard.Problem','DTV QA Test.Enterprise Release.Deferred Defect Log') AND [Net].[nr_desc] in ('3PI','Billing Rpts/Files','Collabrent','Reports','STMS','STMS 2','Telco','Comergent','OOM','C3-BAU','C3-DD','DIRECTV','DIRECTV Sales','DIRECTV Self Care','Dealer Website','EI Servlet','Enterprise Integration','ET','ICAN','ODS','SB-SCM','SeeBeyond','Digital Dashboard','IVR','OMS','Order Services','Retail Services','OSCAR','SAP','CTI','RIO','RIO Call Center','RIO Field Services','FSS-RIO3','TAOS','TCS') ) AND DATEADD(mm, DATEDIFF(mm, 0, DATEADD(ss, SVR.close_date, '1970')), 0) = DATEADD(mm, DATEDIFF(mm,0,DATEADD(mm,@IntDate,getdate())), 0) ORDER BY [Days Open] DECLARE @Count AS INT SELECT @Count = COUNT(*) FROM @table; WITH MyResults(RowNo, [Days Open]) AS ( SELECT RowNo, [Days Open] FROM (SELECT ROW_NUMBER() OVER (ORDER BY [Days Open]) AS RowNo, [Days Open] FROM @table) AS Foo ) insert into @results SELECT DATEADD(mm, DATEDIFF(mm,0,DATEADD(mm,@IntDate,getdate())), 0) as [Month] ,AVG([Days Open])as [Median] FROM MyResults WHERE RowNo = (@Count+1)/2 OR RowNo = ((@Count+1)%2) * ((@Count+2)/2) set @IntDate = @IntDate+1 DELETE FROM @table END select * from @results order by [Month] 

यह SQL 2000 के साथ काम करता है:

 DECLARE @testTable TABLE ( VALUE INT ) --INSERT INTO @testTable -- Even Test --SELECT 3 UNION ALL --SELECT 5 UNION ALL --SELECT 7 UNION ALL --SELECT 12 UNION ALL --SELECT 13 UNION ALL --SELECT 14 UNION ALL --SELECT 21 UNION ALL --SELECT 23 UNION ALL --SELECT 23 UNION ALL --SELECT 23 UNION ALL --SELECT 23 UNION ALL --SELECT 29 UNION ALL --SELECT 40 UNION ALL --SELECT 56 -- --INSERT INTO @testTable -- Odd Test --SELECT 3 UNION ALL --SELECT 5 UNION ALL --SELECT 7 UNION ALL --SELECT 12 UNION ALL --SELECT 13 UNION ALL --SELECT 14 UNION ALL --SELECT 21 UNION ALL --SELECT 23 UNION ALL --SELECT 23 UNION ALL --SELECT 23 UNION ALL --SELECT 23 UNION ALL --SELECT 29 UNION ALL --SELECT 39 UNION ALL --SELECT 40 UNION ALL --SELECT 56 DECLARE @RowAsc TABLE ( ID INT IDENTITY, Amount INT ) INSERT INTO @RowAsc SELECT VALUE FROM @testTable ORDER BY VALUE ASC SELECT AVG(amount) FROM @RowAsc ra WHERE ra.id IN ( SELECT ID FROM @RowAsc WHERE ra.id - ( SELECT MAX(id) / 2.0 FROM @RowAsc ) BETWEEN 0 AND 1 ) 

अपने जैसे नए विद्यार्थियों के लिए जो मूलभूत बातें सीख रहे हैं, मैं व्यक्तिगत रूप से इस उदाहरण को आसानी से पाता हूं, क्योंकि यह समझना आसान है कि क्या हो रहा है और जहां से औसत मूल्य आ रहे हैं …

 select ( max(a.[Value1]) + min(a.[Value1]) ) / 2 as [Median Value1] ,( max(a.[Value2]) + min(a.[Value2]) ) / 2 as [Median Value2] from (select datediff(dd,startdate,enddate) as [Value1] ,xxxxxxxxxxxxxx as [Value2] from dbo.table1 )a 

हालांकि ऊपर दिए गए कुछ कोडों के पूर्ण भय में !!!

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

 SELECT TOP 1 ValueField AS MedianValue FROM (SELECT TOP(SELECT COUNT(1)/2 FROM tTABLE) ValueField FROM tTABLE ORDER BY ValueField) A ORDER BY ValueField DESC 

निम्नलिखित समाधान इन मान्यताओं के तहत काम करता है:

  • डुप्लिकेट मान नहीं है
  • कोई औजार नहीं

कोड:

 IF OBJECT_ID('dbo.R', 'U') IS NOT NULL DROP TABLE dbo.R CREATE TABLE R ( A FLOAT NOT NULL); INSERT INTO R VALUES (1); INSERT INTO R VALUES (2); INSERT INTO R VALUES (3); INSERT INTO R VALUES (4); INSERT INTO R VALUES (5); INSERT INTO R VALUES (6); -- Returns Median(R) select SUM(A) / CAST(COUNT(A) AS FLOAT) from R R1 where ((select count(A) from R R2 where R1.A > R2.A) = (select count(A) from R R2 where R1.A < R2.A)) OR ((select count(A) from R R2 where R1.A > R2.A) + 1 = (select count(A) from R R2 where R1.A < R2.A)) OR ((select count(A) from R R2 where R1.A > R2.A) = (select count(A) from R R2 where R1.A < R2.A) + 1) ; 
 DECLARE @Obs int DECLARE @RowAsc table ( ID INT IDENTITY, Observation FLOAT ) INSERT INTO @RowAsc SELECT Observations FROM MyTable ORDER BY 1 SELECT @Obs=COUNT(*)/2 FROM @RowAsc SELECT Observation AS Median FROM @RowAsc WHERE ID=@Obs 

बड़े पैमाने पर डेटासेट के लिए, आप इस जीआईएसआईएस प्रयास कर सकते हैं:

https://gist.github.com/chrisknoll/1b38761ce8c5016ec5b2

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

मैं कई विकल्पों के साथ कोशिश करता हूं, लेकिन मेरे डेटा रिकॉर्ड के कारण मूल्य दोहराए हैं, ROW_NUMBER संस्करण मेरे लिए कोई विकल्प नहीं हैं तो यहां मैंने जो प्रश्न इस्तेमाल किया (NTILE के साथ एक संस्करण):

 SELECT distinct CustomerId, ( MAX(CASE WHEN Percent50_Asc=1 THEN TotalDue END) OVER (PARTITION BY CustomerId) + MIN(CASE WHEN Percent50_desc=1 THEN TotalDue END) OVER (PARTITION BY CustomerId) )/2 MEDIAN FROM ( SELECT CustomerId, TotalDue, NTILE(2) OVER ( PARTITION BY CustomerId ORDER BY TotalDue ASC) AS Percent50_Asc, NTILE(2) OVER ( PARTITION BY CustomerId ORDER BY TotalDue DESC) AS Percent50_desc FROM Sales.SalesOrderHeader SOH ) x ORDER BY CustomerId; 

जेफ एटवुड का उत्तर ऊपर बिल्डिंग से ऊपर है, यह ग्रुप द्वारा और प्रत्येक समूह के लिए मध्य प्राप्त करने के लिए एक सहसंबद्ध subquery के साथ है।

 SELECT TestID, ( (SELECT MAX(Score) FROM (SELECT TOP 50 PERCENT Score FROM Posts WHERE TestID = Posts_parent.TestID ORDER BY Score) AS BottomHalf) + (SELECT MIN(Score) FROM (SELECT TOP 50 PERCENT Score FROM Posts WHERE TestID = Posts_parent.TestID ORDER BY Score DESC) AS TopHalf) ) / 2 AS MedianScore, AVG(Score) AS AvgScore, MIN(Score) AS MinScore, MAX(Score) AS MaxScore FROM Posts_parent GROUP BY Posts_parent.TestID 

बार-बार, हमें संपूर्ण तालिका के लिए मध्य की गणना करने की आवश्यकता हो सकती है, लेकिन किसी आईडी के संबंध में समुच्चय के लिए दूसरे शब्दों में, हमारी तालिका में प्रत्येक आईडी के लिए औसत गणना, जहां प्रत्येक आईडी में कई रिकॉर्ड हैं (@ गोडोरन द्वारा संपादित समाधान के आधार पर: कई एसक्यूएल में अच्छा प्रदर्शन और काम करता है)

 SELECT our_id, AVG(1.0 * our_val) as Median FROM ( SELECT our_id, our_val, COUNT(*) OVER (PARTITION BY our_id) AS cnt, ROW_NUMBER() OVER (PARTITION BY our_id ORDER BY our_val) AS rnk FROM our_table ) AS x WHERE rnk IN ((cnt + 1)/2, (cnt + 2)/2) GROUP BY our_id; 

आशा करता हूँ की ये काम करेगा।

आपके प्रश्न के लिए, जेफ एटवुड ने पहले से ही सरल और प्रभावी समाधान दिया था। लेकिन, यदि आप औसत गणना करने के लिए कुछ वैकल्पिक दृष्टिकोण की तलाश कर रहे हैं, तो नीचे एसक्यूएल कोड आपको मदद करेगा।

 create table employees(salary int); insert into employees values(8); insert into employees values(23); insert into employees values(45); insert into employees values(123); insert into employees values(93); insert into employees values(2342); insert into employees values(2238); select * from employees; declare @odd_even int; declare @cnt int; declare @middle_no int; set @cnt=(select count(*) from employees); set @middle_no=(@cnt/2)+1; select @odd_even=case when (@cnt%2=0) THEN -1 ELse 0 END ; select AVG(tbl.salary) from (select salary,ROW_NUMBER() over (order by salary) as rno from employees group by salary) tbl where tbl.rno=@middle_no or tbl.rno=@middle_no+@odd_even;