Mysql 用其他列值替换列值
Mysql replace column value with other column value
我有 2 个 table:
table: transaction:
====================
id billed_date amount
1 2016-09-30 5
2 2016-10-04 15
3 2016-10-06 10
table: report_date
====================
transaction_id report_date
1 2016-10-01
我要:
- 创建一个汇总 2016 年 10 月所有交易金额的报告
- 基于报告日期,而不是开票日期
- 未设置报告日期时,以billed_date
为准
- 在上面的例子中,我想要的结果是 30(不是 25)
那我写:
第一个:
SELECT
sum(t.amount),
CASE WHEN d.report_date IS NOT NULL THEN d.report_date ELSE t.billed_date END AS new_date
FROM
transaction t LEFT JOIN report_date d ON t.id = d.transaction_id
WHERE new_date BETWEEN '2016-10-01' AND '2016-10-30'
第二个:
SELECT sum(amount) FROM
(SELECT t.amount,
CASE WHEN d.report_date IS NOT NULL THEN d.report_date ELSE t.billed_date END AS date
FROM transaction t LEFT JOIN report_date d ON t.id = d.transaction_id
) t
WHERE t.date BETWEEN '2016-10-01' AND '2016-10-30'
结果:
第一个:
- 'where clause'
中的未知列 'new_date'
- 如果我将 'new_date' 替换为 'date':结果 = 25(不包括 id=1)
第二个:
- result = 30 => 正确,但在我的例子中,当交易 table 有大约 30k 条记录时,这个过程太慢了。
有人可以帮助我吗?
是否用 table: transaction:
中缺失的值填充 table: report_date
?
SELECT id FROM report_date WHERE report_date BETWEEN '2016-10-01' AND '2016-10-30';
INSERT INTO report_date SELECT id, billed_date FROM transaction WHERE billed_date BETWEEN '2016-10-01' AND '2016-10-30' AND id NOT IN (ids_from previous_query);
SELECT sum(t.amount) FROM transaction LEFT JOIN report_date d ON (t.id = d.transaction_id) WHERE d.report_date BETWEEN '2016-10-01' AND '2016-10-30';
您的第二个查询是正确的,无需重新编写查询。但我有一件事要告诉你,这对你处理 thousand/millions 条记录有很大帮助。我们也关注其他一些事情。因为当您的 table 包含大量数据(成千上万)的记录时,执行查询需要时间。它也可能导致锁定,可能是查询锁定或数据库消失之类的问题。为避免此问题,您只需创建一列的 INDEX。在 where 子句上 act/use 的列上创建 INDEX。就像你的情况一样,你可以在 billed_date 列上创建 INDEX 来自 transaction table.因为你的结果是基于transactiontable。有关如何在 mysql/phpmyadmin 中创建 index 的更多详细信息,您可以参考此 http://www.yourwebskills.com/dbphpmyadmintable.php link。
我曾在某个时候遇到过同样的问题,然后我在列上创建了 INDEX。现在我正在使用 mysql 处理数百万条记录。
终于在小弟的帮助下找到了解决办法:
SELECT sum(amount)
FROM transaction t LEFT JOIN report_date d ON id = transaction_id
WHERE (report_date BETWEEN '2016-10-01' AND '2016-10-30') OR (report_date IS NULL AND billed_date BETWEEN '2016-10-01' AND '2016-10-30')
谢谢你对我的关心!
首先-部分
CASE WHEN d.report_date IS NOT NULL THEN d.report_date ELSE t.billed_date END
可以简写为
COALESCE(d.report_date, t.billed_date)
或作为
IFNULL(d.report_date, t.billed_date)
在您的第一个查询中,您在 WHERE 子句中使用了列别名,这是不允许的。您可以通过将别名后面的表达式移动到 WHERE 子句来修复它:
SELECT sum(t.amount)
FROM transaction t LEFT JOIN report_date d ON t.id = d.transaction_id
WHERE COALESCE(d.report_date, t.billed_date) BETWEEN '2016-10-01' AND '2016-10-30'
这和你自己的解决方案几乎一样。
您的第二个查询很慢,因为 MySQL 必须将子查询结果(30K 行)存储到临时 table 中。尝试对其进行优化,您最终会得到与上述相同的解决方案。
但是,如果您在 transaction.billed_date
和 report_date.report_date
上有索引,此查询仍然无法使用它们。为了使用索引,您可以将查询分成两部分:
带有报告的条目(将使用 report_date.report_date
索引):
SELECT sum(amount)
FROM transaction t JOIN report_date d ON id = transaction_id
WHERE d.report_date BETWEEN '2016-10-01' AND '2016-10-30'
没有报告的条目(将使用 transaction.billed_date
索引):
SELECT sum(amount)
FROM transaction t LEFT JOIN report_date d ON id = transaction_id
WHERE d.report_date IS NULL AND t.billed_dateBETWEEN '2016-10-01' AND '2016-10-30'
两个查询都可以使用索引。您只需要对结果求和,也可以结合两个查询来完成:
SELECT (
SELECT sum(amount)
FROM transaction t JOIN report_date d ON id = transaction_id
WHERE d.report_date BETWEEN '2016-10-01' AND '2016-10-30'
) + (
SELECT sum(amount)
FROM transaction t LEFT JOIN report_date d ON id = transaction_id
WHERE d.report_date IS NULL AND t.billed_dateBETWEEN '2016-10-01' AND '2016-10-30'
) AS sum_amount
我有 2 个 table:
table: transaction:
====================
id billed_date amount
1 2016-09-30 5
2 2016-10-04 15
3 2016-10-06 10
table: report_date
====================
transaction_id report_date
1 2016-10-01
我要:
- 创建一个汇总 2016 年 10 月所有交易金额的报告
- 基于报告日期,而不是开票日期
- 未设置报告日期时,以billed_date 为准
- 在上面的例子中,我想要的结果是 30(不是 25)
那我写:
第一个:
SELECT
sum(t.amount),
CASE WHEN d.report_date IS NOT NULL THEN d.report_date ELSE t.billed_date END AS new_date
FROM
transaction t LEFT JOIN report_date d ON t.id = d.transaction_id
WHERE new_date BETWEEN '2016-10-01' AND '2016-10-30'
第二个:
SELECT sum(amount) FROM
(SELECT t.amount,
CASE WHEN d.report_date IS NOT NULL THEN d.report_date ELSE t.billed_date END AS date
FROM transaction t LEFT JOIN report_date d ON t.id = d.transaction_id
) t
WHERE t.date BETWEEN '2016-10-01' AND '2016-10-30'
结果:
第一个:
- 'where clause' 中的未知列 'new_date'
- 如果我将 'new_date' 替换为 'date':结果 = 25(不包括 id=1)
第二个:
- result = 30 => 正确,但在我的例子中,当交易 table 有大约 30k 条记录时,这个过程太慢了。
有人可以帮助我吗?
是否用 table: transaction:
中缺失的值填充 table: report_date
?
SELECT id FROM report_date WHERE report_date BETWEEN '2016-10-01' AND '2016-10-30';
INSERT INTO report_date SELECT id, billed_date FROM transaction WHERE billed_date BETWEEN '2016-10-01' AND '2016-10-30' AND id NOT IN (ids_from previous_query);
SELECT sum(t.amount) FROM transaction LEFT JOIN report_date d ON (t.id = d.transaction_id) WHERE d.report_date BETWEEN '2016-10-01' AND '2016-10-30';
您的第二个查询是正确的,无需重新编写查询。但我有一件事要告诉你,这对你处理 thousand/millions 条记录有很大帮助。我们也关注其他一些事情。因为当您的 table 包含大量数据(成千上万)的记录时,执行查询需要时间。它也可能导致锁定,可能是查询锁定或数据库消失之类的问题。为避免此问题,您只需创建一列的 INDEX。在 where 子句上 act/use 的列上创建 INDEX。就像你的情况一样,你可以在 billed_date 列上创建 INDEX 来自 transaction table.因为你的结果是基于transactiontable。有关如何在 mysql/phpmyadmin 中创建 index 的更多详细信息,您可以参考此 http://www.yourwebskills.com/dbphpmyadmintable.php link。
我曾在某个时候遇到过同样的问题,然后我在列上创建了 INDEX。现在我正在使用 mysql 处理数百万条记录。
终于在小弟的帮助下找到了解决办法:
SELECT sum(amount)
FROM transaction t LEFT JOIN report_date d ON id = transaction_id
WHERE (report_date BETWEEN '2016-10-01' AND '2016-10-30') OR (report_date IS NULL AND billed_date BETWEEN '2016-10-01' AND '2016-10-30')
谢谢你对我的关心!
首先-部分
CASE WHEN d.report_date IS NOT NULL THEN d.report_date ELSE t.billed_date END
可以简写为
COALESCE(d.report_date, t.billed_date)
或作为
IFNULL(d.report_date, t.billed_date)
在您的第一个查询中,您在 WHERE 子句中使用了列别名,这是不允许的。您可以通过将别名后面的表达式移动到 WHERE 子句来修复它:
SELECT sum(t.amount)
FROM transaction t LEFT JOIN report_date d ON t.id = d.transaction_id
WHERE COALESCE(d.report_date, t.billed_date) BETWEEN '2016-10-01' AND '2016-10-30'
这和你自己的解决方案几乎一样。
您的第二个查询很慢,因为 MySQL 必须将子查询结果(30K 行)存储到临时 table 中。尝试对其进行优化,您最终会得到与上述相同的解决方案。
但是,如果您在 transaction.billed_date
和 report_date.report_date
上有索引,此查询仍然无法使用它们。为了使用索引,您可以将查询分成两部分:
带有报告的条目(将使用 report_date.report_date
索引):
SELECT sum(amount)
FROM transaction t JOIN report_date d ON id = transaction_id
WHERE d.report_date BETWEEN '2016-10-01' AND '2016-10-30'
没有报告的条目(将使用 transaction.billed_date
索引):
SELECT sum(amount)
FROM transaction t LEFT JOIN report_date d ON id = transaction_id
WHERE d.report_date IS NULL AND t.billed_dateBETWEEN '2016-10-01' AND '2016-10-30'
两个查询都可以使用索引。您只需要对结果求和,也可以结合两个查询来完成:
SELECT (
SELECT sum(amount)
FROM transaction t JOIN report_date d ON id = transaction_id
WHERE d.report_date BETWEEN '2016-10-01' AND '2016-10-30'
) + (
SELECT sum(amount)
FROM transaction t LEFT JOIN report_date d ON id = transaction_id
WHERE d.report_date IS NULL AND t.billed_dateBETWEEN '2016-10-01' AND '2016-10-30'
) AS sum_amount