One row per period for the given account_no when it has data
As explained in the comments, your RDBMS is naturally built to do aggregates thanks to the GROUP BY keyword. So GROUP BY period so that one row is output (with the Sum() of matching rows) per different period, as intended:
INSERT INTO #financials
SELECT Concat(period, '_a'),
period,
Coalesce(Sum(credit), 0) - Coalesce(Sum(debit), 0)
FROM accounting_balance
WHERE period LIKE '2025%'
AND account_no = '4000-001-01'
GROUP BY period;
| id |
period |
income |
| 202501_a |
202501 |
50528.55 |
| 202502_a |
202502 |
601475.70 |
One row per period, filtering data only for a given account_no
If you want to output every period, even those where account 4000-001-01 has now debit nor credit, but limit the income to those for this account, instead of filtering on the whole query (in the global WHERE) you'll use a conditional aggregate: Sum(CASE WHEN account_no = '4000-001-01' THEN credit END).
Then only debit and credit of rows for account 4000-001-01 will be accounted for.
INSERT INTO #financials
SELECT Concat(period, '_a'),
period,
Sum(CASE WHEN account_no = '4000-001-01' THEN Coalesce(credit, 0) - Coalesce(debit, 0) END)
FROM accounting_balance
WHERE period LIKE '2025%'
GROUP BY period;
For example, if 4000-001-01 has only balance in January and February but not in March, you'll get:
| id |
period |
income |
| 202501_a |
202501 |
50528.55 |
| 202502_a |
202502 |
601475.70 |
| 202503_a |
202503 |
null |
(everything is shown in a db<>fiddle)
Risky cut and paste
… OK, if you only want to paste columns of unrelated tables next to each other, you'll have to ask each row its position thanks to the row_number() window function, and join on matching positions.
You'll probably get totally unexpected results as some rowsets will have less entries than others, but that's the result of trying to use an RDBMS (with an R as "Relational") to do spreadsheet-like works over unRelated data.
WITH
--create the ids
t1 AS
(
SELECT Concat(period, '_a') id,
row_number() over (order by period) as pos
FROM accounting_balance
WHERE period LIKE '2025%'
),
--get 1st column
t2 AS
(
SELECT period,
row_number() over (order by period) as pos
FROM accounting_balance
WHERE period LIKE '2025%'
),
--get 2nd column
t3 AS
(
SELECT Abs(Sum(Coalesce(credit, 0) - Coalesce(debit, 0))) income,
row_number() over (order by period) as pos
FROM accounting_balance
WHERE account_no = '4000-001-01'
GROUP BY period
)
INSERT INTO #financials
(id,
period,
income)
SELECT id, period, income
FROM t1
JOIN t2 ON t2.pos = t1.pos
JOIN t3 ON t3.pos = t1.pos
;
| id |
period |
income |
| 202501_a |
202501 |
50528.55 |
| 202501_a |
202501 |
601475.70 |
Wait… 202501 for both rows? Yes, because I had multiple rows for January in my example table, so t1 and t2 started with 3 rows in January, while the matching rows in t3 (the aggregated table for sums by month) gave 1 row per month. So now for row 2 of the 3 tables you've got February's total amount associated with the second row from accounting_balance, which happens to be in January.
(show as last query in the augmented fiddle)
#financialstemp table, why not just run the unionedSELECTby itself? Also why isperiodavarcharcolumn and not adatecolumn?UNIONat all. Once you have unioned, you will need to re-merge (let's say with a self join of yourUNION-generated table). Then how would you tell which row to join to which row? Of course you could tell it to put 1 non-null column 1 with first non-null column 2 with first non-null column 3 (and so on for second, third, etc., thanks to window functions) but this would be very fragile. So do it in 1 query where columns are related to the same row from the beginning.