【问题标题】:Filter Table Before Applying Right Join ON 3RD TABLE在第三个表上应用右连接之前过滤表
【发布时间】:2019-02-28 16:21:44
【问题描述】:

使用 MSSQL:只是为了澄清

客户表

CustomerNumber Name
===================

1              David
2              Thomas
3              Mangold    
4              Issac
------------------------------------------------------------

客户地址表

CustomerNumber State EffectiveDate
==================================

1              AL    01/01/2017
1              VA    06/01/2017
1              GA    02/01/2018 
1              FL    10/01/2018
2              TX    01/01/2017
3              MA    
4              IL    04/01/2015

SalesOrder 表

CUSTOMER ORDERNo OrderDate
========================

1        1000   03/01/2017
2        1001   10/10/2017
1        1002   11/01/2017
3        1003   12/01/2017
4        1004   01/01/2018
1        1005   02/01/2018
1        1006   01/01/2019

我需要在订单日期获取所有带有客户详细信息和客户地址的订单。

SELECT T1.ORDERNo, T1.ORDERDATE, T1.CUSTOMER, T2.NAME, T3.STATE     
FROM SALESORDER  T1,  CUSTOMER T2, CUSTOMERADDRESS T3 
RIGHT JOIN(
   SELECT CUSTOMER, MAX(EFFECTIVEDATE) FROM CUSTOMERADDRESS
   --WHERE EFFECTIVEDATE <= T1.ORDERDATE
   GROUP BY CUSTOMER)T4 
   ON T3.CUSTOMER = T4.CUSTOMER AND T3.EFFECTIVEDATE=T4.EFFECTIVEDATE
WHERE T1.CUSTOMER = T2.CUSTOMERNUMBER
AND T1.CUSTOMER = T3.CUSTOMERNUMBER

想看看如何在连接中进行比较,我将第一个表与连接中的第三个表进行比较。见注释代码--WHERE EFFECTIVEDATE &lt;= T1.ORDERDATE

如果我删除注释代码,则连接中的表无法引用外部表。


预期的输出是:

 CUSTOMER ORDERNo       OrderDate     CustomerName State
 =============================================

 1        1000          03/01/2017    David        AL
 2        1001          10/10/2017    Thomas       TX
 1        1002          11/01/2017    David        VA
 3        1003          12/01/2017    Mangold      MA
 4        1004          01/01/2018    Issac        IL
 1        1005          02/01/2018    David        GA
 1        1006          01/01/2019    David        FL

sql fiddlehttp://sqlfiddle.com/#!18/9eecb中的表:

            CREATE TABLE Customer
                ('CustomerNumber' int, 'CustomerName' varchar(30))
            ;

            INSERT INTO Customer
                ('CustomerNumber', 'CustomerName')
            VALUES
                (1, 'David'),
                (2, 'Thomas'),
                (3, 'Mangold'),
                (4, 'Issac')
            ;

            CREATE TABLE CustomerAddress
                ('CustomerNumber' int, 'State' varchar(2), 'EffectiveDate' date)
            ;

            INSERT INTO CustomerAddress
                ('CustomerNumber', 'State', 'EffectiveDate')
            VALUES
                (1, 'AL', 01/01/2017),
                (1, 'VA', 06/01/2017),
                (1, 'GA', 02/01/2018), 
                (1, 'FL', 10/01/2018),
                (2, 'TX', 01/01/2017),
                (3, 'MA',),   
                (4, 'IL', 04/01/2015)
            ;

            CREATE TABLE SalesOrder 
                ('CUSTOMER' int, 'ORDERNO' int,  'OrderDate' Date)
            ;

            INSERT INTO SalesOrder
                ('CUSTOMER', 'ORDERNO', 'OrderDate')
            VALUES
                (1,        1000,   03/01/2017),
                (2,        1001,   10/10/2017),
                (1,        1002,   11/01/2017),
                (3,        1003,   12/01/2017),
                (4,        1004,   01/01/2018),
                (1,        1005,   02/01/2018),
                (1,        1006,   01/01/2019)
            ;

            CREATE TABLE CustomerAddress
                (`CustomerNumber` int, 'State' varchar(2), `EffectiveDate` date)
            ;

            INSERT INTO CustomerAddress
                (`CustomerNumber`, `State`, 'EffectiveDate')
            VALUES
                (1, 'AL', 01/01/2017),
                (1, 'VA', 06/01/2017),
                (1, 'GA', 02/01/2018), 
                (1, 'FL', 10/01/2018),
                (2, 'TX', 01/01/2017),
                (3, 'MA',),   
                (4, 'IL', 04/01/2015)
            ;

            CREATE TABLE SalesOrder 
                (`CUSTOMER` int, 'ORDERNO' int,  `OrderDate` Date)
            ;

            INSERT INTO SalesOrder
                (`CUSTOMER `, `ORDERNO`, 'OrderDate')
            VALUES
                (1,        1000,   03/01/2017),
                (2,        1001,   10/10/2017),
                (1,        1002,   11/01/2017),
                (3,        1003,   12/01/2017),
                (4,        1004,   01/01/2018),
                (1,        1005,   02/01/2018),
                (1,        1006,   01/01/2019)
            ;

