sql >> データベース >  >> RDS >> Mysql

他の行に基づいて結果セットを返す方法

    2つの異なる解決策があります:(注:列挙型フィールドを「package_type」と呼びました)

    最初の解決策(IF()関数を使用):

    select 
      i.location, 
      if(ps.id is not null, ps.id, pg.id) as package_id
    from 
      (select distinct location from Items) i
      inner join 
        (select i.location, p.id
         from Items i
           inner join Packages p on (i.package_id = p.id and p.package_type = 'general')
        ) pg on (i.location = pg.location)
      left join 
        (select i.location, p.id
         from Items i
           inner join Packages p on (i.package_id = p.id and p.package_type = 'special')
        ) ps on (i.location = ps.location)
    

    このソリューションは、基本的に場所を取得し、それを一般的なパッケージに結合します(これは存在すると想定されているため、内部結合 )および特別なパッケージ(これはオプションです。したがって、 left join )。次のようなレコードを作成します:

    location | general-package | [special-package]
    

    次に、MySQL IFを使用します 最初に特別なパッケージのIDを選択しようとし、次に一般的なパッケージのIDにフォールバックする関数。

    2番目の解決策(列挙型から整数へのキャストによる):

    select i.location, p.id
    from
      (select i.location, max(cast(package_type as unsigned)) as package_type
       from Items i
         left join Packages p on (i.package_id = p.id)
       group by location
      ) i
      inner join 
        (select i.location, p.id, p.package_type
         from Items i
           inner join Packages p on (i.package_id = p.id)
        ) p on (i.location = p.location and i.package_type = p.package_type)
    

    このソリューションは、列挙型が整数として格納されるという事実を利用しています。列挙型を整数にキャストします。 特別 この場合、 2が返されます およびgeneral 1を返します 。この場合、これらのスペシャルは一般よりも高いことが保証されているため(つまり、2> 1)、 MAXを使用できます。 集計関数。これで、基本的に場所とその「推奨パッケージ」の表ができました(つまり、存在する場合は特別、そうでない場合は一般)。これを通常のクエリと予想されるパッケージタイプに結合するだけで、正しい結果が返されます。

    免責事項:これらの方法のいずれかの効率についてはよくわかりません。そのため、これを自分でテストすることをお勧めします。

    テーブルを再設計するか、効率を上げるために非正規化することを検討している場合は、この設計の方が適していると思います。

    GeneralPackages table
    id, name
    1, General Package 1
    
    SpecialPackages table
    id, name
    1, Special Package 1
    2, Special Package 2
    
    Items table
    id, general_package_id, special_package_id, location
    1, 1, NULL, America
    2, 1, 2, Europe
    

    利点は、データベースレベルでいくつかのルールを適用するのが簡単になることです。

    • 場所には常に一般パッケージが必要です(Items.general_package_idはNOT NULLとして定義できます)
    • 場所には、一般的なパッケージが1つだけ含まれている必要があります(結合ではなくフィールドに追加すると、指定されたパッケージが1つだけになることが保証されます)
    • 場所には、最大で1つの特別なパッケージを含めることができます(結合ではなくフィールドに追加すると、指定されたパッケージが1つだけになることが保証されます)
    • Items.general_package_id =GeneralPackages.idの外部キーは、その列に「一般」である有効なパッケージのみが含まれることを保証します。
    • special_package_idについても同じことができます。

    欠点は、古いクエリの1つを使用するたびに、おそらくUNIONALLを使用する必要があることです。




    1. 1人の人が複数のアカウントを作成するのを防ぐ最良の方法

    2. クエリの列値として特定の数値を選択する

    3. データベースの精度を向上させる方法

    4. Access2016でオブジェクトの依存関係を表示する方法