【问题标题】:Joining 6 tables into single query?将 6 个表加入单个查询?
【发布时间】:2013-01-09 16:43:28
【问题描述】:

嘿,谁能帮我将下面的 5 个表加入到一个查询中?我目前有下面的查询,但似乎没有工作,好像在招聘表中有两个具有相同 ID 的产品所有产品都是从产品表返回的,这显然是错误的。

SELECT products.prod_id, products.title, products.price, product_types.name,  
listagg(suppliers.name, ',') WITHIN GROUP(ORDER BY suppliers.name) suppliers
FROM products 
INNER JOIN product_suppliers ON products.prod_id = product_suppluer.prod_id 
INNER JOIN product_types ON product_types.type_id = products.type_id 
INNER JOIN suppliers ON product_suppliers.supp_id = suppliers.supp_id 
LEFT OUTER JOIN hires ON hires.prod_id = products.prod_id 
    WHERE (hires.hire_end < to_date('21-JAN-13') OR hires.hire_start > to_date('26-JAN-13')) 
    OR hires.prod_id IS NULL 
GROUP BY products.prod_id, products.title, products.price, product_types.name

表格数据:

PRODUCTS                 
--------------------------------------------
| Prod_ID  | Title   | Price   | Type_ID   |
|------------------------------------------|
| 1        | A       | 5       | 1         |
| 2        | B       | 7       | 1         |
| 3        | C       | 3       | 2         |
| 4        | D       | 3       | 3         |
|------------------------------------------|

PRODUCT_TYPES                 
----------------------
| Type_ID  | Type    |
|--------------------|
| 1        | TYPE_A  |
| 2        | TYPE_B  |
| 3        | TYPE_C  |
| 4        | TYPE_D  |
|--------------------|

PRODUCT_SUPPLIERS                 
-------------------------
| Prod_ID  | Supp_ID    |
|-----------------------|
| 1        | 1          |
| 1        | 2          |
| 2        | 2          |
| 3        | 3          |
| 4        | 4          |
|-----------------------|

SUPPLIERS                 
----------------------
| Supp_ID  | Name    |
|--------------------|
| 1        | SUPP_A  |
| 2        | SUPP_B  |
| 3        | SUPP_C  |
| 4        | SUPP_D  |
|--------------------|

HIRES                
---------------------------------------------------------------
| Hire_ID  | Prod_ID    | Cust_ID    | Hire_Start | Hire_End  |
|-----------------------|------------|------------------------|
| 1        | 1          | 1          | 22-Jan-13  | 23-Jan-13 |
| 2        | 2          | 2          | 27-Jan-13  | 29-Jan-13 |
| 3        | 1          | 3          | 30-Jan-13  | 31-Jan-13 |
|-----------------------|------------|------------|-----------|

PRODUCTS                 
--------------------------------
| Cust_ID  | Name    | Phone   |
|------------------------------|
| 1        | Cust_A  | 555-666 |
| 2        | Cust_B  | 444-234 |
| 3        | Cust_C  | 319-234 |
| 4        | Cust_D  | 398-092 |
|------------------------------|

此时查询的输出如下所示:

-------------------------------------------------------------
| Prod_ID  | Title   | Price   | Type_ID   | Suppliers      |
|------------------------------------------|----------------|
| 1        | A       | 5       | Type_A    | SUPP_A,SUPP_B |
| 2        | B       | 7       | Type_B    | SUPP_B         |
| 3        | C       | 3       | Type_C    | SUPP_C         |
| 4        | D       | 3       | Type_D    | SUPP_D         |
|------------------------------------------|----------------|

什么时候它应该看起来像这样?因为 Prod_ID '1' 在查询中的日期之间被租用

-------------------------------------------------------------
| Prod_ID  | Title   | Price   | Type_ID   | Suppliers      |
|------------------------------------------|----------------|
| 2        | B       | 7       | Type_B    | SUPP_B         |
| 3        | C       | 3       | Type_C    | SUPP_C         |
| 4        | D       | 3       | Type_D    | SUPP_D         |
|------------------------------------------|----------------|

如果有人可以按照建议将查询修改为输出,我将不胜感激。因为我的理解是它应该像写的那样工作?

【问题讨论】:

  • 您有 2 个PRODUCTS 表。怎么样?
  • 2 个产品表出错,抱歉修改了

标签: sql oracle join oracle11g


【解决方案1】:

您的问题是 Prod_Id 1 在这些日期范围之内和之外。因此,改为使用子查询过滤掉哪些 Prod_Id 在这些范围内,并排除那些。

这是您查询的一个非常简化的版本:

SELECT P.Prod_ID
FROM Products P 
 LEFT JOIN (
   SELECT Prod_ID 
   FROM Hires
   WHERE hire_end >= To_Date('20130121', 'yyyymmdd') AND hire_start <= To_Date('20130126', 'yyyymmdd')
   ) H ON P.Prod_ID = H.Prod_ID
WHERE h.prod_id IS NULL

还有SQL Fiddle

假设我正确复制和粘贴,这应该是您的查询:

SELECT products.prod_id, products.title, products.price, product_types.name,  
listagg(suppliers.name, ',') WITHIN GROUP(ORDER BY suppliers.name) suppliers
FROM products 
INNER JOIN product_suppliers ON products.prod_id = product_suppluer.prod_id 
INNER JOIN product_types ON product_types.type_id = products.type_id 
INNER JOIN suppliers ON product_suppliers.supp_id = suppliers.supp_id 
LEFT JOIN (
   SELECT Prod_ID 
   FROM Hires
   WHERE hire_end >= To_Date('20130121', 'yyyymmdd') AND hire_start <= To_Date('20130126', 'yyyymmdd')
   ) H ON products.Prod_ID = H.Prod_ID
