it-swarm.com.de

Wie verwende ich MAX () für ein Ergebnis einer Unterabfrage?

Ich bin neu in Oracle und der SQL-Welt. Ich habe ein kleines Problem mit einer Frage, die ich für mein Leben nicht herausfinden kann. Ich habe ein paar Stunden damit verbracht, verschiedene Ansätze auszuprobieren, und ich kann nicht das erwartete Ergebnis erzielen. Also heres meine Frage:

SELECT *
from(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,      
    count(membership_history.MEM_TYPE) as membership_count
    from membership_history
    JOIN membership ON membership.mem_type = membership_history.mem_type
    group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
    ) g
WHERE g.membership_count = (select MAX(membership_count) from g); 

Die innere Abfrage funktioniert also einwandfrei und liefert zwei Ergebnisse. Nun, da ich diese beiden Werte habe, versuche ich herauszufinden, wie ich die Zeile mit dem maximalen Wert von member_count zurückgeben kann, in dem ich immer festgefahren bin. In der obigen Abfrage habe ich versucht, MAX () in der where-Klausel zu verwenden, aber innerhalb dieser Option wird der Fehler "Tabelle nicht gefunden" (Bedeutung "g") angezeigt. Meine Frage ist also, wie verwende ich die MAX () - Funktion für die Ergebnisse meiner Unterabfrage? Alle Gedanken oder Vorschläge wären sehr dankbar !!!!!

10
user1916441

Sie benötigen keine Unterabfrage, die den maximalen Wert ermittelt.
Stattdessen, ; Sie brauchen nur die erste Reihe, nachdem Sie bestellt haben die Reihen:

select * from (
  select 
    membership.mem_desc,
    membership.mem_max_rentals,
    membership_history.mem_type,      
    count(membership_history.MEM_TYPE) as membership_count
  from membership_history
  JOIN membership ON membership.mem_type = membership_history.mem_type
  group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
  ORDER BY 4 DESC  -- Added this line
) g
WHERE ROWNUM = 1. -- Added this line
12
Bohemian

Das ist alles gute SQL. 

Der beste Weg, um einen Spaltenwert mit dem maximalen Primärschlüsselspaltenwert zu finden, ist: 

SELECT .... from tablename
WHERE ... AND
  (SELECT max(primary key name) FROM tablename WHERE .... ) = primary_key_name

dieses Beispiel gibt einen Skalarwert zurück.

3
user3552157

Ich hatte ein ähnliches Problem in einer Access-Abfrage ... Sind wir aufgrund einiger Kommentare in diesem Thread zu verstehen, dass die ACCESS MAX-Funktion nur in/mit Primärschlüsselfeldern verwendet werden sollte? ... im Grunde habe ich eine Tabelle, in der Adressen definiert werden, die sich auf eine Entität beziehen, ABER mit einer leichten Drehung; 1) Nach dem Speichern darf kein Datensatz gelöscht oder geändert werden (was bedeutet, dass eine Entität mehrere Adressdatensätze haben kann); 2) jede aktuelle Entitätsadresse kann entweder eine Adresse haben; HOME (1 Record) oder HOME und MAIL (2 Records) ... Jeder Adressdatensatz hat eine (ID) (Autonummer Primärschlüssel) und eine HOME ID (HID), die mit dem HOME-Datensatz (ID) übereinstimmt (HID ist KEIN Primärschlüssel und ist NICHT eindeutig) und eine Entitäts-ID (EID) ... also ... wenn ich versuche, eine Unterabfrage zu verwenden, um den maximalen Wert (HID) für eine bestimmte Entität abzurufen, möchte ich nur die aktuelle Adresse zurückgeben ... Bei der Verwendung von MAX in einer Unterabfrage habe ich festgestellt, dass die Ausführung entweder fehlschlägt, weil ACCESS fälschlicherweise der Ansicht ist, dass zu viele übereinstimmende Datensätze für die Unterabfrage vorhanden sind. 

Die einzige Möglichkeit, dieses Problem zu umgehen, bestand darin, die Max-Unterabfrage durch eine Max-Funktion zu ersetzen, die den MAX-HID-Wert für eine Entität zurückgibt (die Funktion verwendet die Unterabfrageanweisung mit DAO-Logik in VBA).

