web-dev-qa-db-ja.com

PHP&MYSQL:JOIN操作であいまいな列名を解決するには?

データベースに2つのテーブルがあります。

NEWS( 'id'-ニュースID、 'user'-作成者のユーザーID)

USERS( 'id'-ユーザーID)

_SELECT * FROM news JOIN users ON news.user = user.id_を作成したいのですが、PHPのような結果になりました:

$row = mysql_fetch_array($result)、および_$row['column-name']_で列名を取得...同じ列名を持つニュースIDとユーザーIDを取得するにはどうすればよいですか?

更新:素早い回答をありがとう。エイリアスが最善の解決策のようです。

71
Dan Burzo

選択している列のエイリアスを設定できます。

$query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id'
115
CMS

数値インデックス($row[0])以上の場合、MySQLでASを使用します。

SELECT *, user.id AS user_id FROM ...

40
Greg

私はこれを理解しました。これはおそらく悪い習慣ですが、この場合はうまくいきました。

私は、テーブルプレフィックスを使用してすべての列名をエイリアスしたり、書き出したりしたくない怠け者の1人です。

Selectステートメントでtable_name.*を使用して、特定のテーブルからすべての列を選択できます。

列名が重複している場合、mysqlは最初から最後まで上書きします。最初に複製された列名のデータは、その列名が再び検出されると上書きされます。したがって、最後に来る重複した列名が優先されます。

それぞれが重複した列名を含む3つのテーブルを結合する場合、selectステートメント内のテーブルの順序によって、重複する列に対して取得するデータが決まります。

例:

SELECT table1.* , table2.* , table3.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup;

上記の例では、dupの値はtable3から取得されます。

duptable1の値にしたい場合はどうなりますか?

次に、これを行う必要があります:

SELECT table3.* , table2.* , table1.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup;

これで、table1が最後に来るため、dupの値はtable1の値になります。

dupに必要な値を取得しましたが、おかしな列を1つずつ書き出す必要はなく、すべての列を使用できます。わーい!

dupの値は3つのテーブルすべてで同じである必要がありますが、table3dupに一致する値がない場合はどうなりますか?その場合、最初の例ではdupが空白になり、それは残念です。

21
Eab

別のヒント:よりきれいなPHPコードが必要な場合は、データベースにVIEWを作成できます。

例えば:

CREATE VIEW view_news AS
SELECT
  news.id news_id,
  user.id user_id,
  user.name user_name,
  [ OTHER FIELDS ]
FROM news, users
WHERE news.user_id = user.id;

PHPの場合:

$sql = "SELECT * FROM view_news";
9
Dirk

@ジェイソン。 phpがmysqlではなく犯人であることを除いて、あなたは正しいです。 JOINをMysql Workbenchに配置すると、まったく同じ名前(テーブルごとに1つ)で3つの列が得られますが、同じデータではありません(テーブルにない場合はnullになります) JOIN)に一致します。

Phpでは、mysql_fetch_array()で_MYSQL_NUM_を使用すると、すべての列が取得されます。問題は、mysql_fetch_array()を_MYSQL_ASSOC_とともに使用する場合です。次に、その関数内で、phpは次のように戻り値を構築します。

_$row['dup'] = [value from table1]
_

以降.

_$row['dup'] = [value from table2]
_

...

_$row['dup'] = [value from table3]
_

したがって、table3から値のみを取得します。問題は、mysqlの結果セットに同じ名前の列を含めることができるが、phpの連想配列では配列内の重複キーが許可されないことです。データがPHPで連想配列に保存されると、一部の情報が静かに失われます...

8
GoTo

次のようなことができます

SELECT news.id as news_id, user.id as user_id ....

その後 $row['news_id']はニュースIDであり、$row['user_id']はユーザーIDになります

8

動的テーブルでも同じ問題が発生しました。 (結合できるようにidを持っていると想定されているが、残りのフィールドについては想定されていないテーブル。)この場合、エイリアスを事前に知りません。

そのような場合、最初にすべての動的テーブルのテーブル列名を取得できます。

$tblFields = array_keys($zendDbInstance->describeTable($tableName));

ここで、$ zendDbInstanceはZend_Dbのインスタンスです。または、Zendに依存しないために、ここで関数のいずれかを使用できます php pdo:テーブルの列名を取得

次に、すべての動的テーブルでエイリアスを取得し、エイリアスを必要としないものに$ tableName。*を使用できます。

$aliases = "";
foreach($tblKeys as $field)
    $aliases .= $tableName . '.' . $field . ' AS ' . $tableName . '_' . $field . ',' ;
$aliases = trim(',', $aliases);

このプロセス全体を1つの汎用関数にまとめて、よりクリーンなコードにするか、必要に応じてより遅延させることができます:)

2
haknick

エイリアスを作成したくない場合は、テーブル名にプレフィックスを付けることもできます。

これにより、クエリの生成をより自動化できます。また、select *を使用しないことをお勧めします(フィールドを選択するよりも明らかに遅いですneedさらに、必要なフィールドに明示的に名前を付けるだけです。

SELECT
    news.id, news.title, news.author, news.posted, 
    users.id, users.name, users.registered 
FROM 
    news 
LEFT JOIN 
    users 
ON 
    news.user = user.id
1
SchizoDuckie