'sql 服务器版本'

            CREATE TABLE Customer
                (CustomerNumber int, CustomerName varchar(30))
            ;


            INSERT INTO Customer
                (CustomerNumber, CustomerName)
            VALUES
                (1, 'David'),
                (2, 'Thomas'),
                (3, 'Mangold'),
                (4, 'Issac');               
            ;

            CREATE TABLE CustomerAddress
                (CustomerNumber int, State varchar(2), EffectiveDate date)
            ;

            INSERT INTO CustomerAddress
                (CustomerNumber, State, EffectiveDate)
            VALUES
                (1, 'AL', '01/01/2017'),
                (1, 'VA', '06/01/2017'),
                (1, 'GA', '02/01/2018'), 
                (1, 'FL', '10/01/2018'),
                (2, 'TX', '01/01/2017'),                    
                (4, 'IL', '04/01/2015')
            ;

            INSERT INTO CustomerAddress
                (CustomerNumber, State)
            VALUES
                (3, 'MA' )
            ;

            CREATE TABLE SalesOrder 
                (CUSTOMER int, ORDERNO int,  OrderDate Date)
            ;

            INSERT INTO SalesOrder
                (CUSTOMER, ORDERNO, OrderDate)
            VALUES
                (1,        1000,   '03/01/2017'),
                (2,        1001,   '10/10/2017'),
                (1,        1002,   '11/01/2017'),
                (3,        1003,   '12/01/2017'),
                (4,        1004,   '01/01/2018'),
                (1,        1005,   '02/01/2018'),
                (1,        1006,   '01/01/2019')
            ;

问题:需要选择所有销售订单及其客户名称和客户地址。重要且棘手的部分是客户地址更改基于销售订单的日期。

--不完整查询的修改版本

        SELECT T1.ORDERNo, T1.ORDERDATE, T1.CUSTOMER, T2.CustomerName, T3.STATE     
        FROM   CUSTOMER T2, SALESORDER  T1 INNER JOIN CUSTOMERADDRESS T3 ON T1.CUSTOMER = T3.CUSTOMERNUMBER
        RIGHT JOIN(
           SELECT CustomerNumber, MAX(EFFECTIVEDATE) as EffectiveDate4 FROM CUSTOMERADDRESS 
           --WHERE EFFECTIVEDATE < T1.ORDERDATE  
           GROUP BY CustomerNumber 
           --HAVING EFFECTIVEDATE < T1.ORDERDATE
           ) T4
           ON T3.CustomerNumber = T4.CustomerNumber AND T3.EFFECTIVEDATE=T4.EffectiveDate4
        WHERE T1.CUSTOMER = T2.CUSTOMERNUMBER

【问题讨论】:

  • 首先,是时候开始使用 ANSI-92 样式连接了。它们已经上市超过 25 年了。 sqlblog.org/2009/10/08/bad-habits-to-kick-using-old-style-joins 另外,使用具有某种含义的别名,T1、T2 不是一个好主意。 sqlblog.org/2009/10/08/… 此外,您应该避免为对象使用保留名称。 “订单”是一个糟糕的表格名称。
  • 我怀疑这可以大大简化,但不确定您在这里要做什么。你期望输出什么?
  • 别名很方便,但通用别名不方便。它们使事情变得更加困难,因为您必须不断地参考别名来弄清楚别名的含义。在您的查询而不是 T1、T2、T3 中,我会使用类似 c 和 ca 的东西
  • 正如当前发布的那样,customeraddress 无关紧要,因为您不包含该表中的任何列。所以重新开始。您的查询和您声明的目标根本不匹配。在开始编写查询之前了解您的目标。分步编写查询。正确加入地址不是您的解决方案的一部分 - 这是一种保证。
  • 这里给出的示例数据,不包含任何地址信息。你想通过正确的加入来完成什么?

标签: sql-server right-join


【解决方案1】:

OUTER APPLY 应该可以解决您的问题。根据您的需要,您可以更改您的查询。

SELECT T1.ORDERNo, T1.ORDERDATE, T1.CUSTOMER, T2.NAME, T3.STATE     
FROM SALESORDER  T1,  CUSTOMER T2, CUSTOMERADDRESS T3 
OUTER APPLY(
   SELECT CUSTOMER, MAX(EFFECTIVEDATE) FROM CUSTOMERADDRESS
   WHERE EFFECTIVEDATE <= T1.ORDERDATE
   AND T3.CUSTOMER = CUSTOMER )T4 
WHERE T1.CUSTOMER = T2.CUSTOMERNUMBER
AND T1.CUSTOMER = T3.CUSTOMERNUMBER
AND T3.EFFECTIVEDATE = T4.EFFECTIVEDATE 

【讨论】:

  • 谢谢。 EFFECTIVEDATE
  • sqlfiddle.com/#!18/9eecb 创建表以使用 sql。
  • 扩展您的查询以编写正确的连接,然后再试一次。这仅适用于 MS SQL Server
猜你喜欢
  • 2013-02-11
  • 1970-01-01
  • 2022-11-14
  • 2011-07-28
  • 2020-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多