Sum from the joined table in sql - sql

I am trying to sum the amount from the tbl_paid where transaction_num has same number and tbl_client.c_id = tbl_paid.c_id.
Basically means I am trying to add the amount of 3359 and 1 where there c_id = 172 and transaction_num = 2 because they have the same record. Row 1 and 2 and then the other is as is.
tbl_client
tbl_paid
Look at the first picture to see the query I used to join table and get the output.
What I am trying to do with my query is to show all the records from tbl_client joined by tbl_paid who are accounts that are paid today. If the pay twice this day the record of the amount will be added to the existing payment.

You want to show clients with their today's total payment. So, select the total payment per client and then join this to the client table.
select c.*, p.total
from tbl_client c
join
(
select c_id, sum(amount) as total
from tbl_paid
where pay_date = current_date()
group by c_id
) p on p.c_id = c.c_id
order by c.c_id;
If you want to show clients with no current payment, too, then change the inner join to an outer join.
UPDATE: In the comments to ϻᴇᴛᴀʟ's answer you say you want to see the different transactions. If this is so, then you don't want the total per client, but the total per client and transaction, which is a very small change in the query:
select c.*, p.transaction_num, p.total
from tbl_client c
join
(
select c_id, transaction_num, sum(amount) as total
from tbl_paid
where pay_date = current_date()
group by c_id, transaction_num
) p on p.c_id = c.c_id
order by c.c_id;

sum() and group by is what you need.
select t3.*, t4.*
from tbl_client t4
inner join
(select sum(t2.amount) as amt, t1.transaction_num, t1.c_id
from tbl_client t1
inner join tbl_paid t2 on t1.c_id = t2.c_id
where t1.pay_date = current_date()
group by t1.transaction_num, t1.cid
) t3 on t3.c_id = t4.c_id

