我必须编写一个符合以下要求的查询:
查询应该返回所有的列表 名为的客户的条目值 “史蒂夫”和显示的每个日期(如果 可用)最新的状态详细信息 那个日期。
客户表
CustomerID | CustomerName
1 | Steve
2 | John
条目表
CustomerID | EntryDate | EntryValue
1 | 5/4/2010 | 200.0
1 | 4/4/2010 | 100.0
1 | 3/4/2010 | 150.0
1 | 2/4/2010 | 170.0
2 | 5/4/2010 | 220.0
状态表
CustomerID | StatusDate | Detail
1 | 5/28/2010 | D
1 | 4/24/2010 | S
1 | 4/5/2010 | P
1 | 2/28/2010 | A
预期输出为:
CustomerName | Date | OrderCost | Detail
Steve | 5/4/2010 | 200.0 | S
Steve | 4/4/2010 | 100.0 | A
Steve | 3/4/2010 | 75.0 | A
Steve | 3/4/2010 | 75.0 | <null>
我认为预期的输出可能是错误的,实际应该是:
CustomerName | Date | OrderCost | Detail
Steve | 5/4/2010 | 200.0 | S
Steve | 4/4/2010 | 100.0 | A
Steve | 3/4/2010 | 150.0 | A
Steve | 2/4/2010 | 170.0 | <null>
根据要求,我不明白为什么2010年3月4日的日期会发生两次,第二次会有详细信息。我写了以下查询:
我写了以下查询:
SELECT Customers.CustomerName, Entries.EntryDate, Entries.EntryValue, Status.Detail
FROM Customers
INNER JOIN Entries ON Customers.CustomerID = Entries.CustomerID
LEFT OUTER JOIN Status ON Status.CustomerID = Customers.CustomersID AND Status.StatusDate <= Entries.EntryDate
WHERE (Customers.CustomerName = 'Steve')
我的查询结果如下:
CustomerName| EntryDate | EntryValue | Detail
Steve | 5/4/2010 | 200.00 | S
Steve | 5/4/2010 | 200.00 | P
Steve | 5/4/2010 | 200.00 | A
Steve | 4/4/2010 | 100.00 | A
Steve | 3/4/2010 | 150.00 | A
Steve | 2/4/2010 | 170.00 | NULL
我在这里做错了什么提示?我无法弄明白......
更新 我已将订单更改为条目,因此不会让我们感到困惑。
答案 0 :(得分:1)
您获得的结果超出预期,因为状态表中的许多行都满足第二个JOIN条件(例如,有5个状态日期早于5/4,因此此日期在结果集中出现3次)。
您需要加入状态表,但只能获得一个匹配(最新)。这可以通过几种方式完成,AFAIK通常带有子查询。我认为你的情况相当复杂 - 我使用临时表。希望它有所帮助......(我目前没有数据库来测试它,希望没有愚蠢的语法错误。)
DROP TABLE IF EXISTS temp;
CREATE TABLE temp AS -- This temp table is basically the result set you got
(SELECT c.CustomerName, e.EntryDate, e.EntryValue, s.Detail, s.StatusDate
FROM Customers c
INNER JOIN Entires e ON c.CustomerID = e.CustomerID
LEFT OUTER JOIN Status s ON s.CustomerID = c.CustomersID
AND s.StatusDate <= e.EntryDate
WHERE (c.CustomerName = 'Steve')
);
SELECT t.CustomerName, t.EntryDate, t.EntryValue, t.Detail
FROM temp t
WHERE t.StatusDate = (SELECT MAX(t2.StatusDate)
FROM temp t2
WHERE t2.EntryDate = t.EntryDate);
要避免创建临时表,我相信这会有用(请尝试让我知道!)
SELECT t.CustomerName, t.EntryDate, t.EntryValue, t.Detail
FROM (SELECT c.CustomerName, e.EntryDate, e.EntryValue, s.Detail, s.StatusDate
FROM Customers c
INNER JOIN Entries e ON c.CustomerID = e.CustomerID
LEFT OUTER JOIN Status s ON s.CustomerID = c.CustomersID
AND s.StatusDate <= e.EntryDate
WHERE c.CustomerName = 'Steve') AS t
WHERE t.StatusDate = (SELECT MAX(t2.StatusDate)
FROM temp t2
WHERE t2.EntryDate = t.EntryDate);
答案 1 :(得分:1)
您可以使用子查询来获取状态 对于SQL Server使用TOP 1,对SQLite / MySQL使用LIMIT 1
SQL Server / SyBase
SELECT Customers.CustomerName, Entries.EntryDate, Entries.EntryValue,
(SELECT top 1 Status.Detail From Status
where Status.CustomerID = Customers.CustomersID AND Status.StatusDate <= Entries.EntryDate
order by Status.StatusDate desc)
FROM Customers
INNER JOIN Entries ON Customers.CustomerID = Entries.CustomerID
WHERE (Customers.CustomerName = 'Steve')
MySQL / SQLite
SELECT Customers.CustomerName, Entries.EntryDate, Entries.EntryValue,
(SELECT Status.Detail From Status
where Status.CustomerID = Customers.CustomersID AND Status.StatusDate <= Entries.EntryDate
order by Status.StatusDate desc
limit 1)
FROM Customers
INNER JOIN Entries ON Customers.CustomerID = Entries.CustomerID
WHERE (Customers.CustomerName = 'Steve')
答案 2 :(得分:0)
状态日期是否应该在订单日期之后?类似的东西:
SELECT Customers.CustomerName, Orders.OrderDate, Orders.OrderCost, Status.Detail
FROM Customers
INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID
LEFT OUTER JOIN Status ON Status.CustomerID = Customers.CustomersID
WHERE Customers.CustomerName = 'Steve' AND Status.StatusDate >= Orders.OrderDate
此外,CustomerID
表中的Status
似乎有点奇怪,因为它通常是具有状态的订单,而不是客户。状态表不应该有OrderID
字段吗?
答案 3 :(得分:0)
预期输出错误。最后一行应该是2010年2月4日。此外,他们的订单成本也不对。 2/4/2010应该返回null,因为没有匹配状态。