“单行子查询返回多行”SQL

时间:2016-12-30 07:59:11

标签: sql oracle

我有两张桌子。

CREATE TABLE Customers
(
  cust_id      char(10)  NOT NULL ,
  cust_name    char(50)  NOT NULL ,
  cust_address char(50)  NULL ,
  cust_city    char(50)  NULL ,
  cust_state   char(5)   NULL ,
  cust_zip     char(10)  NULL ,
  cust_country char(50)  NULL ,
  cust_contact char(50)  NULL ,
  cust_email   char(255) NULL 
);
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000001', 'Village Toys', '200 Maple Lane', 'Detroit', 'MI', '44444', 'USA', 'John Smith', 'sales@villagetoys.com');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES('1000000002', 'Kids Place', '333 South Lake Drive', 'Columbus', 'OH', '43333', 'USA', 'Michelle Green');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000003', 'Fun4All', '1 Sunny Place', 'Muncie', 'IN', '42222', 'USA', 'Jim Jones', 'jjones@fun4all.com');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000004', 'Fun4All', '829 Riverside Drive', 'Phoenix', 'AZ', '88888', 'USA', 'Denise L. Stephens', 'dstephens@fun4all.com');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES('1000000005', 'The Toy Store', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'Kim Howard');

CREATE TABLE Orders
(
  order_num  int      NOT NULL ,
  order_date date     NOT NULL ,
  cust_id    char(10) NOT NULL 
);
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20005, TO_DATE('2012-05-01', 'yyyy-mm-dd'), '1000000001');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20006, TO_DATE('2012-01-12', 'yyyy-mm-dd'), '1000000003');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20007, TO_DATE('2012-01-30', 'yyyy-mm-dd'), '1000000004');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20008, TO_DATE('2012-02-03', 'yyyy-mm-dd'), '1000000005');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20009, TO_DATE('2012-02-08', 'yyyy-mm-dd'), '1000000001');

有趣的是,如果我跑:

SELECT count(*) AS order_count,
  (SELECT cust_name
   FROM customers
   WHERE customers.cust_id=orders.cust_id) AS cust_name,
   cust_id
FROM orders
GROUP BY cust_id
ORDER BY cust_id;

没有错误。

但是如果我创建一个新表并运行类似的代码:

CREATE TABLE orders2 AS SELECT * FROM orders
SELECT count(*) AS order_count,
  (SELECT cust_id
   FROM orders2
   WHERE orders2.cust_id=orders.cust_id) AS cust_id2,
   cust_id
FROM orders
GROUP BY cust_id
ORDER BY cust_id;

它给我一个错误:single-row subquery returns more than one row

那么为什么会这样呢?我知道错误信息是什么。根据该文档,如果“外部查询必须使用其中一个关键字ANY,ALL,IN或NOT IN来指定要比较的值,则会触发此错误,因为子查询返回了多行。”不满意。但我无法理解为什么第一个代码符合条件,但第二个代码不符合。

DBMS:Oracle 11

4 个答案:

答案 0 :(得分:1)

老兄你有重复的cust_id'1000000001'以及如何期待sql解决问题。你可以更详细地说明你的要求吗?可以看到他们中的许多人都不清楚你的问题。

如果存在多个(重复的)Cust_id,那么它会毫无根据,因此Oracle肯定会通过您发送此错误消息。

使用Distinct已解决了查询,并且没有收到任何错误消息。

SELECT count(*) AS order_count,
  (SELECT distinct cust_id
FROM orders2
WHERE orders2.cust_id=orders.cust_id) AS cust_id2,
cust_id
FROM orders
GROUP BY cust_id
ORDER BY cust_id;

如果我的建议错误,请纠正我,因为显然你应该能够理解这个问题。

答案 1 :(得分:0)

我真的不理解失败的陈述,甚至我也不知道为什么你需要一个order2表。 无论如何,我猜你想要计算每个客户ID的订单数量,如果是这样我认为没有必要进行子选择,你可以这样做

SELECT count(*) AS order_count, cust_id
FROM orders
GROUP BY cust_id
ORDER BY cust_id;

或者我错过了什么?

答案 2 :(得分:0)

帮助您了解差异:

因为您目前在Customers表上似乎没有PK,请执行以下操作:

INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES('1000000005', 'DUPLICATE CUST_ID', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'Kim Howard');
  • 然后再次尝试运行您的第一个查询。 你应该注意到它现在也失败并出现相同的错误
  • 相反,如果您只是对第二个查询执行解析检查而不运行:您将不会收到错误,因为 在语法上正确
  

那么为什么会这样呢?

您的代码类似,但您的数据不同。当查询 执行 时,检测到 数据问题 会触发错误。 仅在编译查询时无法检测到此错误。

  

但我无法理解为什么第一个代码符合条件,但第二个代码不符合。

两个查询中的 代码 均有效。只是当子查询执行某些orders.cust_id值时,子查询返回太多行。

这就是为什么在构造此类查询时必须非常小心关系的基数。如果您犯了错误,查询可以成功运行多年,然后在返回额外行时突然中断。

答案 3 :(得分:0)

选择:

SELECT count(*) AS order_count,
  (SELECT cust_id
   FROM orders2
   WHERE orders2.cust_id=orders.cust_id) AS cust_id2,
   cust_id
FROM orders
GROUP BY cust_id
ORDER BY cust_id;

是选择的差异:

    SELECT count(*) AS order_count,
  (SELECT cust_name
   FROM customers
   WHERE customers.cust_id=orders.cust_id) AS cust_name,
   cust_id
FROM orders
GROUP BY cust_id
ORDER BY cust_id;

因为你从Orders而不是从Custmer创建第二个表:

CREATE TABLE orders2 AS SELECT * FROM orders

并且该行重复使用cust_id` = 1000000001