我有这个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,但它不起作用。
答案 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