Sql 甲骨文合并两个选择与工会加起来
我有一个SQL:Sql 甲骨文合并两个选择与工会加起来,sql,oracle,select,union,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 custo
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,但它不起作用。我看不出你有任何理由使用UNION。试试这个,我刚刚删除了空值
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;
我看不出你有任何理由使用union。试试这个,我刚刚删除了空值
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;
可以拆分为两个视图并合并它们。 然后使用最合适的
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
可以拆分为两个视图并合并它们。 然后使用最合适的
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
扩展@VJHil的答案,就有可能摆脱
联盟。诀窍是使用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
这应该比任何两次访问数据的解决方案都要好。扩展@VJHil的答案,就有可能摆脱联合。诀窍是使用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
这应该比您两次访问数据的任何解决方案都要好。另一个简单的解决方案
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
另一个简单的解决方案
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
但是你为什么大喊大叫?但是你为什么大喊大叫?你好。谢谢,但总金额我需要该客户购买的总金额减去购买日期,总金额到日期我只需要在一段时间内购买的金额。您好。谢谢,但总金额我需要该客户购买的总金额减去购买日期,总金额到日期我只需要在一个时间间隔内购买的金额。进一步测试此解决方案,我发现当V2没有记录时(因为在时间间隔内没有购买),我没有记录。我会尝试一个外部连接。好,你也可以考虑艾伦的答案,因为它听起来更好我!除非你的表不是很大。进一步测试这个解决方案,我发现当V2没有记录时(因为在时间间隔内没有购买),我就没有记录。我会尝试一个外部连接。好,你也可以考虑艾伦的答案,因为它听起来更好我!除非你的表不是很大。我同意你的方法,你“忠实”于”他关于单位到日期和单位到日期的总和的原始条件。当然,对空值求和将导致空值。因此,我认为这在技术上是正确的,但我认为最终用户会希望使用零来代替零。@Patrick:在这种情况下,我倾向于使用null
而不是零,因为它同时适用于sum
和count
,所以它更实用。如果列为空时需要非空结果,则可以使用nvl
或coalesce
将其转换。我同意您的方法,并且您“忠实”于”他关于求和单位到日期和单位到日期的原始条件。当然,对空值求和将导致空值。因此,我认为这在技术上是正确的,但我认为最终用户会希望使用零来代替零。@Patrick:在这种情况下,我倾向于使用null
而不是零,因为它同时适用于sum
和count
,所以它更实用。如果列为空时需要非空结果,则可以使用nvl
或coalesce
对其进行转换。