左联接多个子查询

时间:2020-10-13 17:58:08

标签: sql ms-access subquery left-join ms-access-2016

我的意图是为每个产品创建一个表,其中包含两个不同年份的订单数和收入。 我的想法是使用双左联接,但我不明白为什么该查询在MS ACCESS上不起作用。 我决定使用LEFT JOIN,因为每年在子查询中,如果未订购某些产品,则可能不会出现。 子查询a和b都可以。他们分开工作。 此查询有什么问题?

SELECT p.PK_Product_ID, a.[2013_Orders], a.[2013_Gross_Value], b.[2014_Orders], b.[2014_Gross_Value]
    FROM Products AS p

LEFT JOIN 
     (SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2013_Orders,  
     SUM((p.UnitPrice*od.Quantity)) AS 2013_Gross_Value
     FROM [Order Details] AS od, p, Orders AS o
     WHERE od.FK_Product_ID = p.PK_Product_ID
     AND od.FK_Order_ID = o.PK_Order_ID
     AND YEAR(o.OrderDate) = 2013
     GROUP BY p.PK_Product_ID) AS a

ON p.PK_Product_ID = a.Product_ID

LEFT JOIN 
    (SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2014_Orders,  SUM((p.UnitPrice*od.Quantity)) AS 2014_Gross_Value
    FROM od, p, o
    WHERE od.FK_Product_ID = p.PK_Product_ID
    AND od.FK_Order_ID = o.PK_Order_ID
    AND YEAR(o.OrderDate) = 2014
    GROUP BY p.PK_Product_ID) AS b
 ON p.PK_Product_ID = b.Product_ID;

3 个答案:

答案 0 :(得分:0)

此查询没有意义。您说子查询运行良好-但没有办法。尝试运行此查询

  Message    : ORA-00942: table or view does not exist
  ORA-06512: at line 16
  ORA-06512: at line 16

我希望它会给出一个错误,即“ p”不是表的名称。

也许你是这个意思?

 SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2013_Orders,  
 SUM((p.UnitPrice*od.Quantity)) AS 2013_Gross_Value
 FROM [Order Details] AS od, p, Orders AS o
 WHERE od.FK_Product_ID = p.PK_Product_ID
 AND od.FK_Order_ID = o.PK_Order_ID
 AND YEAR(o.OrderDate) = 2013
 GROUP BY p.PK_Product_ID

这意味着您可能想要这样的东西:

 SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2013_Orders,  
 SUM((p.UnitPrice*od.Quantity)) AS 2013_Gross_Value
 FROM [Order Details] AS od, Products as p, Orders AS o
 WHERE od.FK_Product_ID = p.PK_Product_ID
 AND od.FK_Order_ID = o.PK_Order_ID
 AND YEAR(o.OrderDate) = 2013
 GROUP BY p.PK_Product_ID

但是,我不会打扰两个子查询-甚至1个子查询-它只会使您变慢-这样做:

SELECT p.PK_Product_ID, a.[2013_Orders], a.[2013_Gross_Value], b.[2014_Orders], b.[2014_Gross_Value]
    FROM Products AS p

LEFT JOIN (
   SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2013_Orders, SUM((p.UnitPrice*od.Quantity)) AS 2013_Gross_Value
   FROM [Order Details] AS od
   JOIN Products as p ON od.FK_Product_ID = p.PK_Product_ID 
   JOIN Orders AS o ON od.FK_Order_ID = o.PK_Order_ID AND YEAR(o.OrderDate) = 2013
   GROUP BY p.PK_Product_ID         
) AS a ON p.PK_Product_ID = a.Product_ID

LEFT JOIN (
   SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2013_Orders, SUM((p.UnitPrice*od.Quantity)) AS 2013_Gross_Value
   FROM [Order Details] AS od
   JOIN Products as p ON od.FK_Product_ID = p.PK_Product_ID 
   JOIN Orders AS o ON od.FK_Order_ID = o.PK_Order_ID AND YEAR(o.OrderDate) = 2013
   GROUP BY p.PK_Product_ID         
) AS b ON p.PK_Product_ID = b.Product_ID;

请记住,在SQL中,您应该按组进行思考-第一组是订单...年份会晚些。

答案 1 :(得分:0)

您可以通过条件聚合来做到这一点:

SELECT p.PK_Product_ID AS Product_ID,
       SUM(IIF(YEAR(o.OrderDate) = 2013, 1, 0)) AS 2013_Orders,
       SUM(IIF(YEAR(o.OrderDate) = 2013, p.UnitPrice * od.Quantity, 0)) AS 2013_Gross_Value,
       SUM(IIF(YEAR(o.OrderDate) = 2014, 1, 0)) AS 2014_Orders,
       SUM(IIF(YEAR(o.OrderDate) = 2014, p.UnitPrice * od.Quantity, 0)) AS 2014_Gross_Value
FROM (Products AS p LEFT JOIN [Order Details] AS od ON od.FK_Product_ID = p.PK_Product_ID)
LEFT JOIN (SELECT * FROM Orders WHERE YEAR(OrderDate) IN (2013, 2014)) AS o ON od.FK_Order_ID = o.PK_Order_ID
GROUP BY p.PK_Product_ID

如果只希望订购2013年和/或2014年的产品,则可以将LEFT联接更改为INNER联接。

答案 2 :(得分:0)

为什么不通过单个查询手动交叉表样式运行。我仅在订单表中查询2013年1月1日至2015年1月1日之间的记录。这使我获得了两年内的所有订单,无论某个项目在一年之内还是在另一年都不开始销售。

现在,我正在基于IIF()执行sum()。如果订单的年份为2013,则将其总和分别应用1或0。 2014年的情况与此类似。每个结构和最终的列名都应该很明显。如果该记录不适用于该年份,则只需为零。对于总价值也一样,我恰好乘以适用的1或0。

唯一没有意义的是从产品表中获取单价。实际上,我本来会以为订单明细级会有价格,因为多年来价格明显波动,我将分别将2013年和2014年的价格与当前2020年费率数据库中的价格无关。因此,可能需要适当调整。

FROM arm32v7/ubuntu:latest

# this part so that tzdata does not ask for user input during the building process
ENV TZ=Europe/Kiev
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /root
RUN apt-get update
RUN apt-get install -y software-properties-common
RUN add-apt-repository ppa:deadsnakes/ppa
RUN apt-get update
RUN apt-get install -y build-essential git wget python3.6 python3.6-dev libpython3.6-dev
RUN wget --no-check-certificate https://dl.bintray.com/boostorg/release/1.74.0/source/boost_1_74_0.tar.gz
RUN git clone --recurse-submodules https://github.com/arvidn/libtorrent.git
ENV CPLUS_INCLUDE_PATH="${CPLUS_INCLUDE_PATH}:/usr/include/python3.6m"
RUN tar -xzf boost_1_74_0.tar.gz
WORKDIR /root/boost_1_74_0/tools/build
RUN ./bootstrap.sh
RUN cp src/engine/b2 /usr/local/bin/b2
ENV BOOST_ROOT=/root/boost_1_74_0/
ENV BOOST_BUILD_PATH=/root/boost_1_74_0/tools/build/
WORKDIR /root
RUN echo "using gcc : : : <cxxflags>-std=c++14 ;" > user-config.jam
RUN echo "using python : 3.6 : /usr/bin/python3.6 ;" >> user-config.jam
WORKDIR /root/libtorrent
RUN git checkout RC_1_2
WORKDIR /root/libtorrent/bindings/python
RUN b2 -j1 libtorrent-link=static boost-link=static stage_module