web-dev-qa-db-ja.com

サブクエリ結果でMAX()を使用する方法は?

私はOracleとSQLの世界に慣れていません。クエリにわずかな問題があり、自分の人生を把握できず、数時間かけてさまざまなアプローチを試してみましたが、期待した結果が得られません。私のクエリはここにあります:

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); 

したがって、内部クエリは完全に機能し、2つの結果を返します。これら2つの値が得られたので、membership_countの最大値を持つ行を返す方法を見つけようとしています。上記のクエリでは、where句でMAX()を使用しようとしましたが、その選択内でエラー「テーブルが見つかりません」(「g」を意味する)を取得し続けます。だから私の質問は、サブクエリの結果でMAX()関数をどのように使用するのですか?どんな考えや提案も大歓迎です!!!!!

14
user1916441

最大値を見つけるサブクエリは必要ありません。
代わりに、; orderedの行があった後にfirstの行だけが必要です:

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

これはすべて良いSQLです。

最大主キー列値を使用して列値を見つける最良の方法は次のとおりです。

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

この例はスカラー値を返します。

4
user3552157

このクエリのコメントのいくつかに基づいて、アクセスクエリ内で同様の問題が発生しましたが、ACCESS MAX関数は主キーフィールドでのみ使用する必要があることを理解する必要がありますか? ...基本的に、エンティティに関連するアドレスを定義するテーブルがありますが、少しねじれています。 1)一度保存すると、レコードの削除または変更は許可されません(エンティティに複数のアドレスレコードが存在する可能性があることを意味します)、2)現在のエンティティアドレスはいずれかを持つことができます。 HOME(1レコード)またはHOMEおよびMAIL(2レコード)...各Addressレコードには、HOMEレコードの(ID)と一致する(ID)(autonumber Primary KEY)a HOME ID(HID)があります(HIDはPrimary KEYではなく、一意ではありません)およびエンティティID(EID)...だから...サブクエリを使用して特定のエンティティのmax(HID)値を取得しようとすると、現在のアドレスのみが返されます...サブクエリでMAXを使用して見つけたのは、ACCESSがサブクエリに一致するレコードが多すぎると誤って考えているために実行に失敗していることです...または...返すべきではない行を誤って返します.

この問題を回避するために私が見つけた唯一の方法は、エンティティのMAX HID値を返すMax関数でmaxサブクエリを置き換えることでした(関数はVBA内のDAOロジックでサブクエリステートメントを使用します)

メインクエリの一部であるHOMEサブクエリは次のとおりです(メインクエリは、エンティティごとに1行を返す必要があります; EID、Home.Address、Mail.Address)

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)

メインクエリは、HomeとMailの両方のWhere句(図示せず)が以下の関数に置き換えられた場合にのみ適切に機能します。上記のようにMAXサブクエリが含まれている場合、機能しません。

したがって、MAX関数が機能するためにPRIMARY KEYフィールドが必要な場合、これはクエリが失敗する理由を説明するかもしれませんが、それは大きな制限のように聞こえます。

Where tba1.HID = fnGetMaxHID(tba1.EID) 

以下は3行のみを返すテストデータです。

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

最後に、Access Proのいくつかのバージョンがあります。 2002、2003、2016がテストされ、すべて同じ結果が得られました。したがって、この問題はmax関数の固有の癖か、おそらく無視されているか気付かれていない何らかのバグですか? ...この関数は回避策として機能しますが、他の人には機能しない可能性があるため、MAX関数が明確になった場合は素晴らしいでしょう。

1
bxdobs

派生テーブルをwhere句で直接使用することはできないため、table or view does not existエラーが発生するため、HAVING句またはAnalytical FunctionsまたはRownumのような最大カウント値を取得できます。

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)));

(または)

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;

(または)

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

最もきれいな解決策は、ALL比較条件を使用することだと思います。値をリストまたはサブクエリと比較するために使用されます。

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