full outer join with group by query - sql

Calculate profit of company by month, profit of company calculated like this:
sum of incoming minus outgoing.
Tables:
incoming(amount, month)
outgoing(amount, month)
Data types:
month integer, ranges 1-12
amount integer
I tried
SELECT month,tsum-bsum FROM
(SELECT month,SUM(amount) tsum FROM incoming GROUP BY month
FULL OUTER JOIN
(SELECT month,SUM(amount) bsum FROM outgoing GROUP BY month)
)
ON incoming.month=outgoing.month;
but month can be null after joining which will cause problem with tsum-bsum.

Use coalesce():
SELECT coalesce(i.month, o.month) as month, i.tsum - o.bsum
FROM (SELECT month, SUM(amount) as tsum FROM incoming GROUP BY month) i
FULL OUTER JOIN
(SELECT month, SUM(amount) as bsum FROM outgoing GROUP BY month) o
ON i.month = o.month;
Note that the difference may be NULL if either value is NULL, so you may want:
SELECT coalesce(i.month, o.month) as month,
coalesce(i.tsum, 0) - coalesce(o.bsum, 0) as diff
FROM (SELECT month, SUM(amount) as tsum FROM incoming GROUP BY month) i
FULL OUTER JOIN
(SELECT month, SUM(amount) as bsum FROM outgoing GROUP BY month) o
ON i.month = o.month;

here is sample query
SELECT COALESCE(in.month, out.month) as month, sum(COALESCE(in.amount,0) - COALESCE(out.amount,0)) as profit
FROM
incoming as in
FULL OUTER JOIN
outgoing as out
ON in.month = out.month;
GROUP BY COALESCE(in.month, out.month)

Related

Joining two queries together into one main table

I have the following two queries that I need to join together to get one final output.
The primary keys are year, month,cost_center, g.account, and e.submapping.
The first table is an acutals table from a GL while the second query is a planned amount. I am trying to compare actuals to plan and need to join these two tables with the primary keys listed.
---Query 1 (e)
with Ranking as (
select c.*, rank() over(partition by
c.ledger_name,
c.company_code,
c.location_code,
c.cost_center,
c.account_number,
c.period_name,
c.currency,
c.amount,
c.entered_amount,
c.dm_insert_dt
order by dw_last_updated DESC) rnk
from wbr_global.gl_ap_details c
where cost_center IN ('1168','1153','1172','1257')
and ledger_name IN ('ABC.com, Inc.')
and account_number between '59999' and '70000')
select
to_date(period_name, 'Mon-YY') as BalanceDate,
date_part(month,(to_date(period_name, 'Mon-YY'))) as Months,
Case
when right(period_name,2) = right(date_part_year(current_date),2) then 'Current Year'
when right(period_name,2) = right(date_part_year(current_date) - 1,2) then 'Prior Year'
else 'Error' end as YearFlag,
EXTRACT(YEAR from balancedate) as year,
EXTRACT(Month from balancedate) as month,
e.sub_mapping,
c.cost_center,
c.period_name,
sum(c.amount) as amount
from Ranking c
left join wbr_global.raw_station_extended_attribute d on c.location_code = d.location_code
left join sandbox.utr_fixed_mapping_na e on c.account_number = e.account_number
where c.cost_center IN ('1168','1153','1172','1257')
and c.ledger_name = 'abc.com, Inc.'
and c.rnk = 1
group by 1,2,3,4,5,6,7,8
limit 10
Here is the second query
---Second query g
EXTRACT(YEAR from first_day_of_month) as year,
EXTRACT(Month from first_day_of_month) as month,
first_day_of_month,country,cost_center,scenario,'employee_relation' as account,
sum(employee_relation) as amount
from prophecy_to_sabre_ds_db.prophecy_caffeine.output_ww_field_opex
where cost_center = 1172
AND scenario = 'Q2G_22_1'
group by 1,2,3,4,5,6
Would I be able to make one a sub query in the other and join that way.
(Query 2) as g on g.cost_center = c.cost_center
and g.account = e.sub_mapping
and g.year = e.year
and g.month = e.month

Combining multiple queries

I want a table with all customers and their last charge transaction date and their last invoice date. I have the first two, but don't know how to add the last invoice date to the table. Here's what I have so far:
WITH
--Last customer transaction
cust_trans AS (
SELECT customer_id, created
FROM charges a
WHERE created = (
SELECT MAX(created) AS last_trans
FROM charges b
WHERE a.customer_id = b.customer_id)),
--All customers
all_cust AS (
SELECT customers.id AS customer, customers.email, CAST(customers.created AS DATE) AS join_date, ((1.0 * customers.account_balance)/100) AS balance
FROM customers),
--Last customer invoice
cust_inv AS (
SELECT customer_id, date
FROM invoices a
WHERE date = (
SELECT MAX(date) AS last_inv
FROM invoices b
WHERE a.customer_id = b.customer_id))
SELECT * FROM cust_trans
RIGHT JOIN all_cust ON all_cust.customer = cust_trans.customer_id
ORDER BY join_date;
This should get what you need. Notice each individual subquery is left-joined to the customer table, so you always START with the customer, and IF there is a corresponding record in each subquery for max charge date or max invoice date, it will be pulled in. Now, you may want to apply a COALESCE() for the max dates to prevent showing nulls, such as
COALESCE(maxCharges.LastChargeDate, '') AS LastChargeDate
but your call.
SELECT
c.id AS customer,
c.email,
CAST(c.created AS DATE) AS join_date,
((1.0 * c.account_balance) / 100) AS balance,
maxCharges.LastChargeDate,
maxInvoices.LastInvoiceDate
FROM
customers c
LEFT JOIN
(SELECT
customer_id,
MAX(created) LastChargeDate
FROM
charges
GROUP BY
customer_id) maxCharges ON c.id = maxCharges.customer_id
LEFT JOIN
(SELECT
customer_id,
MAX(date) LastInvoiceDate
FROM
invoices
GROUP BY
customer_id) maxInvoices ON c.id = maxInvoices.customer_id
ORDER BY
c.created

