2016-08-15 2 views
-2

Für eine bestimmte Tabelle möchte ich eine SQL-Abfrage, die den statistischen Modus jeder Spalte in einem einzelnen Re-Cord-Set zurückgibt. Ich sehe mehrere Möglichkeiten, dies mit Aggregation zu tun, aber sie sind alle Ein-Spalten-Ansätze. Kann jemand einen Weg finden, dies zu tun, ohne die Vereinigung von so vielen Abfragen wie es Spalten gibt? Es gibt kein mode() - Aggregat in SQL Server.SQL Server - statistischer Modus jeder Spalte

Wenn Tabelle #x 3 Spalten hat, möchte ich eine einzelne Zeile mit 3 Spalten. Hier ist ein Beispiel mit SQL Server. Es ist eine Menge schweres Heben und sehr auf die Tischdefinition zugeschnitten. Ich suche nach einem saubereren, allgemeineren Ansatz. Ich möchte das vielleicht zu verschiedenen Zeiten auf verschiedenen Tischen machen.

create table #x (name varchar(20), age int, city varchar(20)) 
insert into #x values ('Bill', 20, 'NYC') 
insert into #x values ('Bill', 15, 'NYC') 
insert into #x values ('Mary', 29, 'LA') 
insert into #x values ('Bill', 30, 'NYC') 
insert into #x values ('Bill', 30, 'NYC') 
insert into #x values ('Bill', 20, 'LA') 
insert into #x values ('Mary', 20, 'NYC') 
insert into #x values ('Joe', 12, 'NYC') 
insert into #x values ('Fred', 55, 'NYC') 
insert into #x values ('Alex', 41, 'NYC') 
insert into #x values ('Alex', 30, 'LA') 
insert into #x values ('Alex', 10, 'Chicago') 
insert into #x values ('Bill', 20, 'NYC') 
insert into #x values ('Bill', 10, 'NYC') 

create table #modes (_column varchar(20), _count int, _mode varchar(20)) 
insert into #modes select top 1 'name' _column, count(*) _count, name _mode from #x group by name order by 2 desc 
insert into #modes select top 1 'age' _column, count(*) _count, age _mode from #x group by age order by 2 desc 
insert into #modes select top 1 'city' _column, count(*) _count, city _mode from #x group by city order by 2 desc 

select name, age, city from (select _mode, _column from #modes) m 
pivot (max(_mode) for _column in (name, age, city)) p 
+0

Können Sie bitte mit einigen Beispieldaten und Post erwartete Ergebnis – TheGameiswar

+0

aktualisiert mit Beispiel und den gewünschten Ausgang erklären. – bvy

Antwort

0

Dies generiert Item, Value und Hits dynamisch. Sie können wie gewünscht drehen.

Declare @YourTable table (name varchar(20), age int, city varchar(20)) 
Insert Into @YourTable values 
('Bill', 20, 'NYC'), 
('Bill', 15, 'NYC'), 
('Mary', 29, 'LA'), 
('Bill', 30, 'NYC'), 
('Bill', 30, 'NYC'), 
('Bill', 20, 'LA'), 
('Mary', 20, 'NYC'), 
('Joe', 12, 'NYC'), 
('Fred', 55, 'NYC'), 
('Alex', 41, 'NYC'), 
('Alex', 30, 'LA'), 
('Alex', 10, 'Chicago'), 
('Bill', 20, 'NYC'), 
('Bill', 10, 'NYC') 

Declare @XML xml 
Set @XML = (Select * from @YourTable for XML RAW) 

Select Item,Value,Hits 
From (
     Select Item,Value,Hits=count(*),RowNr = ROW_NUMBER() over (Partition By Item Order By Count(*) Desc) 
     From (
       Select ID = r.value('@id','int')       -- Usually Reserved 
         ,Item = Attr.value('local-name(.)','varchar(100)') 
         ,Value = Attr.value('.','varchar(max)') 
       From @XML.nodes('/row') as A(r) 
       Cross Apply A.r.nodes('./@*[local-name(.)!="id"]') as B(Attr) 
      ) A 
     Group By Item,Value 
    ) A 
Where RowNr=1 

Returns

Item Value Hits 
age  20  4 
city NYC  10 
name Bill 7 
+0

Ein bisschen out of the box, da es den XML-Datentyp verwendet, den ich nicht kenne. Aber es scheint mit jedem Tisch zu funktionieren, den Sie darauf werfen. Vielen Dank. – bvy

+0

@bvy Das war die Idee. Ich bin ein fauler Programmierer, ich schreibe lieber einmal etwas und lasse es mehrere Masterserver betreiben. Ich war ein verspäteter XML-Nutzer. Ich wünschte, ich hätte es früher angenommen. –