1

次のような MySql テーブルがあります。

ID  Category    Value
A   LOCATION    COPENHAGEN
A   LOCATION    MADRID
B   LOCATION    MADRID
C   LOCATION    MADRID
C   LOCATION    AARHUS
C   POSITION    WEBDESIGN
D   POSITION    SYSADMIN
D   POSITION    WEBDESIGN
A   GENDER      MALE
B   GENDER      MALE
C   GENDER      FEMALE

Id、Category、および Values が一緒になってキーを形成します。これらは動的 (ユーザー定義) であり、テーブルが大きくなることに注意してください。

ID今、いくつかの基準に一致するものをすべて取得したいと考えています。が返されるには、 がID各 内の 1 つの値と一致するだけで十分ですCategory

例えば:

持っているすべてのIDを教えてください

((場所 = コペンハーゲン OR 場所 = マドリード) AND (性別 = 男性))

A、Bを返す必要があります

もう一つの例:

持っているすべてのIDを教えてください

((POSITION = SYSADMIN OR POSITION = WEBDESIGN) AND (GENDER = FEMALE) AND (LOCATION = COPENHAGEN OR LOCATION = MADRID)) 

Cを返す必要があります

返された ID は、別のクエリのサブクエリとして使用されるため、パフォーマンスが重要になります。

アップデート

サンプルデータと提案された機能しないソリューションを使用して、このSQLフィドルを作成しました。

4

2 に答える 2

2

[機能していなかったため、初期応答を削除しました。それを機能させるために、私は2番目の編集でクエリを思いつきました。これは非常に望ましいです。]


編集

さまざまな場所で働いている人々を追跡するためのスキーマを作成しようとしているようです。データから、彼らはさまざまなオフィス間で複数の役職を保持している可能性があります。以下のスキーマでは、各人、仕事、場所を1回だけ定義してから、リンクテーブルを使用してそれらを接続できます。

TABLE People
  p_id INT AI PK
  p_name VARCHAR
  p_sex BOOL
  ...

TABLE Offices
  o_ID INT AI PK
  o_name VARCHAR
  o_location VARCHAR
  ...

TABLE Jobs
  j_ID INT AI PK
  j_name VARCHAR
  ...

TABLE People_Jobs_Offices  --linking table
  p_ID INT PK
  o_ID INT PK
  j_ID INT PK

マドリッドまたはコペンハーゲンのすべてのシステム管理者を取得します。

SELECT *
FROM People_Jobs_Offices pjo
  INNER JOIN People p
    ON pjo.p_id = p.p_id 
  INNER JOIN Jobs j
    on pjo.j_id = j.j_id
  INNER JOIN Offices o
    ON pjo.o_id = o.o_id
WHERE
  j.j_name = 'SYSADMIN'
  AND ( o.o_location = 'MADRID'
    OR o.o_location = 'COPENHAGEN' )

このアプローチはデータベースの正規化と呼ばれ、通常、RDBMSのインデックスを最大限に活用し、データの重複を回避することでテーブルの行数を最小限に抑えます。


編集²

私はあなたのSQLfiddleをいじり直しました。これの多くは、ポルグラマティックに実行する必要があります。どのカテゴリ/結合の数/テーブルエイリアス/列名を決定しますが、ID列が参照するテーブルから始めて、これらの結合の確実な開始点を確保したいのでusers、説明のためにテーブルを作成しました。

CREATE TABLE users (`ID` varchar(16),`name` varchar(16));
INSERT INTO users (`ID`, `name`)
VALUES ('A', 'andrew'), ('B', 'bob'), ('C', 'charla');

そしてクエリ:

SELECT u.*,
  gen.value 'gender',
  pos.value 'position',
  loc.value 'location'
FROM users u
  LEFT JOIN yourtable gen
    ON u.ID = gen.ID
      AND gen.category = 'GENDER'
  LEFT JOIN yourtable pos
    ON u.id = pos.id
      AND pos.category = 'POSITION'
  LEFT JOIN yourtable loc
    ON u.id = loc.id
      AND loc.category = 'LOCATION'

そして出力:

ID  NAME    GENDER  POSITION    LOCATION
A   andrew  MALE    (null)      COPENHAGEN
A   andrew  MALE    (null)      MADRID
B   bob     MALE    WEBDESIGN   MADRID
B   bob     MALE    SYSADMIN    MADRID
C   charla  FEMALE  (null)      MADRID
C   charla  FEMALE  (null)      AARHUS

また、多くの結合が発生する可能性があるため、テーブルの3つの列すべてではないにcategoryしても、にインデックスがあることを確認します。ID

于 2012-11-08T16:37:23.427 に答える
1

解決策は、現時点では、カテゴリごとにサブクエリを作成することです。このような:

SELECT DISTINCT ID
FROM yourtable
WHERE ID IN 
(SELECT ID from yourtable WHERE (Category = 'POSITION' AND Value = 'SYSADMIN'))
AND ID IN 
(SELECT ID from yourtable WHERE (Category = 'LOCATION' AND Value = 'MADRID') OR (Category = 'LOCATION' AND Value = 'COPENHAGEN'))

実用的な例は、 SQLFiddleで見ることができます。

動作していますが、行数が多い場合やカテゴリをチェックしている場合のパフォーマンスが気になります。

于 2012-11-08T23:15:43.210 に答える