如何在不丢失行的情况下加入3个表?

时间:2018-05-05 19:23:22

标签: php mysql join max multiple-tables

我正在尝试编写一个查询,该查询通过id列连接三个表,组,并查找列的最大值。但是,如果给定行没有值,则从结果集中删除整个表行。

我有一个拍卖网站,有不同的项目。我在名为有效出价的网页上的项目旁边显示price max(bid)。我的问题是,如果某个商品没有出价,那么该商品在收到第一个出价之前就不会出现在页面上。

我还有一列min_price,因此如果在出价列中未添加任何值,我仍然会显示最低价格。

是否可以将max(bid)显示为空白,但仍然可以显示该项目?简而言之,我问我如何显示一个表行,即使其中一列没有插入值(该列已接受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 } ?>`

这是三个相关表的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';

3 个答案:

答案 0 :(得分:2)

根据您发布的三个表的示例数据,您可以使用几个LEFT JOIN来确保保留所有iditem值。因此,当连接的表格与左侧的表格不同步时,您会看到一些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子句来配置您的项目要求。请务必澄清某些列来自哪个表,以免因模糊而导致错误。

反引号包装的表名和列可能有点过分(而且有些开发人员不喜欢膨胀)但我发现这对于消除意外使用RESERVED mysql单词的可能性是明智的。

答案 1 :(得分:1)

你有没有在mysql中使用COALESCE?

我认为你的查询应该有这样的东西

SELECT COALESCE(max(bid) , 0) AS max_bid FROM tables1

COALESCE返回列表中的第一个非空表达式

答案 2 :(得分:0)

您需要在查询中编写正确的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,因为我不确定它出现在哪个表中。

INNER JOIN将尝试加入一条记录,如果找不到该记录,它将为你想要选择的每个INNER JOINED字段添加null值,COALESCE将选择第一个参数,或者如果第一个是null,则为秒。