Отфильтровать таблицу перед применением правого соединения НА 3-Й ТАБЛИЦЕ

Использование 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

Хотите посмотреть, как выполнить сравнение в соединении, где я сравниваю первую таблицу с 3-й таблицей в соединении. см. закомментированный код --WHERE EFFECTIVEDATE <= 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 http://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

person Surya The Sun    schedule 28.02.2019    source источник
comment
Этот запрос все равно не будет работать, ORDER является зарезервированным ключевым словом, а имя объекта не заключено в кавычки. Лично я предлагаю использовать имя объекта, которое не является ключевым словом, оно только вызывает проблемы.   -  person Larnu    schedule 28.02.2019
comment
Прежде всего, пришло время начать использовать соединения в стиле ANSI-92. Они доступны уже более 25 лет. sqlblog.org/2009/10/ 08/bad-habits-to-kick-using-old-style-joins Также не рекомендуется использовать псевдонимы, которые имеют какое-то значение, T1, T2. sqlblog.org/2009/10/08/ Кроме того, вам следует избегать использования зарезервированных имен для объектов. Order — плохое название для таблицы.   -  person Sean Lange    schedule 28.02.2019
comment
Заказ изменен на SalesOrder. Псевдоним T1, T2 просто для удобства.   -  person Surya The Sun    schedule 28.02.2019
comment
Я подозреваю, что это можно значительно упростить, но не совсем уверен, что вы пытаетесь здесь сделать. Что вы ожидаете на выходе?   -  person Sean Lange    schedule 28.02.2019
comment
Псевдонимы удобны, а общие псевдонимы — нет. Они усложняют задачу, потому что вам приходится постоянно обращаться к псевдониму, чтобы понять, что он означает. В вашем запросе вместо T1, T2, T3 я бы использовал что-то вроде так, c и ca   -  person Sean Lange    schedule 28.02.2019
comment
Мне нужно получить весь заказ на продажу, соответствующее имя клиента и адрес. Здесь также должен быть указан SalesOrder 1003 для клиента 3 (в адресе клиента нет даты вступления в силу).   -  person Surya The Sun    schedule 28.02.2019
comment
В настоящее время адрес клиента не имеет значения, поскольку вы не включаете столбцы из этой таблицы. Так что начните сначала. Ваш запрос и заявленная вами цель просто не совпадают. Поймите свою цель ДО того, как начнете писать запрос. Напишите запрос по шагам. И правильное соединение с адресом не является частью вашего решения — это гарантия.   -  person SMor    schedule 28.02.2019
comment
Здесь приведены данные выборки, которые не содержат адресной информации. Чего вы пытаетесь достичь с помощью правильного соединения?   -  person Sean Lange    schedule 28.02.2019
comment
включил T3.STATE в оператор выбора. Просто выберите штат (для простоты не включает всю информацию об адресе)   -  person Surya The Sun    schedule 28.02.2019
comment
Используйте правильный JOIN. Он существует уже более 25 лет!   -  person Eric    schedule 28.02.2019
comment
Прежде чем публиковать сообщения об ошибках Google, прочитайте много ответов по многим причинам. Вы обнаружите, что проблема является часто задаваемым вопросом. Вы, вероятно, хотите CROSS JOIN, а не запятую. Запятая означает перекрестное соединение, но с более низким приоритетом, чем соединения с ключевым словом JOIN. Так что не смешивайте их, это сбивает с толку. Поскольку JOIN выполняется первым, T1 там неизвестен. Когда вы публикуете код, приведите минимально воспроизводимый пример. Этот код не является минимальным, вы можете сократить его, чтобы изолировать проблему.   -  person philipxy    schedule 28.02.2019
comment
Узнайте, что возвращает левое/правое соединение при возврате: внутреннее соединение строк плюс несопоставленные левые/правые строки таблицы, расширенные нулями. Всегда знайте, какое внутреннее соединение вы хотите использовать как часть внешнего соединения. Где это требует, чтобы правый/левый [sic] столбец таблицы не был нулевым после того, как левое/правое соединение удаляет все строки, расширенные нулями, т.е. оставляет только внутреннее соединение строк, т.е. превращает внешнее соединение во внутреннее соединение. У вас есть это. Это тоже часто задаваемые вопросы. Также, чтобы минимальный воспроизводимый пример был минимальным, вы должны добавить минимальный проблемный код в рабочий код. Так что давайте код, который вы показываете, делает то, что вы ожидаете, чтобы найти первое место, где вы ошибетесь.   -  person philipxy    schedule 28.02.2019
comment
Пожалуйста, уточните через правки, а не комментарии.   -  person philipxy    schedule 28.02.2019
comment
Еще проблемы: Ваше описание того, что вы хотите, настолько кратко, что неясно. Но если вы хотите, чтобы внешний joih содержал все заказы, тогда таблица со всеми заказами должна быть левой таблицей левого соединения или правой таблицей правого соединения.   -  person philipxy    schedule 01.03.2019
comment
@philipxy Есть 3 таблицы моделей с ожидаемым результатом, вы можете сформулировать свой запрос по-своему. Я пытался сделать внешнее соединение T4 с двумя разными таблицами T1 и T3, где соединение идет только с одной таблицей.   -  person Surya The Sun    schedule 01.03.2019
comment
Ваш последний комментарий тоже настолько лаконичен, что неясно. Используйте достаточно слов, предложений и ссылок на части примеров, чтобы точно сказать, что вы имеете в виду. Пожалуйста, действуйте в соответствии с моими предыдущими комментариями: используйте CROSS JOIN вместо запятой в FROM (я сказал вам, что вы теперь запрашиваете t1 cross join t2 cross join (t3 right join t4 on c); дайте небольшой код, который вы показываете, делает то, что вы ожидаете, и код, который представляет собой этот код, расширенный небольшим кодом проблемы; используйте слова, чтобы четко сказать, что вы хотите; уточнить через редактирование, а не комментарий.   -  person philipxy    schedule 02.03.2019
comment
Примеры таблиц, ожидаемый результат, Incomplete есть. Сформируйте свой собственный запрос с помощью JOIN, запятой и т. д. Здесь я объясню проблему подробнее. Необходимо выбрать все заказы на продажу и их имя клиента, а также адрес клиента. важной и сложной частью является изменение адреса клиента в зависимости от даты заказа на продажу. Здесь я объясню проблему подробнее. Необходимо выбрать все заказы на продажу и их имя клиента, а также адрес клиента. важной и сложной частью является изменение адреса клиента в зависимости от даты заказа на продажу.   -  person Surya The Sun    schedule 02.03.2019
comment
Это неясно, я не могу сказать, какой код должен что делать, или какой код работает или не работает с какими результатами, или какой код работал так, как вы ожидали, или какой наименьший код больше, чем с проблема. Используйте достаточно слов, предложений и ссылок на части примеров, чтобы точно сказать, что вы имеете в виду. Пожалуйста, уточните через правки, а не комментарии. И т. д. и т. д. Пожалуйста, реагируйте на все мои комментарии. (Предлагаю вам прекратить комментировать код.) PS Уведомления Google 'stackexchange, чтобы узнать, как использовать @x в комментарии, чтобы уведомить не единственного комментатора, не публикующего пост, о комментарии.   -  person philipxy    schedule 04.03.2019


Ответы (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 
person Krishna    schedule 28.02.2019
comment
Спасибо. EFFECTIVEDATE ‹= T1.ORDERDATE ошибки строки, так как не удалось найти составной идентификатор. - person Surya The Sun; 28.02.2019
comment
sqlfiddle.com/#!18/9eecb Создание таблиц для экспериментов с sql. - person Surya The Sun; 28.02.2019
comment
разверните свой запрос, чтобы написать правильные соединения, затем повторите попытку. это работает только в MS SQL Server - person Krishna; 28.02.2019