2015-10-19 5 views
0

У меня есть две таблицы продуктов, которые связаны друг с другом, и третью несвязанную таблицу периодов, которую я хочу использовать, чтобы убедиться, что я получаю полный набор возвращаемых данных.Объединение двух таблиц с третьей несвязанной таблицей

Я не хочу хранить все пустые периоды для каждого продукта, только периоды, которые получают продажу.

Во-первых, мы имеем финансовых показателей таблицы, которая является «хозяином» всех периодов:

ID | PERIOD 
------------ 
1 | Jan 
2 | Feb 
3 | Mar 

Затем продукт и таблицы продаж

ID | Code 
------------ 
1 | ABC 
2 | XYZ 

Product_ID | Period_ID | Sales 
------------------------------ 
    1  |  1  | 5 
    2  |  1  | 4 
    2  |  3  | 7 

Я хотел бы сформулировать запрос чтобы я мог возвращать результаты за каждый из периодов, независимо от того, имеют ли они продажи или нет:

Product_ID | Product_Code | Period_ID | Period_Name | Sales 
----------------------------------------------------------- 
    1  |  ABC  |  1  | Jan  | 5 
    1  |  ABC  |  2  | Feb  | 0 
    1  |  ABC  |  3  | Mar  | 0 
    2  |  XYZ  |  1  | Jan  | 4 
    2  |  XYZ  |  2  | Feb  | 0 
    2  |  XYZ  |  3  | Mar  | 7 

Мне нужен запрос как можно более общий, он должен работать с Firebird (1.5) и MS SQL. Если это невозможно, то MS SQL является предпочтительным.

В дополнение к этому, если в таблице продаж в течение периода было более 1 записи, может ли суммирование суммироваться? то есть:

Product_ID | Period_ID | Sales 
------------------------------ 
    1  |  1  | 1 
    1  |  1  | 1 

вернуть бы

Product_ID | Period_ID | Sales 
------------------------------ 
    1  |  1  | 4 

для этой конкретной линии.

Я попытался сделать соединение, но я не вижу, как заставить его присоединиться к информации из таблицы периодов для каждого продукта.

ответ

0

Вы должны CROSS JOINFinancial стола и Product стола первых, чтобы получить все возможные комбинации периода и продукта. Затем сделать LEFT JOIN и SUM на Sales, чтобы получить желаемый результат:

SQL Fiddle

SELECT 
    p.ID AS Product_ID, 
    p.Code AS Product_Code, 
    f.ID AS Period_ID, 
    f.Period AS Period_ID, 
    SUM(COALESCE(s.Sales, 0)) AS Sales 
FROM Financials f 
CROSS JOIN Product p 
LEFT JOIN Sales s 
    ON s.Period_ID = f.ID 
    AND s.Product_ID = p.ID 
GROUP BY 
    p.ID, p.Code, f.ID, f.Period 
ORDER BY 
    p.ID, f.ID 
+0

Спасибо, это работает для MS SQL. У Firebird 1.5 нет команды CROSS JOIN, есть ли более агностический способ сделать это? Кроме того, что было бы лучшей оптимизацией индекса для этого, он работает довольно медленно в первый раз. – Darren

+1

Вместо 'CROSS JOIN' try:' FROM Financials f, Product p'. –

+1

Или 'FROM Financials f INNER JOIN Продукт p ON 1 = 1' –

0

Используйте левое соединение. Что-то вроде

SELECT a.*, b.* FROM master AS a LEFT JOIN sales AS b ON (a.Period_ID = b.Period_ID) 
+0

К сожалению, это только соединяет таблицу продукции и продаж и игнорирует пропущенные периоды. – Darren

Смежные вопросы