对于mySQL分配,我们将创建一个视图,其中包含2014-01-01和2014-03-28之间订购的数据库中的打印件的item_id,title,artist,unit_price和order_qty。
CREATE VIEW orders_v AS
SELECT items.item_id, title, artist, unit_price,
order_qty
FROM items, orderline, orders
WHERE items.item_id = orderline.item_id
AND orderline.order_id = orders.order_id
AND orders.order_date like '2014-01%'
OR orders.order_date like '2014-02%'
GROUP BY items.item_id;
但是,视图中的数据显示在从未订购过的商品中,我无法找到原因。
在我的测试中,应该只有四个订单落在所需的时间段内:order_id	 10,11和12。
order_id: 9, item_id: 100, order_qty: 3
order_id: 10, item_id: 450, order_qty: 6
order_id: 10, item_id: 600, order_qty: 8
order_id: 10, item_id: 200, order_qty: 4
order_id: 11, item_id: 700, order_qty: 2
order_id: 12, item_id: 300, order_qty: 4
但相反,它会显示不会被订购的商品,例如item_id:400,或者在时间范围之外订购的商品。
任何帮助或建议都将不胜感激。
我的代码可以找到here,如果查看和测试它会有所帮助。
答案 0 :(得分:1)
您需要将以下部分放在括号中:
( orders.order_date like '2014-01%'
OR orders.order_date like '2014-02%'
)
这是因为AND
优先于OR
,因此如果没有括号,则表示所有先前条件必须为真,或者最后一条(单独)。这不是您的意图,因为您希望以前的条件始终为真。
其次,由于您按项目对结果进行分组,但不对订单数量求和,因此您只需获取匹配的第一条记录的订单数量。这可能不是你想要的。只需将sum()
包裹在其周围:
select ... sum(order_qty)
尽管匹配日期与LIKE
有效,但您应该考虑更改比较日期的方式,因为它不能维持更长时间,对于更精确的范围更难。相反,请使用BETWEEN
,您可以将限制设置为当天:
orders.order_date between '2014-01-01' and '2014-02-28'
请参阅具有更正的this SQL fiddle。它返回此结果集:
+---------+---------------+------------------+------------+-----------+
| item_id | title | artist | unit_price | order_qty |
+---------+---------------+------------------+------------+-----------+
| 100 | Under the Sun | Donald Arley | 46.8 | 3 |
| 200 | Dark Lady | Keith Morris | 120.99 | 4 |
| 300 | Happy Days | Andrea Reid | 78 | 3 |
| 450 | The Hunt | Walter Alford | 39.99 | 6 |
| 600 | Rainbow Row | Judy Ford | 46 | 8 |
| 700 | Skies Above | Alexander Wilson | 98 | 6 |
+---------+---------------+------------------+------------+-----------+
答案 1 :(得分:1)
括号是你的朋友。 OR
的优先级高于AND
,因此您在2月份的所有订单上获得了笛卡尔积。您的视图应定义为
CREATE VIEW orders_v AS
SELECT items.item_id, title, artist, unit_price, order_qty
FROM items, orderline, orders
WHERE items.item_id = orderline.item_id
AND orderline.order_id = orders.order_id
AND (orders.order_date like '2014-01%'
OR orders.order_date like '2014-02%')
GROUP BY items.item_id;
答案 2 :(得分:1)
有几种方法可以改善您的查询。首先是使用JOIN
syntax将where连接与where子句分开。这使查询更容易阅读,并有助于发现问题。
SELECT items.item_id, title, artist, unit_price, order_qty
FROM items
JOIN orderline ON items.item_id = orderline.item_id
JOIN orders ON orderline.order_id = orders.order_id
WHERE orders.order_date like '2014-01%'
OR orders.order_date like '2014-02%'
GROUP BY items.item_id
正如其他答案中所指出的,这可以解决您的问题,因为它不再是AND / OR优先问题。
其次是使用CHAR(10)
存储日期的不幸选择。幸运的是,您使用的是ISO 8601格式,因此您可以轻松对其进行排序,但最好将它们存储为DATE
或DATETIME
,以充分利用MySQL's date functions的全部范围和日期索引,并使用较少的存储空间。如果order_date
是DATE
,您可以使用BETWEEN
编写查询。
SELECT items.item_id, title, artist, unit_price, order_qty
FROM items
JOIN orderline ON items.item_id = orderline.item_id
JOIN orders ON orderline.order_id = orders.order_id
WHERE orders.order_date BETWEEN '2014-01-01' AND '2014-02-28'
GROUP BY items.item_id