我参加了一个数据库课程,其中包含AirBnB的列表,并且需要能够在我们根据数据制作的关系模型中执行一些SQL查询,但是我尤其要特别努力:
我有两个我们感兴趣的表,Billing
和Amenities
。第一个具有列表的id
和price
,第二个具有id
和wifi
(为简单起见,如果有Wifi,则等于1,0除此以外)。两者都有我们在这里不太在乎的其他属性。
所以查询的是,“有和没有Wifi的商家信息的平均价格有何不同?”
我的想法是建立JOIN表,其中一个包含具有wifi列表的列表,另一个不包含该列表,然后轻松比较它们:
SELECT avg(B.price - A.price) as averagePrice
FROM (
SELECT Billing.price, Billing.id
FROM Billing
INNER JOIN Amenities
ON Billing.id = Amenities.id
WHERE Amenities.wifi = 0
) A, (
SELECT Billing.price, Billing.id
FROM Billing
INNER JOIN Amenities
ON Billing.id = Amenities.id
WHERE Amenities.wifi = 1) B
WHERE A.id = B.id;
显然这是行不通的...我很确定有一个更简单的解决方案,我想念什么?
(顺便说一下,有没有一种方法可以计算价格差之间的绝对值?)
我希望我足够清楚,谢谢您的时间!
编辑:如评论中所述,忘记了这一点,但是两个表都以id
作为主键,因此每个列表只有一行。
答案 0 :(得分:2)
只需使用条件聚合:
!=
如果您想要差异而不是特定值,可以使用allEqual
。
答案 1 :(得分:1)
假设我们正在处理以下数据(下面将说明您的数据模型存在的问题):
Billing +------------+---------+ | listing_id | price | +------------+---------+ | 1 | 1500.00 | | 2 | 1700.00 | | 3 | 1800.00 | | 4 | 1900.00 | +------------+---------+ Amenities +------------+------+ | listing_id | wifi | +------------+------+ | 1 | 1 | | 2 | 1 | | 3 | 0 | +------------+------+
请注意,我已将“ id”更改为“ listing_id”以使其清晰可见(无论如何,使用“ id”作为属性名称都是有问题的)。另外,请注意,“便利设施”表中没有一个列表。根据您的数据,可能会或可能不会担心(再次,请参阅底部的有关数据模型的讨论)。
基于此数据,您的平均值应为:
所以差额是200美元。
要在SQL中获得此结果,首先获取每次使用便利设施的平均费用(是否提供wifi)可能会有所帮助。这可以通过以下查询获得:
SELECT Amenities.wifi AS has_wifi, AVG(Billing.price) AS avg_cost FROM Billing INNER JOIN Amenities ON Amenities.listing_id = Billing.listing_id GROUP BY Amenities.wifi
为您提供以下结果:
+----------+-----------------------+ | has_wifi | avg_cost | +----------+-----------------------+ | 0 | 1800.0000000000000000 | | 1 | 1600.0000000000000000 | +----------+-----------------------+
到目前为止,一切都很好。因此,现在我们需要计算这两行之间的差。有许多不同的方法可以执行此操作,但是一种方法是使用CASE
表达式将其中一个值设为负,然后简单地将结果的SUM
用作结果(请注意,使用CTE,但您也可以使用子查询):
WITH avg_by_wifi(has_wifi, avg_cost) AS ( SELECT Amenities.wifi, AVG(Billing.price) FROM Billing INNER JOIN Amenities ON Amenities.listing_id = Billing.listing_id GROUP BY Amenities.wifi ) SELECT ABS(SUM ( CASE WHEN has_wifi = 1 THEN avg_cost ELSE -1 * avg_cost END )) FROM avg_by_wifi
这为我们提供了200
的期望值。
现在有关您的数据模型:
Billing
和Amenities
表的每个列表仅具有1行,则将它们合并为1个表是有意义的。例如:Listings(listing_id, price, wifi)
Listings(listing_id, price) Amenities(amenity_id, amenity_name) ListingsAmenities(listing_id, amenity_id)
这样,您可以为给定列表列出多个便利设施,而不必添加其他列。存储有关便利设施的其他信息也变得很容易:什么是wifi密码?游泳池有多深?等
当然,使用此模型会使您的原始查询(按wifi列出的平均房源费用有所不同)有些棘手,但绝对可以。