Hier ist die HOME-Unterabfrage, die Teil der Hauptabfrage ist (die Hauptabfrage muss eine Zeile pro Entität als EID, Home.Address, Mail.Address zurückgeben) 

Select *
From tbAddresses As tba1
Where tba1.aType = "Home"
  And tba1.HID = (Select MAX(tba2.HID) 
                      From tbAddresses As tba2 
                     Where tba1.EID = tba2.EID)

Die Hauptabfrage funktioniert nur ordnungsgemäß, wenn die Where-Klauseln Home und Mail (nicht dargestellt) durch die unten stehende Funktion ersetzt werden. Wenn die MAX-Unterabfrage wie oben enthalten ist, funktioniert sie nicht. 

Wenn also für die MAX-Funktion ein PRIMARY KEY-Feld erforderlich ist, kann dies möglicherweise erklären, warum meine Abfragen fehlschlagen, obwohl dies nach einer wesentlichen Einschränkung klingt.

Where tba1.HID = fnGetMaxHID(tba1.EID) 

Hier sind einige Testdaten, die nur 3 Zeilen liefern sollen

ID    HID    EID   aType  Address
 1      1    100   Home   Blah 1
 2      2    101   Home   Blah 2
 3      2    101   Mail   PO Box Blah 0
 4      4    102   Home   Blah 3
 5      5    101   Home   Blah 4

Eine letzte Anmerkung, mehrere Versionen von Access Pro; 2002, 2003, 2016 wurden getestet und liefern alle die gleichen Ergebnisse. Also ist dieses Problem entweder eine inhärente Eigenheit der Max-Funktion oder eine Art von Fehler, der möglicherweise ignoriert wurde oder unbemerkt blieb? ... die Funktion funktioniert für mich als Workaround, kann aber für andere nicht funktionieren, wäre also nett, wenn die MAX-Funktion geklärt wäre.

1
bxdobs

Sie könnten so etwas versuchen

 SELECT membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type, membership_count, rank() over ORDER BY membership_count DESC as ranky
from
(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,      
count(membership_history.MEM_TYPE) as membership_count
from membership_history
JOIN membership ON membership.mem_type = membership_history.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
) 
WHERE ranky =1;
0
Scotch

Sie können eine abgeleitete Tabelle nicht direkt in der where-Klausel verwenden, in der sie table or view does not exist errorso gibt, um den maximalen Zählwert abzurufen, den Sie HAVING-Klausel oder Analytical Functions oder Rownum-like verwenden können

select * from
      (Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,      
      count(membership_history.MEM_TYPE) as membership_count
      from membership_history a
      JOIN membership b ON b.mem_type = a.mem_type
      group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
      having count(a.MEM_TYPE) = (Select      
      MAX(count(a.MEM_TYPE)) from membership_history a
      JOIN membership b ON b.mem_type = a.mem_type
      group by (a.mem_type,b.mem_desc,b.mem_max_rentals)));

(ODER)

select * from
(SELECT g.*,rank() over (order by membership_count desc) rnk from
      (Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,      
      count(membership_history.MEM_TYPE) as membership_count
      from membership_history
      JOIN membership ON membership.mem_type = membership_history.mem_type
      group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)) g)
WHERE rnk=1;

(ODER)

select * from
(SELECT g.*,rownum rn from
      (Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,      
      count(membership_history.MEM_TYPE) as membership_count
      from membership_history
      JOIN membership ON membership.mem_type = membership_history.mem_type
      group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
      order by membership_count desc) g)
WHERE rn=1;
0
Aspirant

Ich denke, die sauberste Lösung ist die Verwendung der ALL-Vergleichsbedingung. Es wird verwendet, um einen Wert mit einer Liste oder Unterabfrage zu vergleichen.

SELECT 
  m.mem_desc,
  m.mem_max_rentals,
  mh.mem_type,      
  COUNT(mh.mem_type) as membership_count
FROM membership_history mh
JOIN membership m ON m.mem_type = mh.mem_type
GROUP BY mh.mem_type,m.mem_desc,m.mem_max_rentals
HAVING membership_count >= ALL (
  SELECT count(*)
  FROM membership_history
  GROUP BY mem_type
)   
0
max68