2009-03-30 10 views
1

Ich habe zwei Tabellen (Management und Mitarbeiter).Frage zur SQL-Abfrage (Möglicher Beitritt/Unterabfrage?)

Die Verwaltungstabelle verfolgt die verschiedenen Managementteams, die das Unternehmen X in den letzten Jahren verwaltet haben. Jedes Managementteam erhält eine ID (z. B. managementnr), und jedes Team hat einen CEO (ceoname).

Die Mitarbeitertabelle verfolgt Mitarbeiter für Unternehmen X arbeiten (im Grunde ihre Namen nur und das Management-Team engagierte sie)

Hier ist der SQL-Code:


CREATE TABLE EMPLOYEE(
    EMPLOYEENAME VARCHAR2(15) NOT NULL, 
    HIRETEAM NUMBER(2), 
    PRIMARY KEY (EMPLOYEENAME) 
    ); 

CREATE TABLE MANAGEMENT(
    MANAGEMENTNR NUMBER(2) NOT NULL, 
    CEONAME VARCHAR2(20) NOT NULL, 
    PRIMARY KEY (MANAGEMENTNR,CEONAME) 
    ); 

Ich versuche, eine SQL zu bilden Abfrage, um die ManagementNR zu erhalten, in der die höchste Anzahl an Mitarbeitern eingestellt wurde. Ich habe versucht mit:

SELECT HIRETEAM,max(count(HIRETEAM)) 
from EMPLOYEE 
group by HIRETEAM 

aber ich bekomme immer wieder:

ORA-00937: not a single-group group function 

(Ich bin mit Oracle)

Nach Stunden des Google-fu, verstehe ich endlich, was dieser Fehler bedeutet, aber ich kann mir immer noch keine andere Möglichkeit vorstellen, diese Abfrage zu erstellen. Ich habe versucht, Unterabfragen/Joins zu verwenden, aber immer noch nichts. Ich bin SQL im Allgemeinen sehr neu. Wenn jemand helfen kann, wäre ich wirklich dankbar!

Vielen Dank für Ihre Zeit =]
--Evan Lestrange

Antwort

2

die erste Zeile aus dieser Abfrage holen:

select hireteam,count(*) from EMPLOYEE group by hireteam order by count(*) desc 
0

Auf diese Weise können alle Teams mit der Anzahl der eingestellten Mitarbeiter bekommen.

select 
    Management.ManagementNr, 
    Management.CeoName, 
    count(Employee.EmployeeName) 
from 
    Employee 
inner join 
    Management on Employee.HireTeam = Management.ManagementNr 
group by 
    Management.ManagementNr 
order by 
    count(Employee.EmployeeName) desc 

Hinzufügen eine zusätzliche having-Klausel und Verzicht auf die Verbindung (weil der CEO Name nicht erforderlich ist, wie ich gerade erkannt) Sie Ihr gewünschtes Ergebnis wie folgt.

Dies kann tatsächlich mehrere Zeilen zurückgeben, wenn mehrere Management die gleiche Anzahl von Mitarbeitern eingestellt haben. Und es ist hässlich ... aber ad hoc kenne ich keinen besseren Weg, es in einer einzigen Abfrage zu tun.

+0

Meine Augen bluten;) – karim79

+0

ich die Namenskonvention nur kopiert ... und abdonned es schnell ...: D –

3

Ich glaube, Sie sind für diese Suche:

WITH counts_hireteam as (
    SELECT HIRETEAM 
     , count(*) count_hireteam 
    from EMPLOYEE 
    group by HIRETEAM 
    order by count(*) desc 
) 
select HIRETEAM 
    from counts_hireteam 
where rownum = 1; 
2

Die „richtige“ Weg, dies zu tun, ist eigentlich so etwas wie:

SELECT m.ceoname, COUNT(1), ROW_NUMBER() OVER (ORDER BY COUNT(1) DESC) 
FROM management m 
JOIN employee e ON m.managementnr = e.hireteam 
GROUP BY m.ceoname 

Sie bekommen in den murkky Bereich der Top- N Fragen und ich werde Sie auf diese excellent column of Ask Tom on Top-N verweisen. Andere Antworten funktionieren in einfachen Fällen, aber wenn Sie beginnen, Dinge wie die Rückkehr der Top-3-Management-Teams (nach Kopfzahl) und tun dies konsequent tun, werden Sie auf Probleme stoßen.

Konsistenz ist ein wichtiger Punkt.Als Tom bemerkt:

ein GROUP BY-Klausel in einer Abfrage Garantie dafür, dass die Ausgangsdaten werden BY-Spalten in Reihenfolge auf der GROUP sortieren, auch wenn es keine ORDER BY-Klausel ist?

Sofern und solange es eine ORDER BY Anweisung für eine Abfrage ist, können die Reihen zurück nicht, um in angenommen werden. Ohne ORDER BY können die Daten in einer beliebigen Reihenfolge in zurückgegeben werden. Die Datenbank fühlt sich an wie und gibt sie zurück. Dies war immer wahr und wird immer wahr sein.

In der Tat, in Oracle Database 10g Release 2 , werden Sie GROUP BY Rückkehr Daten in zufälliger Reihenfolge sehen viele häufiger als früher:

diese Beispieldaten:

INSERT INTO employee VALUES ('Bob',1); 
INSERT INTO employee VALUES ('Sue',1); 
INSERT INTO employee VALUES ('John',1); 
INSERT INTO employee VALUES ('James',2); 
INSERT INTO employee VALUES ('Mary',2); 
INSERT INTO employee VALUES ('Ron', 2); 
INSERT INTO employee VALUES ('Jane',3); 
INSERT INTO employee VALUES ('Luke',4); 
INSERT INTO employee VALUES ('Rob',4); 
INSERT INTO employee VALUES ('Tim', 5); 

INSERT INTO management VALUES (1, 'Kate'); 
INSERT INTO management VALUES (2, 'Larry'); 
INSERT INTO management VALUES (3, 'Jake'); 
INSERT INTO management VALUES (4, 'Sarah'); 
INSERT INTO management VALUES (5, 'Tom'); 
0

Wenn Sie die Ergebnisse auf einem einzelnen Datensatz, auch im Falle von Verbindungen für die größte Zahl der Mitarbeiter einschränken möchten:

select * from (
    select hireteam, count(hireteam) count 
    from employee 
    group by hireteam 
    order by count(hireteam) desc, hireteam asc) 
where rownum = 1 

Um alle hireteam Werte, die die meisten Mitarbeiter mit (einschließlich Verbindungen) abrufen:

select * from (
    select hireteam, 
      count(hireteam) count, 
      rank() over (order by count(hireteam) desc) rank 
    from employee 
    group by hireteam) 
where rank = 1;