【问题标题】:MySQL View: Join tables without causing the data to duplicate on every row?MySQL 视图:连接表而不导致数据在每一行上重复?
【发布时间】:2012-03-28 11:36:09
【问题描述】:

我基本上遇到了和这里完全相同的问题:

SQL View: Join tables without causing the data to duplicate on every row?

除了那个问题,他使用的是 SQL,而我使用的是 mysql。我想知道在 mysql 中是否可以进行相同的查询。如果是这样,我可能有错误的语法?

我正在尝试做类似的事情

select a.name as account_Name, 
   p.description as property_DESCRIPTION, 
   p.address as property_ADDRESS, 
   null as vehicles_DESCRIPTION,
   null as vehicles_MAKE, 
   null as vehicles_MODEL
from Accounts a
    inner join Properties p
        on a.accountid = p.accountid
UNION ALL   
select a.name as account_Name, 
   null as property_DESCRIPTION, 
   null as property_ADDRESS, 
   v.description as vehicles_DESCRIPTION,
   v.make as vehicles_MAKE, 
   v.model as vehicles_MODEL
from Accounts a
    inner join vehicles v
        on a.accountid = v.accountid

这是我的实际代码:

SELECT user.first_name, user.last_name, upi.image_id, NULL AS friends.friend_user_id FROM user 
INNER JOIN user_profile_images as upi ON (user.user_id = upi.user_id) 
UNION 
SELECT user.first_name, user.last_name, NULL AS upi.image_id, friends.friend_user_id FROM user 
INNER JOIN friends ON (user.user_id = friends.user_id) 
WHERE user.user_id = '$profile_id'

我有 3 个表:user、user_profile_images 和 friends。 user_profile_images 和好友都通过 user_id 与用户相关联。因此,用户可以拥有多个个人资料图像以及多个朋友条目。如果没有意义,我可以发布表格图。但我想要的基本上是所有信息的视图,如果它们不适用于整体视图,则字段为 NULL。

如果我使用 2 个表进行查询,或者使用 user 和 user_profile_images,或者使用 user 和 friends,我会得到想要的结果,但是添加第三个表会给我重复的行。

【问题讨论】:

  • SQL 是一种语言,其中 MySQL 是一种特定的实现。没有什么是“只是 SQL”。当您执行union all 时,您会强制 mysql 从联合查询中返回所有行。删除all关键字,mysql为你消除重复行。
  • 另请阅读左/右连接,因为它们有时可能是更好的解决方案。
  • 您的“实际代码”可能会出错,因为每个表中的列数不同 - 第二个 SELECT 有一个 upi.image_id,但第一个没有。
  • 我的错误,我复制了一段错误的代码,再次更新了我仍然无法开始工作的代码......
  • 您的错误消息显然是 PHP 错误消息(“mysqli_num_rows() 需要参数 1 ...”) - 您可以直接从 MySQL 提示符进行查询(这样我们就可以解决 MySQL 问题在讨论 PHP 问题之前),或者至少发布您用于查询数据库的 PHP 代码,包括错误来自的行。此外,在您用于执行查询的行中,您能否执行$con->query('...') or die($con->error)(或mysqli_query(...) or die(mysqli_error(...))),以便我们可以确定错误是在 MySQL 中还是在 PHP 中,以及 究竟是什么 错误是。

标签: mysql join duplicates union


【解决方案1】:

如果我要处理这样的数据,其中两个表通过第三个表的 id 相关联,我会考虑使用外连接。在您引用的问题的 cmets 中,提到了外连接作为一种可能的解决方案。代码如下所示。

select a.name as account_Name, 
p.description as property_DESCRIPTION,
p.address as property_ADDRESS,
v.description as vehicles_DESCRIPTION,
v.make as vehicles_MAKE, 
v.model as vehicles_MODEL
from accounts a
left outer join properties p on p.accountid = a.accountid
left outer join vehicles v on v.accountid = a.accountid;

这是解决方案的测试方式。首先我创建了三个表。

CREATE TABLE `accounts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `properties` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`accountid` int(11) NOT NULL,
`description` varchar(255) COLLATE utf8_bin NOT NULL,
`address` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `vehicles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`accountid` int(11) NOT NULL,
`description` varchar(255) COLLATE utf8_bin NOT NULL,
`make` varchar(100) COLLATE utf8_bin NOT NULL,
`model` varchar(100) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

接下来我将数据插入到每个表中。

INSERT INTO `demo`.`accounts` (
`accountid` ,
`name`
)
VALUES (
NULL , 'techport80.com'
);

INSERT INTO `demo`.`properties` (
`id` ,
`accountid` ,
`description` ,
`address`
)
VALUES (
NULL , '1', 'office', '123 may street');

INSERT INTO `demo`.`vehicles` (
`id` ,
`accountid` ,
`description` ,
`make` ,
`model`
)
VALUES (
NULL , '1', 'motorcycle', 'honda', 'shadow'
);