WHERE H.Prod_ID IS NULL
GROUP BY products.prod_id, products.title, products.price, product_types.name

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您的左外连接将在没有匹配项时返回空值,这意味着当此连接查询的结果为 Null 时,您仍然有一行(没有 HIRE 表数据):

    LEFT OUTER JOIN hires ON hires.prod_id = products.prod_id 
    WHERE (hires.hire_end < to_date('21-JAN-13') 
    OR hires.hire_start > to_date('26-JAN-13')) 
    OR hires.prod_id IS NULL
    

    尝试从招聘表中添加一个选择(例如hire.Hire_Start)以查看此情况,然后将其切换为内部连接,我认为您的问题将得到解决。

    或在完整查询中添加 WHERE 子句,例如 hire.Hire_Start is not null

    编辑

    如果您将原始查询更改为:

    SELECT hires.Hire_Start, products.prod_id, products.title, products.price, product_types.name,  
    listagg(suppliers.name, ',') WITHIN GROUP(ORDER BY suppliers.name) suppliers
    FROM products 
    INNER JOIN product_suppliers ON products.prod_id = product_suppluer.prod_id 
    INNER JOIN product_types ON product_types.type_id = products.type_id 
    INNER JOIN suppliers ON product_suppliers.supp_id = suppliers.supp_id 
    LEFT OUTER JOIN hires ON hires.prod_id = products.prod_id 
        WHERE (hires.hire_end < to_date('21-JAN-13') OR hires.hire_start > to_date('26- JAN-13')) 
        OR hires.prod_id IS NULL 
    GROUP BY products.prod_id, products.title, products.price, product_types.name
    

    Hire_Start 列中返回了什么?

    那么如果你将它添加到 where 子句中,你会得到预期的结果:

    SELECT hires.Hire_Start, products.prod_id, products.title, products.price, product_types.name,  
    listagg(suppliers.name, ',') WITHIN GROUP(ORDER BY suppliers.name) suppliers
    FROM products 
    INNER JOIN product_suppliers ON products.prod_id = product_suppluer.prod_id 
    INNER JOIN product_types ON product_types.type_id = products.type_id 
    INNER JOIN suppliers ON product_suppliers.supp_id = suppliers.supp_id 
    LEFT OUTER JOIN hires ON hires.prod_id = products.prod_id 
        WHERE (hires.hire_end < to_date('21-JAN-13') OR hires.hire_start > to_date('26- JAN-13')) 
        OR hires.prod_id IS NULL 
    WHERE hires.Hire_Start is not null
    GROUP BY products.prod_id, products.title, products.price, product_types.name
    

    最后,完全放弃外连接,这是否按预期工作?

    SELECT hires.Hire_Start, products.prod_id, products.title, products.price, product_types.name,  
    listagg(suppliers.name, ',') WITHIN GROUP(ORDER BY suppliers.name) suppliers
    FROM products 
    INNER JOIN product_suppliers ON products.prod_id = product_suppluer.prod_id 
    INNER JOIN product_types ON product_types.type_id = products.type_id 
    INNER JOIN suppliers ON product_suppliers.supp_id = suppliers.supp_id 
    INNER JOIN hires ON hires.prod_id = products.prod_id 
        WHERE (hires.hire_end < to_date('21-JAN-13') OR hires.hire_start > to_date('26- JAN-13'))
    GROUP BY products.prod_id, products.title, products.price, product_types.name
    

    请注意:OR Hires.prod_ID 是否旨在表明如果结果没有返回可用的雇用信息,在这种情况下,您需要编写查询更像提供的其他答案。

    【讨论】:

    • 您好,感谢您的回复。抱歉,当您说从招聘表中添加选择并将其更改为内部联接时,我不太明白您的意思
    【解决方案3】:

    下面是一些可能对您有所帮助的代码:

    SELECT L.V_PRODUCT_ID  "PROD_ID"   , L.TITLE "TITLE" , L.PRICE "PRICE"  , L.TYPE "TYPE" , S.NAME "SUPPLIERS"
    FROM 
    
    (SELECT V_PRODUCT_ID   , TITLE , PRICE , TYPE , SUPPLIER_ID FROM 
    
    ((select p.prod_id  v_product_id , p.title  TITLE , p.price PRICE  , t.type  TYPE
    from products p , products_types t 
    where p.type_id = t_type_id)   A 
    
    JOIN
     (SELECT PROD_ID  VV_PRODUCT_ID  ,  SUPP_ID  SUPPLIER_ID  
    FROM  PRODUCTS_SUPPLIERS)  H 
    
    ON (A.V_PRODUCT_ID  = H.VV_PRODUCT_ID)))   L
    JOIN 
    SUPLLIERS  S 
    ON (L.SUPPLIER_ID = S.SUPP_ID);
    

    【讨论】:

      【解决方案4】:

      选择 Emp.Empid、Emp.EmpFirstName、Emp.EmpLastName、Dept.DepartmentName 来自雇员雇员 INNER JOIN部门 ON Emp.Departmentid=Dept.Departmenttid

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-24
        • 2011-12-03
        • 1970-01-01
        相关资源
        最近更新 更多