【发布时间】:2015-02-21 02:57:54
【问题描述】:
为入站呼叫创建一个数据库,其中包含每种呼叫类型的数据。我已经定义了一个带有“records”表、“sales”表和“accounts_receivable”表的数据库。 “sales”和“accounts_receivable”表本质上是“records”表的子集。意思是,对于“sales”和“accounts_receivable”表的每一行(唯一),“records”表中都有相应的行。
我的“记录”表有值:
id (BIGINT)
timestamp (TIMESTAMP)
rep_id (INT)
notes (VARCHAR)
我的“销售”表有值:
local_record_id (BIGINT)
record_id (BIGINT)
amount (VARCHAR)
bottles_sold (VARCHAR)
record_type (VARCHAR) default 'sales'
我的“accounts_receivable”表有值:
local_record_id (BIGINT)
record_id (BIGINT)
amount (VARCHAR)
bottles_sold (VARCHAR)
record_type (VARCHAR) default 'ar'
我正在尝试提取整个数据库中的所有记录以及每条记录的适用数据。为此,我认为以“记录”表开头的 LEFT JOIN 可以正常工作,但由于某种原因它不是。这是我的查询:
SELECT *
FROM $table_name_records
LEFT JOIN $table_name_sales ON ($table_name_records.id = $table_name_sales.record_id)
LEFT JOIN $table_name_ar ON ($table_name_records.id = $table_name_ar.record_id)
这将返回一组结果,其中列名相似的子表中的数据被清空。
输出示例(对应于我的数据库的“销售”表中的一行/条目):
Array (
[id] => 1
[timestamp] => 2014-12-17 13:11:07
[rep_id] => 37
[notes] => Some notes for you.
[local_record_id] =>
[record_id] =>
[amount] =>
[bottles_sold] =>
[record_type] =>
)
我已验证我的数据库的每个子表的每个列中都有数据,所以我不明白为什么这些值返回为空白。如果我只使用一个左连接查询:
SELECT *
FROM $table_name_records
LEFT JOIN $table_name_sales ON ($table_name_records.id = $table_name_sales.record_id)
我得到了我期望看到的:
Array (
[id] => 1
[timestamp] => 2014-12-17 13:11:07
[rep_id] => 37
[notes] => Some notes for you.
[local_record_id] => 14
[record_id] => 1
[amount] => 45.45
[bottles_sold] => Multiple
[record_type] => sales
)
如果我只加入“应收帐款”表,工作方式与我预期的相同:
SELECT *
FROM $table_name_records
LEFT JOIN $table_name_ar ON ($table_name_records.id = $table_name_ar.record_id)
Array (
[id] => 1
[timestamp] => 2014-12-17 13:12:16
[rep_id] => 37
[notes] => Some notes.
[local_record_id] => 6
[record_id] => 2
[amount] => 50.89
[bottles_sold] => Single
[record_type] => ar
)
我查看了很棒的图形 SQL 连接文档 MySQL Joins,那里的 LEFT JOIN 看起来正是我想要的:表 A(记录)中的每一件事与表 B(销售)中的数据,然后也是第二个表 B (accounts_receivable) 附加到相应的行(根据 ON 语句)。
我做错了什么,这没有像我期望的那样响应?
我只需要“销售”记录的查询通常是在另一个方向构建的。因此:
SELECT *
FROM $table_name_sales
LEFT JOIN $table_name_records ON ($table_name_records.id = $table_name_sales.record_id)
所以,我尝试从那个方向构建我的查询,然后通过以下方式加入它们:
SELECT *
FROM $table_name_sales
LEFT JOIN $table_name_records ON ($table_name_records.id = $table_name_sales.record_id)
UNION
SELECT *
FROM $table_name_ar
LEFT JOIN $table_name_records ON ($table_name_records.id = $table_name_ar.record_id)
这个查询完全符合我的预期:
Array (
[id] => 1
[timestamp] => 2014-12-17 13:11:07
[rep_id] => 37
[notes] => Some notes for you.
[local_record_id] => 14
[record_id] => 1
[amount] => 45.45
[bottles_sold] => Multiple
[record_type] => sales
)
但在我看来,当我有大量记录和更多表时(对应于不同类型的入站呼叫——例如:信息请求、订单问题等),以这种方式构建查询可能会变得昂贵)。不过,我对 MySQL 没有太多经验。
【问题讨论】:
-
在
JOIN查询(实际上是任何生产代码)中不建议使用SELECT *。正如您所发现的,类似命名的列将无法正确返回。您必须指定每个(实际上,只指定您需要的列)并为类似名称的列提供别名:SELECT $table_name_records.id AS records_id, $table_name_records.notes AS records_notes, $table_accounts_receivable.bottles_sold AS ar_bottles_sold, $table_sales.bottles_sold AS sales_bottles_sold... -
执行
UNION会产生与JOIN截然不同的查询和结果集。 JOIN 似乎是您在这里真正需要的。 -
@MichaelB:所以,我尝试按照您的建议进行操作,并且得到了相同的结果。只有这一次我注意到最终查询结果中的所有“ar”记录看起来都很好。我加了:$table_name_records.id AS id, $table_name_records.timestamp AS timestamp, $table_name_records.rep_id AS rep_id, $table_name_records.notes AS notes, $table_name_sales.amount AS amount, $table_name_sales.bottles_sold AS bottle_sold, $table_name_sales.record_type AS record_type, $table_name_ar.amount AS amount, $table_name_ar.bottles_sold AS bottle_sold, $table_name_ar.record_type AS record_type 到查询。
-
它们都必须是不同的别名。您同时拥有
$table_name_sales.bottles_sold AS bottles_sold和$table_name_ar.bottles_sold AS bottles_sold。使用原始表的前缀区分$table_name_sales.bottles_sold AS sales_bottles_sold和$table_name_ar.bottles_sold AS ar_bottles_sold等别名,因此它们都不是bottles_sold。对 all 类似命名的列执行此操作。 -
如果您需要不同地使用sales和accounts_receivable,您应该分别查询它们。与它们进行 JOIN 会使事情变得混乱,除非这些行真正相互关联,而不是仅仅与
records独立相关