此时如果我测试解决方案,我将收到一行包含帐户、财产和车辆信息。

INSERT INTO `demo`.`vehicles` (
`id` ,
`accountid` ,
`description` ,
`make` ,
`model`
)
VALUES (
NULL , '1', 'passenger car', 'Ford', 'Mustang'
);

现在,如果我测试我的解决方案,我会看到 2 行,每辆车一个。但是这两行并不完全重复。尽管有些列具有相同的数据。最值得注意的是帐户信息。

INSERT INTO `demo`.`properties` (
`id` ,
`accountid` ,
`description` ,
`address`
)
VALUES (
NULL , '1', 'home', '321 yam street'
);

接下来我添加了第二个地址。现在返回四行。每辆车一个,每个地址一个。但是,没有任何行是重复的。

最后我添加了另一辆车。这是为了造成车辆与财产的失衡。

INSERT INTO `demo`.`vehicles` (
`id` ,
`accountid` ,
`description` ,
`make` ,
`model`
)
VALUES (
NULL , '1', 'Van', 'Chev', 'Cargo'
);

现在我们有 6 行。每辆车一个,每辆车也与两个属性有关。 (所以 2 x 3)

完成了这个练习后,我想知道数据的分层视图是否会成为该数据的更好模型。也许可以使用 XML 或 JSON 来表示数据。对于此任务,您可以使用存储函数,但我个人会首先考虑一种编程语言,如 PHP、C#、C++ 或其他许多语言。

HTH

【讨论】:

  • 谢谢,我按照你说的尝试了左连接,但仍然有重复的行。
【解决方案2】:

正如@MarcB 建议的那样,解决方案是使用UNION 而不是UNION ALL

但是,我有一个问题要问您 - 为什么要使用 UNION?以下是等价的,除了如果(比如说)账户 1 拥有一个财产和一辆车,而不是得到:

account_Name   property_DESCRIPTION   vehicles_MAKE
  account1          property1             NULL
  account1           NULL                vehicle1

你会得到

account_Name   property_DESCRIPTION   vehicles_MAKE
  account1          property1            vehicle1

查询:

SELECT a.name as account_Name, 
   p.description as property_DESCRIPTION, 
   p.address as property_ADDRESS, 
   v.description as vehicles_DESCRIPTION,
   v.make as vehicles_MAKE, 
   v.model as vehicles_MODEL
FROM Accounts a
LEFT JOIN Properties p
        on a.accountid = p.accountid
LEFT JOIN vehicles v
        on a.accountid = v.accountid
WHERE p.description IS NOT NULL AND v.make IS NOT NULL

注意 - 最后一行(p 和 v 都不是 NULL)模拟 INNER JOIN 的“帐户表”部分,并确保仅显示至少具有财产或车辆的帐户。替换pvid 列。

【讨论】:

  • 我对 SQL 不太熟悉,所以不确定其他方法可以做到这一点,只是 UNION 对其他链接上的问题有意义。我尝试从 UNION 中删除 ALL,但查询似乎仍然不起作用。我尝试了你提到的左连接,但我仍然得到重复的行。我已经更新了我的问题,以便更清楚地了解正在发生的事情。
  • “似乎仍然不起作用”是什么意思 - 你得到重复,或者你得到一个错误(以及什么错误)?重新尝试左连接并获取重复的行 - 你的意思是有些行的每一列都是相同的吗?它们在您没有 SELECTed 的某些领域有什么不同吗? (我可以让症状消失,但可能有一些不干净的东西,所以我想弄清楚是什么)。你能举一个“重复行”的例子吗?干杯。
  • 不起作用我的意思是我得到一个错误:mysqli_num_rows() 期望参数 1 是 mysqli_result,给定的布尔值。这让我觉得语法在某种程度上是错误的。对不起,我不擅长电子
  • 不起作用我的意思是我得到一个错误:mysqli_num_rows() 期望参数 1 是 mysqli_result,给定的布尔值。这让我觉得语法在某种程度上是错误的。对不起,我不擅长解释,而不是完全重复。例如:会有多行,user 和 user_image_profile 列中的数据相同,但friends 列中的数据不同。所以我想要的是表中每个唯一的数据行都有自己的行,其他表的列为空。我认为这可能效率低下,而且我的做法是错误的......?
  • 这样做,我意识到该表将乘以 user_profile_images 中的行数 x 朋友列中的行数。因此,如果用户有 4 个朋友和 7 张图像,它将返回 28 行,如果他们添加另一个图像,则返回 8、32 行。这似乎不是进行此查询的最有效方法...对朋友和 user_profile_images 表进行 2 个单独的查询是要走的路吗?抱歉换个话题,但我不想浪费你太多时间!只是想找出最有效的做事方式。
猜你喜欢
  • 2011-06-29
  • 1970-01-01
  • 2021-04-04
  • 2017-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
相关资源
最近更新 更多