我想修改以下查询,以便它不是ORDER.S_ID列,而是从表(称为STORES)S_ID引用的相应NAME列中获取值。
但是,在某些情况下,S_ID为null,在这种情况下,没有相应的名称列。在这种情况下,仍然有来自ORDER和ORDERLIST表的记录,我想要COUNT(*) - ed并由此查询显示,以便结果集的第二列为空
SELECT
COUNT(*), ORDER.S_ID
FROM
ORDER, ORDERLIST
WHERE
ORDERLIST.O_ID = ORDER.ID AND
ORDER.DATE = '13-APR. -09 19.42.05,259000000'
GROUP BY S_ID;
示例数据:
ORDER表
ID DATE S_ID
----------------------------------------
1 11-APR. -09 19.41.39,187000000 null
2 12-APR. -09 19.42.05,259000000 null
3 13-APR. -09 19.42.41,688000000 null
11 16-APR. -09 22.06.11,169000000 3
ORDERLIST表
O_ID B_ID PRICE
---------------------
3 6 7999
2 2 2000
2 6 7999
1 5 5000
1 1 1000
11 4 4000
11 6 7999
STORES表
ID NAME
----------
1 Store1
2 Store2
3 Store3
如果用户查询S_ID值为非空的日期,我希望看到的内容:(此特定情况是查询日期16-APR。-09 22.06.11,169000000)
COUNT(*) STORENAME
2 Store3
如果它为空,我想要返回的内容: (查询日期13-APR.-09 19.42.41,688000000)
COUNT(*) STORENAME
1 null
答案 0 :(得分:1)
正如Gordon所说,你需要一个外连接,并且使用正确的连接语法会更好 - 特别是对于外连接,但无论你的导师使用什么,都要一直使用。
由于您从订单开始并且可能具有匹配的商店,因此您需要将stores表的连接作为外部联接:
SELECT o.s_id, s.name, count(*)
FROM "ORDER" o
JOIN orderlist ol ON ol.o_id = o.id
LEFT JOIN stores s ON s.id = o.s_id
--WHERE o."DATE" = TO_TIMESTAMP('13-APR. -09 19.42.05,259000000', 'DD-MON". "-RR HH24.MI.SS,FF9')
GROUP BY o.s_id, s.name;
S_ID NAME COUNT(*)
---------- ------ ----------
5
3 Store3 2
由于'order'和'date'是保留字,我必须使用带引号的标识符,但它们可能不是真实的名字。如果您可以避免使用带引号的标识符,请不要使用它们。我使用表别名来减轻痛苦。 'date'也是一个时间戳而不是一个日期,因为你有小数秒,使名称更令人困惑。
我已经注释了日期/时间戳限制,因为它与您的任何样本数据都不匹配,如果更改为4月12日仍然只匹配一个,这对于演示来说不是很有用。您的NLS_TIMESTAMP_FORMAT是......不寻常,但这是一个单独的问题。为了比较,使用时间戳文字更简单:
WHERE o."DATE" = TIMESTAMP '2009-04-12 19:42:05.259000000'
请注意,与NLS_TIMESTAMP_FORMAT不同,它具有冒号和句点作为秒值的小数分数。
如果您的导师真的坚持旧的,特定于Oracle的连接语法,那么可以将其排列为:
SELECT o.s_id, s.name, count(*)
FROM "ORDER" o, orderlist ol, stores s
WHERE ol.o_id = o.id
AND s.id (+) = o.s_id
--AND o."DATE" = TIMESTAMP '2009-04-12 19:42:05.259000000'
GROUP BY o.s_id, s.name;
...但是要弄清楚发生了什么事情要困难得多,而且更容易在连接条件中犯错(或者完全留下一个)。请使用正确的ANSI连接语法...