{"id":28,"date":"2006-07-08T00:31:54","date_gmt":"2006-07-07T22:31:54","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/2006\/07\/08\/sql-talk\/headwriteline-das-median-problem-teil-2\/"},"modified":"2006-07-09T00:39:31","modified_gmt":"2006-07-08T22:39:31","slug":"headwriteline-das-median-problem-teil-2","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2006\/07\/08\/sql-talk\/headwriteline-das-median-problem-teil-2","title":{"rendered":"Ein Median mit SQL Server 2000"},"content":{"rendered":"<p>Ich habe heute entdeckt, dass bei <a href=\"http:\/\/headwriteline.blogspot.com\/2006\/04\/das-median-problem-teil-2.html\" target=\"_blank\">head.WriteLine(): Das Median-Problem, Teil 2<\/a> diskutiert wird, wie man mit SQL den Median berechnen kann. Die folgende Formulierung reizte meinen Spieltrieb:<\/p>\n<blockquote><p>Dank der neuen Rankingfunktionen des SQL Server 2005, ist die Ermittlung jedoch wesentlich einfacher als mit den Vorg&#228;ngerversionen. Hier h&#228;tte ich den Median n&#228;mlich in zeitaufwendigen Cursor- oder Schleifendurchl&#228;ufen ermitteln m&#252;ssen.<\/p><\/blockquote>\n<p>Generell stimmt es, die neuen Ranking-Funktionen sind wirklich gro&#223;artig. Ich hatte sie schon sooo lange vermisst. Aber die Geschichte mit den Cursors oder Schleifen m&#246;chte ich gerne widerlegen.<br \/>\nEine simple Median-Berechnung w&#252;rde mit SQL Server 2000 so aussehen:<\/p>\n<pre>select top 1 Quantity as \"Fast Median (1)\"\r\n     from (    SELECT TOP 50 percent Quantity\r\n                      FROM #bla\r\n                      order by Quantity) as d\r\n     order by Quantity desc<\/pre>\n<p>Ein Blick auf den Query Plan zeigt, dass hier noch leichter Spielraum f&#252;r Verbesserungen besteht:<\/p>\n<pre>select max(Quantity) as \"Fast Median (2)\"\r\n     from (    SELECT TOP 50 percent Quantity\r\n                      FROM #bla\r\n                      order by Quantity) as d<\/pre>\n<p>Nun leider ist das Leben nicht immer so einfach. Obige Berechnungen klappen nur bei einer ungeraden Anzahl an Werten. Aber wie man in der <a title=\"Wikipedia - Median\" target=\"_blank\" href=\"http:\/\/de.wikipedia.org\/wiki\/Median\">Wikipedia<\/a> nachlesen kann, muss man bei einer geraden Anzahl den Durchschnitt der mittleren Werte ausgeben. Das sieht dann schon komplizierter aus.<\/p>\n<pre>select ((select max(Quantity)\r\n                   from (    SELECT TOP 50 percent Quantity\r\n                                    FROM #bla\r\n                                    order by Quantity asc) as d)\r\n          +(select min(Quantity)\r\n                   from (    SELECT TOP 50 percent Quantity\r\n                                    FROM #bla\r\n                                    order by Quantity desc) as d)\r\n          )\/2 as \"richtiger Median\"<\/pre>\n<p>Wenn jetzt zu allen &#220;bel die Werte noch ganzzahlig sind, dann muss man vor der Division den Typ in Numeric konvertieren:<\/p>\n<pre>\r\nselect cast(\r\n          (select max(Quantity)\r\n                from (    SELECT TOP 50 percent Quantity\r\n                                   FROM #bla\r\n                            order by Quantity asc) as d)\r\n        +(select min(Quantity)\r\n                from (    SELECT TOP 50 percent Quantity\r\n                                   FROM #bla\r\n                            order by Quantity desc) as d)\r\n        as numeric(12,2))\/2 as \"richtiger Median bei ganzen Zahlen\"<\/pre>\n<p>Nat&#252;rlich ist diese L&#246;sung nicht blitzschnell, aber durch einen geeigneten Index kann man das Ganze doch sch&#246;n beschleunigen.<\/p>\n<p>Zuletzt noch der Code, um die Beispieltabelle anzulegen und zu best&#252;cken:<\/p>\n<pre>if object_id(N'tempdb..#bla') is not null drop table #bla\r\ncreate table #bla (quantity numeric(12,2))\r\n\r\ninsert into #bla(quantity) values (1)\r\ninsert into #bla(quantity) values (2)\r\ninsert into #bla(quantity) values (3)\r\ninsert into #bla(quantity) values (4)\r\ninsert into #bla(quantity) values (5)\r\ninsert into #bla(quantity) values (105)<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Ich habe heute entdeckt, dass bei head.WriteLine(): Das Median-Problem, Teil 2 diskutiert wird, wie man mit SQL den Median berechnen kann. Die folgende Formulierung reizte meinen Spieltrieb: Dank der neuen Rankingfunktionen des SQL Server 2005, ist die Ermittlung jedoch wesentlich einfacher als mit den Vorg&#228;ngerversionen. Hier h&#228;tte ich den Median n&#228;mlich in zeitaufwendigen Cursor- oder [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/28"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=28"}],"version-history":[{"count":0,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/28\/revisions"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=28"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=28"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=28"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}