【问题标题】:Subquery in FROM not working in Oracle SQLFROM 中的子查询在 Oracle SQL 中不起作用
【发布时间】:2018-10-05 17:11:08
【问题描述】:

我正在将查询从 WHERE 部分中的子查询转换为 FROM 部分。

据我了解,FROM 子句将返回一个表,我称之为“product_locations”,然后我的外部查询可以从该表中检索信息。我现在看不到外部查询是否正常工作,因为我遇到了一个错误,我错过了一个右括号。 在这一点上,我认为我的主要问题是不了解如何正确识别构成子查询的 IN 子句的两个部分。

这是原始查询:

SELECT size_option, 
       product.product_name
FROM   sizes
JOIN   available_in ON sizes.sized_id = available_in.sizes_id
JOIN   product ON product.product_id = available_in.product_id
WHERE (SELECT COUNT (store_name)
       FROM store_location IN (SELECT COUNT (store_location_id)
       FROM sells
       JOIN product ON sells.product_id = product.product_id
       GROUP BY sells.store_location)

这是我正在尝试的查询:

SELECT size_option, 
       product_location.product_name 
FROM   (SELECT COUNT(store_name)
       FROM   store_location) IN (SELECT COUNT (store_location_id)
       FROM sells
       JOIN product ON sells.product_id = product.product_id
GROUP BY sells.store_location_id) product_location
JOIN   sizes ON sizes.size_option = product_location.size_option
JOIN   available_in ON sizes.sizes_id = available_in.sizes_id
JOIN   product ON product.product_id = available_in.product_id

以及我得到的错误:

SELECT size_option, 
       product_location.product_name 
FROM   (SELECT COUNT(store_name)
       FROM   store_location) IN (SELECT COUNT (store_location_id)
       FROM sells
       JOIN product ON sells.product_id = product.product_id
GROUP BY sells.store_location_id) product_location
JOIN   sizes ON sizes.size_option = product_location.size_option
JOIN   available_in ON sizes.sizes_id = available_in.sizes_id
JOIN   product ON product.product_id = available_in.product_id
Error at Command Line : 4 Column : 31
Error report -
SQL Error: ORA-00933: SQL command not properly ended
00933. 00000 -  "SQL command not properly ended"
*Cause:    
*Action:

这是我的编辑器中的错误图片

这里是 ERD

【问题讨论】:

  • INFROM 子句中无法识别。很难说你的意图是什么。
  • FROM 子句中的查询称为“表表达式”。表表达式必须命名,如select * from (select ...) x。查看x?
  • 现在,在原始查询中,子查询是“相关”子查询。典型的表格表达式不接受这些,除非您创建“横向表格表达式”。分分钟越来越难看。你为什么要首先这样做?
  • 其目的是显示所有位置可用的所有产品。 IN 语句的目的是,第一个 COUNT (SELECT COUNT(store_name) FROM store_location) 计算商店数量,第二个 (SELECT COUNT (store_location_id) FROM sells JOIN product ON sells.product_id = product.product_id GROUP BY sells.store_location_id) product_location 计算每个产品可用的商店数量,因此如果第二个查询中包含第一个数字,则结果将被选中。
  • @TheImpaler 不幸的是,我想这样做是因为我的研究生院数据库教授是一个虐待狂。我是一名网络人,正在学习数据库课程!

标签: sql oracle oracle11g subquery


【解决方案1】:

在 FROM 子句中使用 IN condition 可能会让您感到痛苦,因为 “条件指定一个或多个表达式和逻辑(布尔)运算符的组合,并返回 TRUE、FALSE 或 UNKNOWN 值。” (见documentation)。因此,像 (SELECT ...) IN (SELECT ...) 这样的结构 - 如果语法正确 - 将返回 true、false 或 unknown - 这在 WHERE 子句(而不是 FROM 子句)中很有用。

在您的一个 cmets 中,您正在解释... " 目的是展示在所有位置可用的所有产品。"

使用包含 5 个表的小型测试数据集(请参阅 dbfiddle),以下查询可能会为您提供 寻找解决方案的起点:

-- Find the store count for each product (table SELLS)
-- and return all product_ids that are available everywhere (STORE_LOCATION count)

select product_id
from (
  select 
    product_id
  , count( store_location_id ) store_count
  from sells
  group by product_id
  having count( store_location_id ) = ( select count(*) from store_location )
) ;

-- result
PRODUCT_ID
----------
        10

另类

-- ---------------------------------------------------
-- use analytics -> we don't need GROUP BY and HAVING
-- ---------------------------------------------------
-- 1  count all store_locations (SL)
-- 2  count the amount of stores a product is located in (S)
-- 3  JOIN the 2 result sets (equijoin)
-- 4  return the product_id found
-- NOTE: we are working with Oracle -> don't use AS when defining table aliases (AS can be used for column aliases)

select product_id -- 4
from ( 
  select count(*) store_count from store_location  -- 1
) SL join (
  select unique 
    product_id
  , count( store_location_id ) over ( partition by product_id ) store_count -- 2
  from sells
) S on SL.store_count = S.store_count -- 3
;

-- result
PRODUCT_ID
----------
        10

获得正确的 product_id(s) 后,您可以“固定”查询所需的剩余表(使用 JOIN)并将所有必需的列名(包括表别名)写入 SELECT。 例如

select 
  S.product_id
, P.product_name
, SZ.size_option
from ( 
  select count(*) store_count from store_location 
) SL join (
  select unique
    product_id
  , count( store_location_id ) over ( partition by product_id ) store_count
  from sells
) S on SL.store_count = S.store_count 
join product P       on S.product_id = P.product_id
join available_in AI on AI.product_id = P.product_id 
join sizes SZ        on AI.sizes_id = SZ.sizes_id
;

-- result
PRODUCT_ID PRODUCT_N SIZE_OP
---------- --------- -------
        10 product10 option1
        10 product10 option2

【讨论】:

    【解决方案2】:

    您的查询可能如下所示

    SELECT size_option, 
           product_location.product_name,
          (
           SELECT COUNT(store_name)
           FROM   store_location
           )  as store_name_cnt,
           (
           SELECT COUNT (store_location_id)
           FROM sells
           JOIN product ON sells.product_id = product.product_id
        GROUP BY sells.store_location_id
         ) as location_count
        from product_location
    JOIN   sizes ON sizes.size_option = product_location.size_option
    JOIN   available_in ON sizes.sizes_id = available_in.sizes_id
    

    您的查询错误

    SELECT size_option, 
           product_location.product_name 
    FROM   (SELECT COUNT(store_name) --invalid from 
           FROM   store_location) 
          IN (SELECT COUNT (store_location_id) -- there is no where but you use in
           FROM sells
           JOIN product ON sells.product_id = product.product_id
    GROUP BY sells.store_location_id) product_location -- inconsistent table alias
    JOIN   sizes ON sizes.size_option = product_location.size_option
    JOIN   available_in ON sizes.sizes_id = available_in.sizes_id
    JOIN   product ON product.product_id = available_in.product_id
    

    【讨论】:

      【解决方案3】:

      根据 cmets 中的 OP:目的是显示所有位置可用的所有产品。

      考虑连接两个聚合查询派生表(或FROMJOIN 子句中的子查询):

      1. 计算特定产品的店铺数
      2. 统计所有产品的店铺数

      然后通过相应的 product_idstore_count 值加入子查询。请务必使用表别名以提高可读性。

      SELECT s.size_option, 
             p.product_name
      FROM   sizes AS s
      JOIN   available_in AS a ON s.sized_id = a.sizes_id
      JOIN   product AS p ON p.product_id = a.product_id
      JOIN  
            --- STORE COUNT BY PRODUCT
            (
             SELECT sub_p.product_id, COUNT(sl.store_location_id) AS store_count
             FROM sells AS sl
             JOIN product AS sub_p ON sl.product_id = sub_p.product_id
             GROUP BY sub_p.product_id
            ) AS agg_p 
        ON agg_p.product_id = p.product_id
      
      JOIN  
            --- STORE COUNT ACROSS ALL PRODUCTS
            (
             SELECT COUNT(sl.store_location_id) AS store_count
             FROM sells AS sl
             JOIN product AS sub_p ON sl.product_id = sub_p.product_id
            ) AS agg_s 
        ON agg_s.store_count = agg_p.store_count
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-17
        相关资源
        最近更新 更多