简体   繁体   English

SQL:左外部联接,不同的GROUP BY,需要复制记录吗?

[英]SQL: Left Outer Join, different GROUP BY, need to replicate records ?

I have information about accounts in two tables (A, B). 我在两个表(A,B)中有关于帐户的信息。 The records in A are all unique at the account level (account_id), but in table B, accounts are identified by account_id and month_start_dt, so each account may exist in zero or more months. A中的记录在帐户级别(account_id)都是唯一的,但是在表B中,帐户由account_id和month_start_dt标识,因此每个帐户可能存在零个或更多个月。

The trouble is, when I left outer join A to B so the joined table contains all records from A with the records from B (by account, by month) any account that does not exist in table B for a given month does not have a record for that month. 问题是,当我将外部联接A留给B时,联接表包含A的所有记录和B的记录(按帐户,按月),在给定月份表B中不存在的任何帐户都没有记录该月。

Desired outcome: If an account does not exist in table B for a given month, create a record for that account in the joined table with month_start_dt and 0 for all variables being selected from B. 预期结果:如果表B在给定月份中不存在某个帐户,请在联接表中为该帐户创建一条记录,其中month_start_dt和0表示从B中选择的所有变量。

As it stands, I can get the join to work where all accounts not appearing in B (not appearing at all, in any month) have 0 values for all variables being selected from B (using nvl(variable, 0) ) but, these accounts only have a single record. 就目前而言,我可以使联接工作,其中所有未出现在B中的帐户(在任何月份都根本没有出现)对于从B中选择的所有变量都具有0值(使用nvl(variable,0)),但是,这些帐户只有一条记录。 They should have one for each month. 他们每个月应该有一个。

Create a temp table with number of records you want for not-existing rows and right join the result of first query. 创建一个临时表,其中包含所需的不存在的行数的记录,并右联接第一个查询的结果。

select tbl.* from ( select * from A left join B on a.col1 = b.col2) tbl join tmpTable on tbl.col2 = tmpTable.zerocol

try this. 尝试这个。

I don't see why you need an outer join. 我不明白为什么需要外部联接。 This uses Standard SQL's EXCEPT ( MINUS in Oracle): 这使用标准SQL的EXCEPT (在Oracle中为MINUS ):

SELECT account_id, month_start_dt, all_variables 
  FROM B
UNION
(
 SELECT account_id, month_start_dt, 0 AS all_variables
   FROM A 
        CROSS JOIN (
                    SELECT DISTINCT month_start_dt
                      FROM B
                   ) AS DT1
 EXCEPT 
 SELECT account_id, month_start_dt, 0 AS all_variables
   FROM B
);

You could use a tally Calendar table, with months (of several years). 您可以使用带有数月(数年)的理货日历表。 See this similar question: How to create a Calender table for 100 years in Sql 看到类似的问题: 如何在Sql中创建100年的日历表

And then have: 然后有:

FROM 
        A
    CROSS JOIN
        ( SELECT y
               , m
          FROM Calendar
          WHERE (   y = @start_year
                AND m >= @start_month
                )
             OR (   y > @start_year
                AND y < @end_year
                )
             OR (   y = @end_year
                AND m <= @end_month
                )
        ) AS C
    LEFT JOIN
        B
            ON  B.account_id = A.account_id
            AND YEAR(B.start_date) = C.y
            AND MONTH(B.start_date) = C.m

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM