这是我第一次在这里问一个问题,我通常可以从搜索中找到我需要的东西,不过这次我被困住了,我希望这里有人可以提供帮助。
这是要点。我为一家美发工作室创建了一个数据库。有五张桌子。这个问题唯一涉及的是Customers表(存储客户详细信息),ProductSales表(关于每个产品销售的商店详细信息,以及HairCuts表,存储有关每个剪切的详细信息。
我需要一个查询,列出客户表中每个客户的头发削减和产品所花费的总额。
我有两个单独的查询可以正常工作。每个人计算每个顾客为削减头发或产品所花费的总金额。我需要以某种方式将这些组合成一个能显示总数的。
SELECT c.customer_ID, c.first_Name, c.last_name,
SUM(hc.cost) AS hc_sales_total
FROM Customers c, HairCuts hc
WHERE c.customer_ID = hc.customer_ID
GROUP BY c.customer_ID;
SELECT c.customer_ID, c.first_Name, c.last_name,
SUM(ps.cost) AS ps_sales_total
FROM Customers c,ProductSales ps
WHERE c.customer_ID = ps.customer_ID
GROUP BY c.customer_ID;
我相信我所遇到的问题源于这样一个事实,即虽然所有顾客至少购买了一次剪发,但并非所有顾客都购买了产品。无论如何,任何帮助将不胜感激。
答案 0 :(得分:4)
UNION
你的两个问题在一起。
然后你会得到一张包含所有费用的表格。
从那时起,您可以将其视为新查询的来源,以总计这些结果
SELECT customer_ID, first_name, last_name, sum(hc_sales_total) as totalsales
FROM
(
SELECT c.customer_ID, c.first_Name, c.last_name,
SUM(hc.cost) AS hc_sales_total
FROM Customers c
INNER JOIN HairCuts hc
ON c.customer_ID = hc.customer_ID
GROUP BY c.customer_ID
UNION ALL
SELECT c.customer_ID, c.first_Name, c.last_name,
SUM(ps.cost) AS ps_sales_total
FROM Customers c
INNER JOIN ProductSales ps
ON c.customer_ID = ps.customer_ID
GROUP BY c.customer_ID
) sales
GROUP BY customer_ID, first_name, last_name
当然,内部分组是多余的,所以
SELECT customer_ID, first_name, last_name, sum(cost) as totalsales
FROM
(
SELECT c.customer_ID, c.first_Name, c.last_name, hc.cost
FROM Customers c
INNER JOIN HairCuts hc
ON c.customer_ID = hc.customer_ID
UNION ALL
SELECT c.customer_ID, c.first_Name, c.last_name, ps.cost
FROM Customers c
INNER JOIN ProductSales ps
ON c.customer_ID = ps.customer_ID
) sales
GROUP BY customer_ID, first_name, last_name
答案 1 :(得分:1)
如果您想要所有三个总和,可以使用union all
/ group by
方法执行此操作:
SELECT c.customer_ID, c.first_Name, c.last_Name,
SUM(hp.hc_sales) as hp.hc_sales_total, SUM(hp.ps_sales) as hp.ps_sales_total,
SUM(hp.hc_sales_total + hp.ps_sales_total) as Total
FROM ((SELECT hc.customer_ID, hc.cost AS hc_sales, 0 as ps_sales
FROM HairCuts hc
) UNION ALL
(SELECT ps.customer_ID, 0, ps.cost AS ps_sales
FROM ProductSales ps
)
) hp JOIN
Customers c
on c.customer_ID = hp.customer_ID
GROUP BY c.customer_ID, c.first_Name, c.last_Name;
请注意此查询与您的查询不同的方式:
union all
使用显式join
语法后的联接,条件符合on
子句。答案 2 :(得分:0)
你有没有试过这样的事情:
SELECT c.customer_ID, c.first_Name, c.last_name,
SUM( isnull( hc.cost,0) + isnull(ps.cost,0) ) AS hc_pc_sales_total
FROM Customers c, HairCuts hc, ProductSales ps
WHERE c.customer_ID = hc.customer_ID AND
c.customer_ID = ps.customer_ID
GROUP BY c.customer_ID;
我不知道你使用的是哪个数据库,但请不要忘记使用'ISNULL'来处理'null'值。
有关ISNULL函数,请参阅http://www.w3schools.com/sql/sql_isnull.asp。
答案 3 :(得分:0)
您需要使用外部联接以确保所有客户都在联接表中表示。这是您修改的第二个查询:
SELECT
c.customer_ID,
c.first_Name,
c.last_name,
COALESCE(SUM(ps.cost), 0) AS ps_sales_total
FROM
Customers AS c
LEFT JOIN ProductSales AS ps ON c.customer_ID = ps.customer_ID
GROUP BY
c.customer_ID
另请注意,我使用COALESCE确保SUM的结果为零而不是NULL。
顺便说一句,我个人不喜欢用于连接表的逗号语法(FROM c, ps
)。我更喜欢使用显式语法(FROM c JOIN ps ON ...
)。在某种程度上,这是因为我认为最好将连接逻辑放在FROM子句中,而不是将它与WHERE子句组合。
另外,为什么first_Name
有N
但last_name
有n
?
关于组合两个查询的结果,您可以采用多种方法。您可以在子查询中使用union,然后使用GROUP BY使用GROUP,如podiluska所建议的那样。或者,您可以为customers表中的每一行选择子查询的结果:
SELECT
(
SELECT COALESCE(SUM(hc.cost), 0)
FROM HairCuts AS hc
WHERE hc.customer_ID = c.customer_ID
) + (
-- similar to above
) AS AmountSpent
FROM
Customers c
答案 4 :(得分:0)
就个人而言,我更喜欢预先聚合到新的表引用中:
SELECT Customers.customer_Id, Customer.first_Name, Customer.last_Name,
COALESCE(HairCuts.cost, 0) + COALESCE(ProductSales.cost, 0) as totalCost
FROM Customers
LEFT JOIN (SELECT customer_Id, SUM(cost) AS cost
FROM HairCuts
GROUP BY customer_Id) HairCuts
ON HairCuts.customer_Id = Customers.customer_Id
LEFT JOIN (SELECT customer_Id, SUM(cost) AS cost
FROM ProductSales
GROUP BY customer_Id) ProductSales
ON ProductSales.customer_Id = Customers.customer_Id
(未经过测试,因为我没有基于它的数据。但是应该在任何RDBMS中工作)