ORACLE合并两个SELECT与UNION加起来

时间:2014-06-06 19:41:07

标签: sql oracle select union

我有这个SQL:

SELECT 
c.customer_code,                           
SUM(units) AS tot_units,
SUM(total_amount) AS tot_money,
null as units_to_date,
null as amount_to_date,
FROM customers c
join transactions t on t.customer_code = c.customer_code
WHERE customer_active='S'
GROUP BY c.customer_code
UNION
SELECT 
c.customer_code,               
null AS tot_units,
null AS tot_money,
SUM(units) as units_to_date,
SUM(total_amount) as amount_to_date, 
FROM customers c
join transactions t on t.customer_code = c.customer_code
WHERE customer_active='S' and t.transaction_date >= (trunc(current_date) - (60 * INTERVAL '1' DAY))
GROUP BY c.customer_code;

结果是:

CUSTOMER_CODE, TOT_UNITS, TOT_AMOUNT, TO_DATE_UNITS, TO_DATE_AMOUNT
0000001        450        300         null           null          
0000001        null       null        30             15        

我需要的结果是:

CUSTOMER_CODE, TOT_UNITS, TOT_AMOUNT, TO_DATE_UNITS, TO_DATE_AMOUNT
0000001        450        300         30             15        

我尝试使用UNION,但它不起作用。

4 个答案:

答案 0 :(得分:2)

可以拆分为两个视图并加入它们。 然后使用最适合的NVL()MAX()

WITH V1 AS (
SELECT 
c.customer_code,                           
SUM(units) AS tot_units,
SUM(total_amount) AS tot_money,
null as units_to_date,
null as amount_to_date,
FROM customers c
join transactions t on t.customer_code = c.customer_code
WHERE customer_active='S'
GROUP BY c.customer_code
),
V2 AS (
SELECT 
c.customer_code,               
null AS tot_units,
null AS tot_money,
SUM(units) as units_to_date,
SUM(total_amount) as amount_to_date, 
FROM customers c
join transactions t on t.customer_code = c.customer_code
WHERE customer_active='S' and t.transaction_date >= (trunc(current_date) - (60 * INTERVAL '1' DAY))
GROUP BY c.customer_code)
SELECT 
 V1.CUSTOMER_CODE, NVL(V1.TOT_UNITS,V2. TOT_UNITS), NVL(V1.TOT_AMOUNT,V2. TOT_AMOUNT), NVL(V1.TO_DATE_UNITS,V2. TO_DATE_UNITS) TO_DATE_AMOUNT
FROM V1, V2
WHERE V1.CUSTOMER_CODE = V2.CUSTOMER_CODE

答案 1 :(得分:2)

扩展@ VJHil的答案, 可以摆脱union。诀窍是使用case过滤掉所需日期范围之外的所有内容:

SELECT   c.customer_code,
         SUM (units) AS tot_units,
         SUM (total_amount) AS tot_money,
         SUM (
            CASE
               WHEN t.transaction_date >=
                       (TRUNC (CURRENT_DATE) - (60 * INTERVAL '1' DAY)) THEN
                  units
               ELSE
                  NULL
            END)
            AS units_to_date,
         SUM (
            CASE
               WHEN t.transaction_date >=
                       (TRUNC (CURRENT_DATE) - (60 * INTERVAL '1' DAY)) THEN
                  total_amount
               ELSE
                  NULL
            END)
            AS amount_to_date
FROM     customers c JOIN transactions t ON t.customer_code = c.customer_code
WHERE    customer_active = 'S'
GROUP BY c.customer_code

这应该比您访问数据两次的任何解决方案都要好。

答案 2 :(得分:0)

我认为你没有理由使用工会。试试这个,我只是删除了空值。

SELECT 
c.customer_code,               
SUM(units) AS tot_units,
SUM(total_amount) AS tot_money,
SUM(units) as units_to_date,
SUM(total_amount) as amount_to_date, 
MIN(transaction_date) AS first_transaction_date
FROM customers c
join transactions t on t.customer_code = c.customer_code
WHERE customer_active='S' and t.transaction_date >= (trunc(current_date) - (60 * INTERVAL '1' DAY))
GROUP BY c.customer_code;

答案 3 :(得分:0)

另一个简单的解决方案;

WITH CUSTOMER AS (
  SELECT C.CUSTOMER_CODE,
         SUM(UNITS) AS TOT_UNITS,
         SUM(TOTAL_AMOUNT) AS TOT_MONEY,
         NULL AS UNITS_TO_DATE,
         NULL AS AMOUNT_TO_DATE,
    FROM CUSTOMERS C JOIN TRANSACTIONS T ON T.CUSTOMER_CODE = C.CUSTOMER_CODE
   WHERE CUSTOMER_ACTIVE = 'S'
GROUP BY C.CUSTOMER_CODE
UNION
  SELECT C.CUSTOMER_CODE,
         NULL AS TOT_UNITS,
         NULL AS TOT_MONEY,
         SUM(UNITS) AS UNITS_TO_DATE,
         SUM(TOTAL_AMOUNT) AS AMOUNT_TO_DATE,
    FROM CUSTOMERS C JOIN TRANSACTIONS T ON T.CUSTOMER_CODE = C.CUSTOMER_CODE
   WHERE     CUSTOMER_ACTIVE = 'S'
         AND T.TRANSACTION_DATE >= (TRUNC(CURRENT_DATE) - (60 * INTERVAL '1' DAY))
GROUP BY C.CUSTOMER_CODE)
    SELECT CUSTOMER_CODE,
           MAX(TOT_UNITS) AS TOT_UNITS,
           MAX(TOT_MONEY) AS TOT_MONEY,
           MAX(UNITS_TO_DATE) AS UNITS_TO_DATE,
           MAX(AMOUNT_TO_DATE) AS AMOUNT_TO_DATE
      FROM CUSTOMER
  GROUP BY CUSTOMER_CODE