我有一个包含两个表的数据库-公司和报告。我想计算从q1(第1季度)到q2(第2季度)的变化。我尝试使用(以下)子查询,但随后主查询失败...
FROM
(SELECT revenue FROM reports WHERE quarter = 'q2' AND fiscal_year = 2018) AS q,
(SELECT revenue FROM reports WHERE quarter = 'q1' AND fiscal_year = 2017) AS lq
这里是DB Fiddle,可以帮助您了解问题和架构:
https://www.db-fiddle.com/f/eE8SNRojn45h7Rc1rPCEVN/4
当前的简单查询。
SELECT
c.name, r.quarter, r.fiscal_year, r.revenue, r.taxes, r.employees
FROM
companies c
JOIN
reports r
ON
r.company_id = c.id
WHERE
c.is_marked = 1;
预期结果(这是我所需要的):
+---------+----------+----------------+----------+--------------+-----------+------------------+
| Name | Revenue | Revenue_change | Taxes | Taxes_change | Employees | Employees_change |
+---------+----------+----------------+----------+--------------+-----------+------------------+
| ABC INC | 11056 | +54.77 | 35000.86 | -28.57% | 568 | -32 |
| XYZ INC | 5000 | null | null | null | 10 | +5 |
+---------+----------+----------------+----------+--------------+-----------+------------------+
非常感谢您帮助建立此查询。预先感谢。
答案 0 :(得分:5)
使用MySQL 8.0窗口函数:
WITH cte AS (
SELECT c.name, quarter, fiscal_year
,revenue,100*(revenue-LAG(revenue) OVER s)/NULLIF(revenue,0) AS change_revenue
,taxes,100*(taxes-LAG(taxes) OVER s)/NULLIF(taxes,0) AS change_taxes
,employees,employees-LAG(employees) OVER s AS change_employees
FROM companies c
JOIN reports r ON r.company_id = c.id
WINDOW s AS (PARTITION BY r.company_id ORDER BY fiscal_year, quarter)
)
SELECT *
FROM cte
WHERE quarter = 'Q2'; -- only to get specific quarter
-- comment this condition to get quarter to quarter comparison
答案 1 :(得分:3)
如果只需要比较两个季度,则可以用普通SQL进行。无需编程。
没有子查询,只需加入公司即可根据季度报告两次。
select
c.name,
r2.revenue,
100 * (r2.revenue - r1.revenue) / r2.revenue as revenue_change,
r2.taxes,
100 * (r2.taxes - r1.taxes) / r2.taxes as taxes_change,
r2.employees,
r2.employees - r1.employees as employees_change
from
companies c
LEFT JOIN reports r1 ON (c.id = r1.company_id and r1.quarter = 'q1')
LEFT JOIN reports r2 ON (c.id = r2.company_id and r2.quarter = 'q2')
答案 2 :(得分:2)
使用纯SQL很难获得结果。 但是我做到了。
执行以下sql。希望您对此SQL有所帮助。
select
qd2.name as Name,
qd2.Revenue as Revenue,
qd2.Revenue - qd1.Revenue as Revenue_Change,
qd2.Taxes as Taxes,
(qd2.Taxes - qd1.Taxes) * 100 / qd1.Taxes as Taxes_Change,
qd2.Employees as Employees,
(qd2.Employees - qd1.Employees) as Employees_Change
from
(
SELECT
(@cnt := @cnt + 1) AS rowNumber,
c.name as name,
r.revenue as Revenue,
r.taxes as Taxes,
r.employees as Employees
FROM
companies c
JOIN
reports r
CROSS JOIN (SELECT @cnt := 0) AS dummy
ON
r.company_id = c.id and
r.quarter = "q2"
order by name
) as qd2
JOIN
(
SELECT
(@cnt2 := @cnt2 + 1) AS rowNumber,
c.name as name,
r.revenue as Revenue,
r.taxes as Taxes,
r.employees as Employees
FROM
companies c
JOIN
reports r
CROSS JOIN (SELECT @cnt2 := 0) AS dummy
ON
r.company_id = c.id and
r.quarter = "q1"
order by name
) as qd1
ON qd1.rowNumber = qd2.rowNumber
结果如下
Name Revenue Taxes Employees Revenue_Change Taxes_Change Employees_Change
ABC INC 11056 35000.86 568 6056 -22.221798 -32
XYZ LLC 5000 null 10 null null 5
答案 3 :(得分:0)
我只使用一个联接和 group by 子句以及集合函数来实现这一目标。 pecentajes计算的最后一步是使用第一种方法的派生表:
SELECT
der.name, der.quarter, der.fiscal_year,
der.revenue,
100 * der.revenue_change / der.revenue AS revenue_change,
der.taxes,
100 * der.taxes_change / der.taxes AS taxes_change,
der.employees,
der.employees_change
FROM
(
/* First approach (with raw changes) */
SELECT
c.name,
MAX(r.quarter) AS quarter,
ANY_VALUE(r.fiscal_year) AS fiscal_year,
SUM(CASE WHEN r.quarter = "Q2" THEN r.revenue END) AS revenue,
IF (COUNT(r.revenue) = 2,
SUM(CASE WHEN r.quarter = "Q1" THEN (-1 * r.revenue) ELSE r.revenue END),
NULL) AS revenue_change,
SUM(CASE WHEN r.quarter = "Q2" THEN r.taxes END) AS taxes,
IF (COUNT(r.taxes) = 2,
SUM(CASE WHEN r.quarter = "Q1" THEN (-1 * r.taxes) ELSE r.taxes END),
NULL) AS taxes_change,
SUM(CASE WHEN r.quarter = "Q2" THEN r.employees END) AS employees,
IF (COUNT(r.employees) = 2,
SUM(CASE WHEN r.quarter = "Q1" THEN (-1 * r.employees) ELSE r.employees END),
NULL) AS employees_change
FROM
companies AS c
LEFT JOIN
reports AS r ON r.company_id = c.id AND r.quarter IN ("Q1","Q2")
GROUP BY
c.id
) AS der
您可以在下一个链接中查看到最终查询的进度:
https://www.db-fiddle.com/f/2tUC1gGJusVnXSyGhHGWc/3
概括查询
我对前面的查询进行了概括,以求对不同会计年度的季度进行比较,正如您在评论中所问的那样,这就是我的处理方式:
SET @q1Year = 2017;
SET @q2Year = 2018;
SET @q1 = "Q1" COLLATE utf8mb4_unicode_ci;
SET @q2 = "Q2" COLLATE utf8mb4_unicode_ci;
SELECT
der.name,
der.compared_quarters,
der.quarter,
der.fiscal_year,
der.revenue,
100 * der.revenue_change / der.revenue AS revenue_change,
der.taxes,
100 * der.taxes_change / der.taxes AS taxes_change,
der.employees,
der.employees_change
FROM
(
/* This query generate raw changes on revenue, taxes and employees */
SELECT
c.name,
CONCAT(@q1,"-",@q1Year," vs ",@q2,"-",@q2Year) AS compared_quarters,
@q2 AS quarter,
@q2Year AS fiscal_year,
SUM(IF(r.quarter = @q2, r.revenue, 0)) AS revenue,
IF (COUNT(r.revenue) = 2,
SUM(IF(r.quarter = @q1, -1 * r.revenue, r.revenue)),
NULL) AS revenue_change,
SUM(IF(r.quarter = @q2, r.taxes, 0)) AS taxes,
IF (COUNT(r.taxes) = 2,
SUM(IF(r.quarter = @q1, -1 * r.taxes, r.taxes)),
NULL) AS taxes_change,
SUM(IF(r.quarter = @q2, r.employees, 0)) AS employees,
IF (COUNT(r.employees) = 2,
SUM(IF(r.quarter = @q1, -1 * r.employees, r.employees)),
NULL) AS employees_change
FROM
companies AS c
LEFT JOIN
reports AS r ON r.company_id = c.id
AND
((r.quarter = @q1 AND r.fiscal_year = @q1Year) OR (r.quarter = @q2 AND r.fiscal_year = @q2Year))
GROUP BY
c.id
) AS der;
您可以在下一个链接上查看示例:
答案 4 :(得分:0)
我尝试了一下。这就是我要做的。
SELECT
c.name,
reportsQ2.quarter,
reportsQ2.revenue as revenu1,
reportsQ1.revenue as revenue2,
(COALESCE(reportsQ2.revenue, 0) - COALESCE(reportsQ1.revenue, 0)) as difference
FROM
reports as reportsQ2
LEFT JOIN
reports as reportsQ1 ON reportsQ1.company_id = reportsQ2.company_id
AND
reportsQ1.quarter = 'Q1'
LEFT JOIN
companies as c ON c.id = reportsQ2.company_id
WHERE
reportsQ2.quarter = 'Q2'
因此,我基本上首先选择了第二季度以来的所有报告。然后我以相同的公司ID加入了第一季度。
此时,您已经拥有进行计算所需的所有必要信息。我使用COALESCE()
来确保null值不会干扰输出null而不是有效数字的计算。
最后,我加入了companies
表以获取名称。
我对收入行进行了数学运算,并将其输出为difference
。
希望有帮助!
答案 5 :(得分:0)
它为我提供了所需的输出。
select
c.name,
r2.revenue,
concat(TRUNCATE(100 * (r2.revenue - r1.revenue) / r2.revenue,2),"%") as revenue_change,
r2.taxes,
concat(TRUNCATE( 100 * (r2.taxes - r1.taxes) / r2.taxes,2),"%") as taxes_change,
r2.employees,
r2.employees - r1.employees as employees_change
from
companies c
LEFT JOIN reports r1 ON (c.id = r1.company_id and r1.quarter = 'q1')
LEFT JOIN reports r2 ON (c.id = r2.company_id and r2.quarter = 'q2')
输出:
谢谢!