You can use SUM() :
select SUM(amount), t1.transaction_num
from tbl_client t1
left join tbl_paid t2 on t1.c_id = t2.c_id
where t1.transaction_num = 2 and t1.c_id = 172`

Related

Getting a SUM of the values in INNER JOIN adds up duplicate values

I am running a query which is counting the records on monthly basis from the table.
I am trying to add one extra column called "TotalPrice", I need a sum of all the prices from 'settle' table.
The problem I am facing is because of INNER JOIN, 'SUM' of the prices is adding up multiple prices due to duplicate records which the INNER JOIN is returning. Is there a way to avoid it and get a SUM of the prices from unique records ?
SELECT
CONCAT(year(datetime), '-', month(datetime)) AS YearMonth,
COUNT (DISTINCT a.id) AS TOTAL, SUM(total_price) AS TotalPrice
FROM settle AS a with (nolock)
INNER JOIN transfers b with (nolock) ON b.settleId = a.id
INNER JOIN Fdata AS c with (nolock) ON c.id= b.data
GROUP BY CONCAT(year(datetime), '-', month(datetime))
Thanks in advance.
sql server 2008 onwards:
with CTE as -- A CTE alows us to manipulate the data before we use it, like a derived table
(
select datetime, id, total_price,
row_number() over(partition by id, datetime order by total_price) as rn -- This creates a row number for each combo of id and datetime that appears
FROM settle AS a with (nolock)
INNER JOIN transfers b with (nolock) ON b.settleId = a.id
INNER JOIN Fdata AS c with (nolock) ON c.id= b.data
)
SELECT CONCAT(year(datetime), '-', month(datetime)) AS YearMonth,
COUNT (DISTINCT a.id) AS TOTAL,
SUM(total_price) AS TotalPrice
from CTE
where rn = 1 -- that row_number we created? This selects only the first one, removing duplicates
group by CONCAT(year(datetime), '-', month(datetime))

JOIN only one row from second table and if no rows exist return null

In this query I need to show all records from the left table and only the records from the right table where the result is the highest date.
Current query:
SELECT a.*, c.*
FROM users a
INNER JOIN payments c
ON a.id = c.user_ID
INNER JOIN
(
SELECT user_ID, MAX(date) maxDate
FROM payments
GROUP BY user_ID
) b ON c.user_ID = b.user_ID AND
c.date = b.maxDate
WHERE a.package = 1
This returns all records where the join is valid, but I need to show all users and if they didn't make a payment yet the fields from the payments table should be null.
I could use a union to show the other rows:
SELECT a.*, c.*
FROM users a
INNER JOIN payments c
ON a.id = c.user_ID
INNER JOIN
(
SELECT user_ID, MAX(date) maxDate
FROM payments
GROUP BY user_ID
) b ON c.user_ID = b.user_ID AND
c.date = b.maxDate
WHERE a.package = 1
union
SELECT a.*, c.*
FROM users a
--here I would need to join with payments table to get the columns from the payments table,
but where the user doesn't have a payment yet
WHERE a.package = 1
The option to use the union doesn't seem like a good solution, but that's what I tried.
So, in other words, you want a list of users and the last payment for each.
You can use OUTER APPLY instead of INNER JOIN to get the last payment for each user. The performance might be better and it will work the way you want regarding users with no payments.
SELECT a.*, b.*
FROM users a
OUTER APPLY ( SELECT * FROM payments c
WHERE c.user_id = a.user_id
ORDER BY c.date DESC
FETCH FIRST ROW ONLY ) b
WHERE a.package = 1;
Here is a generic version of the same concept that does not require your tables (for other readers). It gives a list of database users and the most recently modified object for each user. You can see it properly includes users that have no objects.
SELECT a.*, b.*
FROM all_users a
OUTER APPLY ( SELECT * FROM all_objects b
WHERE b.owner = a.username
ORDER BY b.last_ddl_time desc
FETCH FIRST ROW ONLY ) b
I like the answer from #Matthew McPeak but OUTER APPLY is 12c or higher and isn't very idiomatic Oracle, historically anyway. Here's a straight LEFT OUTER JOIN version:
SELECT *
FROM users a
LEFT OUTER JOIN
(
-- retrieve the list of payments for just those payments that are the maxdate per user
SELECT payments.*
FROM payments
JOIN (SELECT user_id, MAX(date) maxdate
FROM payments
GROUP BY user_id
) maxpayment_byuser
ON maxpayment_byuser.maxdate = payments.date
AND maxpayment_byuser.user_id = payments.user_id
) b ON a.ID = b.user_ID
If performance is an issue, you may find the following more performant but for simplicity you'll end up with an extra "maxdate" column.
SELECT *
FROM users a
LEFT OUTER JOIN
(
-- retrieve the list of payments for just those payments that are the maxdate per user
SELECT *
FROM (
SELECT payments.*,
MAX(date) OVER (PARTITION BY user_id) maxdate
FROM payments
) max_payments
WHERE date = maxdate
) b ON a.ID = b.user_ID
A generic approach using row_number() is very useful for "highest date" or "most recent" or similar conditions:
SELECT
*
FROM users a
LEFT OUTER JOIN (
-- determine the row corresponding to "most recent"
SELECT
payments.*
, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY date DESC) is_recent
FROM payments
) b ON a.ID = b.user_ID
AND b.is_recent = 1
(reversing the ORDER BY within the over clause also enables "oldest")

adding column to select gives group_by error

I have a following query:
SELECT transactions.created,
installments.*,
transactions.installment_id,
Sum(transactions.amount) AS s,
Sum(installments.amount) AS s1
FROM installments
LEFT OUTER JOIN transactions
ON transactions.installment_id = installments.id
WHERE installments.customer_id = ?
GROUP BY installments.id
which gives me error
org.h2.jdbc.JdbcSQLException: Column "TRANSACTIONS.CREATED" must be in
the GROUP BY list; SQL statement:
But I need the created field and don't want to use it in GROUP_BY.
SELECT *,s,S1,created
FROM installments
LEFT OUTER JOIN
(
SELECT SUM(transactions.amount) AS s, SUM(installments.amount) AS
s1,created
FROM transactions
GROUP BY created
) A ON A.installment_id = installments.id
WHERE installments.customer_id=?
Including it in the GROUP BY fixes the syntax problem:
SELECT t.created, i.*,
Sum(t.amount) AS s,
Sum(i.amount) AS s1
FROM installments i LEFT OUTER JOIN
transactions t
ON t.installment_id = i.id
WHERE i.customer_id = ?
GROUP BY i.id, t.created;
But the real issue is that you might have multiple transactions. Which created value do you want? You probably intend something more like:
SELECT Min(t.created) as created, i.*,
Sum(t.amount) AS s,
Sum(i.amount) AS s1
FROM installments i LEFT OUTER JOIN
transactions t
ON t.installment_id = i.id
WHERE i.customer_id = ?
GROUP BY i.id;
I should note that the calculation of s1 is probably wrong, because it is getting multiplied by the number of transactions. I'm thinking something more like this may be what you intend:
SELECT t.created, i.*,
t.amount as s,
Sum(i.amount) as s1
FROM installments i LEFT OUTER JOIN
(SELECT t.installment_id, t.created as created,
SUM(t.amount) as s
FROM transactions t
GROUP BY t.installment_id
) t
ON t.installment_id = i.id
WHERE i.customer_id = ?
GROUP BY i.id, t.created, t.amount;

left join two tables on a non-unique column in right table

I have two tables in sql server and i wanna select and join some data from these table.the first tables have some customer like:
---------------
customer id
Dave 1
Tom 2
---------------
and second table i table of purchases that includes list of last purchases with cost and which customer bought that Product:
------------------
product date customer id
PC 1-1-2000 1
phone 2-3-2000 2
laptop 3-1-2000 1
------------------
i wanna select first table (customers info) with last date of their purchases!
i tried left join but that doesn't give me last purchases becuase customer id is not unique in second table! how can i do this function with SQL server query? Regards
If you just want the max date, use aggregation. I would recommend a left join for customers who have made no purchases:
select c.customer, c.id, max(p.date)
from customers c left join
purchases p
on c.id = p.customer_id
group by c.customer, c.id;
Use the not exists clause for the win!
select c.customer, p.*
from Customer as c
inner join Purchase as p
on p.customer_id = c.id
where not exists (
select 1
from Purchase as p2
where p2.customer_id = p.customer_id
and p2.date > p.date
)
I think you can use inner join and group by
select table1.customer, table1.id, table.max(date)
from table1
inner join table2 on table1.id = table2.id
group by table1.customer, table1.id

Sql query to minus the two tables. What Is wrong?

select table1.t1 from
(
(
select
ItemCategory.Name as Category,
InventoryItems.Name as ItemName,
sum(SalesItems.Quantity) as Quantity,
(InventoryItems.Weight*sum(SalesItems.Quantity)) as Weight,
sum(SalesItems.Amount) as Amount
from SalesInvoices
inner join Sales on Sales.ID = SalesInvoices.SalesID
inner join SalesItems on SalesItems.SalesID = Sales.ID
inner join InventoryItems on InventoryItems.ID = SalesItems.InventoryItemID
inner join ItemCategory on ItemCategory.ID = InventoryItems.ItemCategoryID
inner join BusinessPartners on Sales.BusinessPartnerID = BusinessPartners.ID
where SalesInvoices.Date >= '2013-07-1' and SalesInvoices.Date <= '2013-11-7'
group by ItemCategory.Name,InventoryItems.Name,InventoryItems.Weight
) as t1,
(
select
ItemCategory.Name as Category,
InventoryItems.Name as ItemName,
sum(SalesAdjustmentItems.AdjustedQuantity)*-1 as Quantity,
(sum(SalesAdjustmentItems.AdjustedQuantity)*InventoryItems.Weight)*-1 as
Weight,
sum(SalesAdjustmentItems.AmountReturn)*-1 as Amount
from SalesInvoices
inner join Sales on Sales.ID = SalesInvoices.SalesID
inner join SalesItems on SalesItems.SalesID = Sales.ID
inner join SalesAdjustmentItems on SalesAdjustmentItems.SalesItemID = SalesItems.ID
inner join InventoryItems on InventoryItems.ID = SalesItems.InventoryItemID
inner join ItemCategory on ItemCategory.ID = InventoryItems.ItemCategoryID
inner join SalesAdustment on SalesAdustment.SalesInvoiceID = SalesInvoices.ID
inner join BusinessPartners on Sales.BusinessPartnerID = BusinessPartners.ID
where SalesAdustment.Date>= '2013-07-1' and SalesAdustment.Date <= '2013-11-7'
group by ItemCategory.Name,InventoryItems.Name,InventoryItems.Weight
) as t2
)
as table1
What I am doing wrong in this query. 1st query is for Sales and second query is for Sale returns. I want to get the difference of Sales and Returns. But is giving me error.
Thanks
The SQL minus operator is known as EXCEPT e.g. to find sales that have no invoices:
-- Sales minus SalesInvoices
SELECT ID
FROM Sales
EXCEPT
SELECT SalesID
FROM SalesInvoices;
If you are using older versions,
SELECT ID
FROM Sales
where not exists(SELECT SalesID FROM SalesInvoices where sales.ID=SalesID);