对 SQL 查询非常困惑

时间:2021-01-21 15:14:23

标签: mysql

我刚刚开始学习 SQL 查询,但事情似乎并没有按预期进行。

给出的问题如下:

房地产所有者数据库中有两个表。

一个拥有所有权信息,另一个拥有价格信息,以百万为单位。

一个业主可以拥有多栋房子,但一栋房子只能有一个业主。

编写查询以打印至少拥有价值 1 亿房屋且拥有超过 1 间房屋的业主的 ID。

输出顺序无关紧要。

结果应采用以下格式:BUYER_ID TOTAL_WORTH。

The image of the database

我写下的查询是

SELECT house.BUYER_ID
     , SUM(price.PRICE) AS TOTAL_WORTH
  FROM house
  LEFT 
  JOIN price
    ON house.HOUSE_ID = price.HOUSE_ID
 GROUP 
    BY house.BUYER_ID
     , price.PRICE
 HAVING COUNT(house.HOUSE_ID) > 1

这没有得到正确答案,因为我无法将价格相加,并且相同的 BUYER_ID 在结果中多次出现。

在这种情况下,我需要解决什么问题才能得到正确答案?..

3 个答案:

答案 0 :(得分:3)

你应该怎么做?

只需从 price.PRICE 中删除 GROUP BY

为什么?

为了测试你的 mysql,我在谷歌上搜索“mysql 沙箱在线”并使用下一个模式进行测试:

CREATE TABLE `house` ( `BUYER_ID` INT UNSIGNED NOT NULL , `HOUSE_ID` INT UNSIGNED NOT NULL) ENGINE = InnoDB;
CREATE TABLE `price` ( `HOUSE_ID` INT UNSIGNED NOT NULL AUTO_INCREMENT , `PRICE` INT UNSIGNED NOT NULL , UNIQUE (`HOUSE_ID`)) ENGINE = InnoDB;

INSERT INTO `house` (`BUYER_ID`, `HOUSE_ID`) VALUES ('1', '1'), ('1', '2'), ('1', '3'), ('2', '4'), ('3', '5');
INSERT INTO `price` (`PRICE`) VALUES ('70'), ('20'), ('30'), ('50'), ('10');

我对 integer 使用类型 HOUSE_ID 而不是 string,只是因为它对我来说看起来更合乎逻辑。此外,我在表 AUTO_INCREMENT 中将 HOUSE_ID 用于列 price,因此所有价格都会自动获得它们的 HOUSE_ID,例如,1 表示价格 70,2 表示价格 20 等等。< /p>

因此,我得到了接下来的两个表(分别为 houseprice),其中包含要处理的数据: |BUYER_ID|HOUSE_ID| |HOUSE_ID|价格| |--------|--------|-|--------|-----| |1 |1 | |1 |70 | |1 |2 | |2 |20 | |1 |3 | |3 |30 | |2 |4 | |4 |50 | |3 |5 | |5 |10 |

当我尝试您的查询时,我会得到下一个结果: |BUYER_ID|总价值| |--------|-----------| |1 |20 | |1 |30 | |1 |70 | |2 |50 | |3 |10 |

如您所见,它只是从两个表中连接的所有现有行的列表。

为什么会这样?

您将 GROUP BY 用于两列

GROUP 
    BY house.BUYER_ID
     , price.PRICE

因此 mysql 尝试查找表 house 中在列 BUYER_ID 中具有相同值的所有行并将它们分组(应该是我的变体中的前三行)。但是,与此同时,mysql 也尝试在表price 中找到所有相同的价格。在我的示例中,至少不存在两行具有相等对 BUYER_ID - PRICE。结果 - 没有一行被分组。

为了更清楚,请看下表: |BUYER_ID|价格| |BUYER_ID*|价格*| |--------|-----|-|---------|------| |1 |20 | |1 |20 | |1 |30 | |1 |20 |

当我们使用您的查询时,我们会得到下一个结果: |BUYER_ID|总价值| |BUYER_ID*|TOTAL_WORTH*| |--------|-----------|-|---------|------------| |1 |20 | |1 |40 | |1 |30 |

  • 在第一种情况下(没有星号的列)我们将得到相同的两行,因为价格不同
  • 在第二种情况下(带星号的列)我们将得到一行,因为 BUYER_ID*PRICE* 值相等

最后的小提示

如果您在不同的表中有同名的列并且需要它们的值相等,您可以在加入它们时使用 USING

LEFT 
  JOIN price
  USING (HOUSE_ID)

它将等于您的查询

LEFT 
  JOIN price
  ON house.HOUSE_ID = price.HOUSE_ID

如果在 join 语句中有更多的列应该相等:将它们放在括号中并用逗号分隔:

USING (foo, bar)

此外,您可以对表使用别名,就像您在查询中对 SUM 使用的别名一样。如果您有长表名,则允许编写更少的代码:

FROM foo_is_my_table_name AS f

然后像这样使用

SELECT f.bar_column

代替

SELECT foo_is_my_table_name.bar_column

希望对您有所帮助,祝您学习愉快;)

答案 1 :(得分:2)

解决方案如下:

select BUYER_ID, sum(p.price) as TOTAL_WORTH from house h join price p using(HOUSE_ID) group by h.BUYER_ID with sum(p.price)>100 and count(*)>1;

这可以通过复制以下代码在任何在线编辑器 (MySQL) 上进行测试:

CREATE TABLE house ( BUYER_ID INT UNSIGNED NOT NULL , HOUSE_ID INT UNSIGNED NOT NULL) ENGINE = InnoDB;

创建表 price ( HOUSE_ID INT UNSIGNED NOT NULL AUTO_INCREMENT , PRICE INT UNSIGNED NOT NULL , UNIQUE (HOUSE_ID)) ENGINE = InnoDB;

INSERT INTO house (BUYER_ID, HOUSE_ID) VALUES ('1', '1'), ('1', '2'), ('1', ' 3'), ('2', '4'), ('3', '5');

INSERT INTO price (PRICE) VALUES ('70'), ('20'), ('30'), ('50'), ('110');

从房子中选择*;

从价格中选择*;

select BUYER_ID, sum(p.price) as TOTAL_WORTH from house h join price p using(HOUSE_ID) group by h.BUYER_ID with sum(p.price)>100 and count(*)>1;

不要忘记进行一些更改并使用代码。快乐编码!!

答案 2 :(得分:1)

输出应该是什么样的?

BUYER_ID TOTAL_WORTH

这可以通过以下方式实现:

SELECT house.BUYER_ID , SUM(price.PRICE) AS TOTAL_WORTH

条件 1: 买家应拥有 1 套以上的房子:

COUNT(house.BUYER_ID) > 1

条件2:所有自有房屋的总和应大于100。

SUM(price.PRICE) > 100

在输出中 SUM(price.PRICE) 只是具有相同 BUYER_ID 的价格总和。因此 house.BUYER_ID 可以分组,对于同一组,我们需要检查 SUM(price.PRICE) > 100。可以实现如下:

GROUP BY(house.BUYER_ID) HAVING  SUM(price.PRICE) > 100

最终答案如下:

SELECT house.BUYER_ID , SUM(price.PRICE) AS TOTAL_WORTH
FROM house 
JOIN price
USING(HOUSE_ID) GROUP BY house.BUYER_ID HAVING  SUM(price.PRICE) > 100 AND COUNT(house.BUYER_ID) > 1;