如何在不丢失行的情况下连接 3 个表?
How to join 3 tables without losing rows?
我正在尝试编写一个查询,该查询连接三个 table,按 id 列分组,并查找列的最大值。但是,如果给定行没有值,则会从结果集中删除整个 table 行。
我有一个拍卖网站,有不同的物品。我将 price
显示为 max(bid)
并显示在名为 active bids 的页面上的项目旁边。我的问题是,如果某个项目没有出价,那么该项目在收到第一次出价之前不会出现在页面上。
我还有一列 min_price
因此,如果出价列中没有添加任何值,我仍然会显示最低价格。
是否可以将 max(bid)
显示为空白,但仍然显示该项目?简而言之,我问的是如何显示 table 行,即使其中一列没有插入值(该列接受了 null
,但仍然没有结果)。
这是我的查询:
SELECT COALESCE(max(bid.amount) , 0) AS amount, item.img, item.expirydate, item.iditem, item.description, item.min_price, seller.name
FROM item,seller,bid
WHERE seller.idseller=item.idseller
AND idcategory=1
and
bid.iditem=item.iditem
AND item.expirydate> curdate()
group by iditem;"
;
PHP:
<?php $datasett = $tilkobling->query($sql);
<?php while ($rad=mysqli_fetch_array($datasett)) { ?>
<tr>
<div class="artikkelbilde" id="tabell">
<td>
<img class="artikkelbilde" src="../images/<?php echo $rad ["img"];?>">
</td>
</td>
</div>
<td>
<?php echo $rad["iditem"]; ?>
</td>
<td>
<?php echo $rad["description"]; ?>
</td>
<td>
<?php echo $rad["min_price"]; ?>
</td>
<td>
<?= $rad["name"]; ?>
</td>
<td>
<?php echo $rad["expirydate"]; ?>
</td>
<td>
<?php echo $rad["amount"]; ?>
</td>
<td>
<a href="Gibud.php"> Gi bud </a>
</td>
<?php } ?>`
这里是三个相关table的SQL,信息量绝对最少,但原理应该是一样的。当项目没有出价时,我正在努力让 sql 检索项目:
CREATE TABLE `bid` (
`idbid` INT NOT NULL AUTO_INCREMENT,
`amount` INT NOT NULL,
`idbuyer` INT NULL,
`iditem` INT NULL,
PRIMARY KEY (`idbid`)
);
CREATE TABLE `item` (
`iditem` INT NOT NULL AUTO_INCREMENT,
`min_price` INT NULL,
`description` VARCHAR(45) NULL,
`idseller` INT NULL,
`idcategory` INT NULL,
PRIMARY KEY (`iditem`)
);
CREATE TABLE `seller` (
`idseller` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL,
PRIMARY KEY (`idseller`)
);
ALTER TABLE `bid`
ADD INDEX `FK_item_idx` (`iditem` ASC);
ALTER TABLE `bid`
ADD CONSTRAINT `FK_item`
FOREIGN KEY (`iditem`)
REFERENCES `item` (`iditem`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
ALTER TABLE `item`
ADD INDEX `FK_seller_idx` (`idseller` ASC);
ALTER TABLE `item`
ADD CONSTRAINT `FK_seller`
FOREIGN KEY (`idseller`)
REFERENCES `seller` (`idseller`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
INSERT INTO `item` (`min_price`, `description`) VALUES ('200', 'coffeetable');
INSERT INTO `item` (`min_price`, `description`) VALUES ('400', 'lamp');
INSERT INTO `item` (`min_price`, `description`) VALUES ('600', 'painting');
INSERT INTO `bid` (`amount`, `iditem`) VALUES ('800', '1');
INSERT INTO `bid` (`amount`,`iditem`) VALUES ('1000','2');
INSERT INTO `seller` (`name`) VALUES ('Bob');
INSERT INTO `seller` (`name`) VALUES ('Rob');
INSERT INTO `seller` (`name`) VALUES ('Tob');
UPDATE `item` SET `idseller`='1' WHERE `iditem`='1';
UPDATE `item` SET `idseller`='1' WHERE `iditem`='2';
UPDATE `item` SET `idseller`='2' WHERE `iditem`='3';
您在 mysql 中使用过 COALESCE 吗??
我想你的查询中应该有这样的内容
SELECT COALESCE(max(bid) , 0) AS max_bid FROM tables1
COALESCE return 列表中的第一个非空表达式
您需要在查询中编写正确的 JOINS,而不是依赖 FROM [ table1, table2 ] 语句,因为它只使用常规 JOIN。
您可能想要这样的东西:
SELECT
COALESCE(max(bid.amount) , 0) AS amount,
item.img,
item.expirydate,
item.iditem,
item.description,
item.min_price,
seller.name
FROM item
LEFT JOIN seller on seller.idseller = item.idseller
INNER JOIN bid on bid.iditem = item.iditem
WHERE
item.expirydate > curdate()
# add your idcategory here, prefixed with the tablename
GROUP BY item.iditem;
PS:我没有添加你的idcategory=1
,因为我不确定它出现在哪个table。
INNER JOIN 将尝试 JOIN 记录,如果未找到该记录,它将为您想要 SELECT 的每个 INNER JOINED 字段添加 null
值,COALESCE 将选择第一个参数,如果第一个参数是 null
.
,则为第二个
根据您为三个 table 发布的示例数据,您可以使用几个 LEFT JOIN
来确保保留所有 iditem
值。因此,当加入的 table 不与左侧的 table 同步时,您会看到一些 NULL
值。
SELECT `item`.`iditem`,
COALESCE(MAX(`bid`.`amount`), 0) AS `amount`,
`item`.`description`,
`item`.`min_price`,
`seller`.`name`
FROM `item`
LEFT JOIN `seller` ON `seller`.`idseller` = `item`.`idseller`
LEFT JOIN `bid` ON `bid`.`iditem` = `item`.`iditem`
WHERE `item`.`idcategory` IS NULL /* because you didn't give this bit of data, nor the expiry */
GROUP BY `item`.`iditem`;
这是我的 sqlfiddle demo 来证明查询对您的样本数据的成功。
在执行 JOIN 时,您应该包含一个 ON
子句来确定哪些列充当粘合剂。
WHERE
子句现在可供您根据项目要求进行配置。请务必弄清楚 table 某些列来自哪些列,以免因含糊不清而出错。
反引号环绕 table名称和列可能有点矫枉过正(有些开发人员不喜欢膨胀)但我发现这对于消除意外使用 RESERVED [=27= 的可能性是明智的]字.
我正在尝试编写一个查询,该查询连接三个 table,按 id 列分组,并查找列的最大值。但是,如果给定行没有值,则会从结果集中删除整个 table 行。
我有一个拍卖网站,有不同的物品。我将 price
显示为 max(bid)
并显示在名为 active bids 的页面上的项目旁边。我的问题是,如果某个项目没有出价,那么该项目在收到第一次出价之前不会出现在页面上。
我还有一列 min_price
因此,如果出价列中没有添加任何值,我仍然会显示最低价格。
是否可以将 max(bid)
显示为空白,但仍然显示该项目?简而言之,我问的是如何显示 table 行,即使其中一列没有插入值(该列接受了 null
,但仍然没有结果)。
这是我的查询:
SELECT COALESCE(max(bid.amount) , 0) AS amount, item.img, item.expirydate, item.iditem, item.description, item.min_price, seller.name
FROM item,seller,bid
WHERE seller.idseller=item.idseller
AND idcategory=1
and
bid.iditem=item.iditem
AND item.expirydate> curdate()
group by iditem;"
;
PHP:
<?php $datasett = $tilkobling->query($sql);
<?php while ($rad=mysqli_fetch_array($datasett)) { ?>
<tr>
<div class="artikkelbilde" id="tabell">
<td>
<img class="artikkelbilde" src="../images/<?php echo $rad ["img"];?>">
</td>
</td>
</div>
<td>
<?php echo $rad["iditem"]; ?>
</td>
<td>
<?php echo $rad["description"]; ?>
</td>
<td>
<?php echo $rad["min_price"]; ?>
</td>
<td>
<?= $rad["name"]; ?>
</td>
<td>
<?php echo $rad["expirydate"]; ?>
</td>
<td>
<?php echo $rad["amount"]; ?>
</td>
<td>
<a href="Gibud.php"> Gi bud </a>
</td>
<?php } ?>`
这里是三个相关table的SQL,信息量绝对最少,但原理应该是一样的。当项目没有出价时,我正在努力让 sql 检索项目:
CREATE TABLE `bid` (
`idbid` INT NOT NULL AUTO_INCREMENT,
`amount` INT NOT NULL,
`idbuyer` INT NULL,
`iditem` INT NULL,
PRIMARY KEY (`idbid`)
);
CREATE TABLE `item` (
`iditem` INT NOT NULL AUTO_INCREMENT,
`min_price` INT NULL,
`description` VARCHAR(45) NULL,
`idseller` INT NULL,
`idcategory` INT NULL,
PRIMARY KEY (`iditem`)
);
CREATE TABLE `seller` (
`idseller` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NULL,
PRIMARY KEY (`idseller`)
);
ALTER TABLE `bid`
ADD INDEX `FK_item_idx` (`iditem` ASC);
ALTER TABLE `bid`
ADD CONSTRAINT `FK_item`
FOREIGN KEY (`iditem`)
REFERENCES `item` (`iditem`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
ALTER TABLE `item`
ADD INDEX `FK_seller_idx` (`idseller` ASC);
ALTER TABLE `item`
ADD CONSTRAINT `FK_seller`
FOREIGN KEY (`idseller`)
REFERENCES `seller` (`idseller`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;
INSERT INTO `item` (`min_price`, `description`) VALUES ('200', 'coffeetable');
INSERT INTO `item` (`min_price`, `description`) VALUES ('400', 'lamp');
INSERT INTO `item` (`min_price`, `description`) VALUES ('600', 'painting');
INSERT INTO `bid` (`amount`, `iditem`) VALUES ('800', '1');
INSERT INTO `bid` (`amount`,`iditem`) VALUES ('1000','2');
INSERT INTO `seller` (`name`) VALUES ('Bob');
INSERT INTO `seller` (`name`) VALUES ('Rob');
INSERT INTO `seller` (`name`) VALUES ('Tob');
UPDATE `item` SET `idseller`='1' WHERE `iditem`='1';
UPDATE `item` SET `idseller`='1' WHERE `iditem`='2';
UPDATE `item` SET `idseller`='2' WHERE `iditem`='3';
您在 mysql 中使用过 COALESCE 吗??
我想你的查询中应该有这样的内容
SELECT COALESCE(max(bid) , 0) AS max_bid FROM tables1
COALESCE return 列表中的第一个非空表达式
您需要在查询中编写正确的 JOINS,而不是依赖 FROM [ table1, table2 ] 语句,因为它只使用常规 JOIN。
您可能想要这样的东西:
SELECT
COALESCE(max(bid.amount) , 0) AS amount,
item.img,
item.expirydate,
item.iditem,
item.description,
item.min_price,
seller.name
FROM item
LEFT JOIN seller on seller.idseller = item.idseller
INNER JOIN bid on bid.iditem = item.iditem
WHERE
item.expirydate > curdate()
# add your idcategory here, prefixed with the tablename
GROUP BY item.iditem;
PS:我没有添加你的idcategory=1
,因为我不确定它出现在哪个table。
INNER JOIN 将尝试 JOIN 记录,如果未找到该记录,它将为您想要 SELECT 的每个 INNER JOINED 字段添加 null
值,COALESCE 将选择第一个参数,如果第一个参数是 null
.
根据您为三个 table 发布的示例数据,您可以使用几个 LEFT JOIN
来确保保留所有 iditem
值。因此,当加入的 table 不与左侧的 table 同步时,您会看到一些 NULL
值。
SELECT `item`.`iditem`,
COALESCE(MAX(`bid`.`amount`), 0) AS `amount`,
`item`.`description`,
`item`.`min_price`,
`seller`.`name`
FROM `item`
LEFT JOIN `seller` ON `seller`.`idseller` = `item`.`idseller`
LEFT JOIN `bid` ON `bid`.`iditem` = `item`.`iditem`
WHERE `item`.`idcategory` IS NULL /* because you didn't give this bit of data, nor the expiry */
GROUP BY `item`.`iditem`;
这是我的 sqlfiddle demo 来证明查询对您的样本数据的成功。
在执行 JOIN 时,您应该包含一个 ON
子句来确定哪些列充当粘合剂。
WHERE
子句现在可供您根据项目要求进行配置。请务必弄清楚 table 某些列来自哪些列,以免因含糊不清而出错。
反引号环绕 table名称和列可能有点矫枉过正(有些开发人员不喜欢膨胀)但我发现这对于消除意外使用 RESERVED [=27= 的可能性是明智的]字.