Compose a SQL query that produces monthly revenue by channel and the previous month's revenue

Hey everyone I have two tables with output like this:
Month_Table
Transaction_Table
I need to calculate the monthly revenue by channel and the previous month's revenue: I did this query but it is not completed
Select date_created, channel, sum(revenue) as monthly_revenue
from transaction_table
GROUP BY date_created,channel
The result should be displaying monthly revenue and the month's revenue of previous month.
How can I do that?
try this code .
with resultTable as(
select RT.channel,RT.sumRevenue,LT.[month-start_date],LT.month_end_date,LT.year_month
from (select t.channel,sum(revenue) as sumRevenue,M.month_index from Month_Table M,Transaction_Table T
where t.date_created BETWEEN m.[month-start_date] AND m.month_end_date
group by m.month_index,t.channel) RT Join Month_Table LT on RT.month_index = LT.month_index
)
select * from resultTable
output:
OR use this query
with resultTable as(
select RT.channel,RT.sumRevenue,LT.[month-start_date],LT.month_end_date,LT.year_month
from (select t.channel,sum(revenue) as sumRevenue,M.month_index from Month_Table M,Transaction_Table T
where t.date_created BETWEEN m.[month-start_date] AND m.month_end_date
group by m.month_index,t.channel) RT Join Month_Table LT on RT.month_index = LT.month_index
)
select *,LAG(sumRevenue,1) OVER (PARTITION BY channel ORDER BY channel) previous_month_sales from resultTable
output:
You could try uing a a join between you tables
Select a.month_index, a.year_month, b.channel, sum(b.revenue) as monthly_revenue
from Month_Table a
from transaction_table b ON b.date_created between a.month_start_date and a.month_and_date
amd month(b.date_created) = betwwen month(curdate()) -1 and month(curdate())
GROUP BY a.month_index, a.year_month, b.channel
order by a.year_month desc
Try this:
Select t1.date_created, t1.channel, sum(t1.revenue) as monthly_revenue ,sum(t2.revenue) prev_month_revenue
from transaction_table t1 left join transaction_table t2 on t1.channel = t2.channel and to_char(t1.date_created,'MM') = to_char(add_months(t2.date_created,-1),'MM')
GROUP BY t1.date_created,t1.channel;

lag/lead for previour year,same month,date,hour in sql server

I have year, month, day of month, hour column also sale column . The data is for four years. How to create lag varaibles for sales in next year, same month, day of month, hour?
SELECT
[UtilityName],
[CustomerID],
[DT_EST],
[Date_Raw],
[Hour_Raw],
[EPT_Year],
[EPT_month],
[EPT_DayNum],
[EPT_Hour24],
[Sales],
lag([Sales]) over( partition by [UtilityName] ,[CustomerID],[EPT_month],
[EPT_DayNum],[EPT_Hour24] order by [DT_EST] ) as lag_Sales
FROM [dbo].[table]
I would suggest instead using left join:
SELECT t.*, tprev.Sales as prev_year_sales
FROM [dbo].[table] t LEFT JOIN
[dbo].[table] tprev
ON tprev.UtilityName = t.UtilityName AND
tprev.CustomerId = t.CustomerId AND
tprev.EPT_Year = t.EPT_Year - 1 AND
tprev.EPT_month = t.EPT_month AND
tprev.EPT_DayNum = t.EPT_DayNum AND
tprev.EPT_Hour24 = t.EPT_Hour24;
You must partition by month, day and hour also and order by year descending to get the previous year's value:
lag([Sales])
over(partition by
[UtilityName] ,[CustomerID],
[EPT_month], [EPT_DayNum], [EPT_Hour24]
order by [EPT_Year]
) as lag_Sales

Output two columns for 1 field for different date ranges?

I have a SQL table "ITM_SLS" with the following fields:
ITEM
DESCRIPTION
TRANSACTION #
DATE
QTY SOLD
I want to be able to output QTY SOLD for a one month value and a year to date value so that the output would look like this:
ITEM, DESCRIPTION, QTY SOLD MONTH, QTY SOLD YEAR TO DATE
Is this possible?
You could calculate the total quantity sold using group by in a subquery. For example
select a.Item, a.Description, b.MonthQty, c.YearQty
from (
select distinct Item, Description from TheTable
) a
left join (
select Item, sum(Qty) as MonthQty
from TheTable
where datediff(m,Date,getdate()) <= 1
group by Item
) b on a.Item = b.Item
left join (
select Item, sum(Qty) as YearQty
from TheTable
where datediff(y,Date,getdate()) <= 1
group by Item
) c on a.Item = c.Item
The method to limit the subquery to a particular date range differs per DBMS, this example uses the SQL Server datediff function.
Assuming the "one month" is last month...
select item
, description
, sum (case when trunc(transaction_date, 'MM')
= trunc(add_months(sysdate, -1), 'MM')
then qty_sold
else 0
end) as sold_month
, sum(qty_sold) as sold_ytd
from itm_sls
where transaction_date >= trunc(sysdate, 'yyyy')
group by item, description
/
This will give you an idea of what you can do:
select
ITEM,
DESCRIPTION,
QTY SOLD as MONTH,
( select sum(QTY SOLD)
from ITM_SLS
where ITEM = I.ITEM
AND YEAR = i.YEAR
) as YEAR TO DATE
from ITM_SLS I