Order_ID
=========
id price
A 10
A 10
B 20
B 20
C 30
C 30
D 40
D 40
Client
==================
Client Name id
1 ClientInc. A
1 ClientInc. A
1 ClientInc. B
1 ClientInc. B
1 ClientInc. C
1 ClientInc. C
1 ClientInc. D
1 ClientInc. D
I have two tables that I need to join (Order_ID and Client) and want to sum the price by distinct order_ID and create the report below:
Desired Solution
========================
id Name Sum(Price)
1 ClientInc. 100
This is the current query I am using:
SELECT merchant,
name,
SUM(price)
FROM order_id a
JOIN client b
ON a.id = b.id
GROUP BY merchant, name
It is displaying the following output by summarizing every order_id, but the problem is that I want to SUM a distinct order ID:
Current Wrong Report
======================
id Name Sum(Price)
1 ClientInc. 200
SELECT merchant,
name,
SUM(price)
FROM ( SELECT DISTINCT id,price
FROM order_id
) a
JOIN client b
ON a.id = b.id
GROUP BY merchant, name;
Related
I have the following sales table that displays the customer ID, their name, the order amount, and the order date.
ID
Name
Order
Date
1
A
25
11/10/2006
1
A
10
5/25/2010
1
A
10
6/18/2018
2
B
20
3/31/2008
2
B
15
11/15/2010
3
C
35
1/1/2019
3
C
20
4/12/2007
3
C
10
3/20/2010
3
C
5
10/19/2012
4
D
15
12/12/2013
4
D
15
2/18/2010
5
E
25
12/11/2006
6
F
10
5/1/2016
I am trying to group the data so that for each customer it would only show me their most recent order and the amount, as per below:
ID
Name
Order
Date
1
A
10
6/18/2018
2
B
15
11/15/2010
3
C
35
1/1/2019
4
D
15
12/12/2013
5
E
25
12/11/2006
6
F
10
5/1/2016
So far I've only been able to group by ID and Name, because adding the Order column would also group by that column as well.
SELECT
ID,
Name,
MAX(Date) 'Most recent date'
FROM Table
GROUP BY Customer, Customer
How can I also add the order amount for each Customer?
SELECT ID, Name, Order, Date FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Date DESC) AS sn
FROM your_table_name
) A WHERE sn = 1;
You could use a subqoery for max date
SELECT
ID,
Name,
MAX(Date) 'Most recent date'
FROM Table
GROUP BY Customer, Customer
select a.ID, a.Name, b.max_date
from Table a
inner join (
select name, max(Date) max_date
from Table
group by name
) b on a. name = b.name and a.date = b.max_date
You can use this query to get the expected result:
SELECT S.*
FROM Sales S
CROSS APPLY
(
SELECT ID, Max(Date) MaxDate
FROM Sales
GROUP BY ID
)T
WHERE S.ID = T.ID
AND S.Date = T.MaxDate
ORDER BY S.ID
I'm working on a service that needs to calculate how much a customer owes, according to a total invoice value and the partial payments that the customer has made.
So, in a tableA I have a row with the invoice total value:
[dbo].[TableA]
ID CustomerId InvoiceVal
1 12 1000
2 11 2000
3 10 5000
4 14 15000
5 12 100
6 16 8000
7 18 3200
In a TableB I have the record of each customer's partial payments they have made to each invoice:
[dbo].[TableB]
ID InvoiceId Payment
1 1 150
2 3 50
3 1 120
4 1 100
5 5 90
6 4 7500
So, as you can see, the customer 12 has an invoice for $1000 and has made 3 payment that sum $370
I need to be able to se the partial total owed in each row, this is the expected result:
No. InoviceId CustomerId Payment Owed
1 1 12 150 850
2 1 12 120 730
3 1 12 100 630
So far, this is my code:
DECLARE #invid int = '1'
DECLARE #invoicetotal numeric(18,2)
SET #invoicetotal =
(
SELECT
[dbo].[TableA].[InvoiceVal]
FROM [dbo].[TableA]
WHERE
([dbo].[TableA].[ID] = #invid)
)
SELECT
*,
SUM(#invoicetotal - [dbo].[TableB].[Payment]) OVER(ORDER BY [dbo].[TableB].[ID] ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS [Owed]
FROM [dbo].[TableB]
WHERE
([dbo].[TableB].[InvoiceId] = #invid)
But this is what I get:
ID InvoiceId Payment Owed
1 1 150.00 NULL
3 1 120.00 850.00
4 1 100.00 1730.00
I need to sum the previous payment on each row.
Thanks!
Something like this would help
SELECT
ROW_NUMBER() OVER (ORDER BY TableB.ID ASC) NO,
CustomerId,
Payment,
InvoiceVal - SUM(Payment) OVER (PARTITION BY TableA.ID ORDER BY TableB.Id ASC) Owed
FROM TableA
INNER JOIN TableB
ON TableA.Id = TableB.InvoiceId
WHERE
CustomerId = 12
Working Fiddle
Your query will depend on what you are trying to make as your final output.
If you want just ONE CustomerID, go with:
SELECT a.ID AS InvoiceID, a.CustomerID, a.InvoiceVal AS StartInvoice
, b.ID AS bid, b.Payment
, a.InvoiceVal - ISNULL(SUM(b.Payment) OVER (PARTITION BY a.ID ORDER BY b.id),0) AS owed
FROM TableA a
LEFT OUTER JOIN TableB b ON a.ID = b.InvoiceID
WHERE a.CustomerID = 12
And if that CustomerID doesn't have any payments, you want to use a LEFT JOIN so that you don't eliminate an amount owed.
SELECT a.ID AS aid, a.CustomerID, a.InvoiceVal AS StartInvoice
, b.ID AS bid, b.Payment
, a.InvoiceVal - ISNULL(SUM(b.Payment) OVER (PARTITION BY a.ID ORDER BY b.id),0) AS owed
FROM TableA a
LEFT OUTER JOIN TableB b ON a.ID = b.InvoiceID
WHERE a.CustomerID = 11
I also added an ISNULL() around Payment to keep from nulling out your owed amount. It could also be added to the InvoiceVal to account for a CustomerID who hasn't been invoiced yet, if that was needed (or possible from other tables).
IF you want to get ALL CustomerIDs, you'll have to account for that in your partition.
SELECT s1.CustomerID, aid AS InvoiceID, s1.bid, s1.Payment
, (s1.StartInvoice - s1.runningPayment) AS Owed
FROM (
SELECT a.ID AS aid, a.CustomerID, a.InvoiceVal AS StartInvoice
, b.ID AS bid, b.Payment
, ISNULL(SUM(b.Payment) OVER (PARTITION BY a.CustomerID, a.ID ORDER BY b.id),0) AS runningPayment
FROM TableA a
LEFT OUTER JOIN TableB b ON a.ID = b.InvoiceID
) s1
ORDER BY s1.CustomerID, s1.aid, s1.bid
Fiddle demonstrates overpayment or paying total balance for 0 owed.
let me explain what i need, i have 2 table named A and B. B is sub table for A.
Here is Schema:
------------------------
Table B:
itemId version qty AId
44 1 1 200
44 1 2 201
44 2 2 200
------------------------
Table A:
id tId
200 100
201 100
------------------------
and here is what i need: i need sum of all latest version qty that have same tId.
here is my query:
select sum(qty) as sum from B
left join A on A.id=B.AId
where itemId=44 and tId=100 and
version=(select max(version) from B where itemId=44 and tId=100)
the result get wrong when one item got version 2 and version 1 ignored.
thanks.
EDIT:
what exactly i need is:
itemId version qty AId
44 2 2 200
44 1 2 201
And Result of Sum(qty) must be 4, because they have same tId and they have Max version in each AId.
Use window function.
select itemid, version, qty, aid
from (
select *, max(version) over (partition by AId) as latestVersion
from B
) as B
where version = latestVersion
to sum up
select tId, SUM(qty) AS qty_sum
from (
select *, max(version) over (partition by AId) as latestVersion
from B
) as B
join A on B.AId = A.id
where version = latestVersion
group by tId
Working solution
select b.* from B as b
inner join
(select AID,itemId,Max(version) as mVersion from B
group by AID,itemID) d
on b.AID = d.AID and b.itemID = d.itemID and b.Version = d.mVersion
inner join A as a
on B.AID = a.id
where b.itemID = 44 --apply if you need
result
itemid version qty aid
44 2 2 200
44 1 2 201
this will give you result as you sum of quantity
select itemID,sum(qty) from (
select b.* from B as b
inner join
(select AID,itemId,Max(version) as mVersion from B
group by AID,itemID) d
on b.AID = d.AID and b.itemID = d.itemID and b.Version = d.mVersion
inner join A as a
on B.AID = a.id
where b.itemID = 44 --apply if you need
) e group by itemID
result
itemid sum
44 4
Try This one
DECLARE #TA Table (id int,tid int)
DECLARE #TB Table (itemid int, version int,qty int,AID int)
INSERT INTO #TA
SELECT 200, 100
UNION ALL
SELECT 201, 100
INSERT INTO #TB
SELECT 44,1,1,201
UNION ALL
SELECT 44,1,2,200
UNION ALL
SELECT 44,2,3,200
UNION ALL
SELECT 44,2,5,201
DECLARE #tid int
SET #tid = 100
SELECT XB.* FROM #Tb XB INNER JOIN
(SELECT Version,Max(AID) Aid FROM #TA A INNER JOIN #TB B ON A.id = B.AID AND tid = #tid Group By Version) X
ON X.version = XB.version and XB.AID = X.Aid
i think this query help you to solve your problem
SELECT itemId, version, qty , AId FROM (
SELECT itemId, version, qty , AId FROM b
LEFT JOIN a ON (b.aid = a.id)
) temp
WHERE version = (SELECT MAX(version) FROM b WHERE b.aid = temp.aid)
and temp.tid = 100 and temp.itemId = 44
SELECT B.*
FROM B
INNER JOIN
(SELECT Aid,MAX(version) AS version FROM B WHERE itemId=44 GROUP BY AId) AS B1
ON B.Aid=B1.Aid
AND B.version=B1.version
INNER JOIN
(SELECT * FROM A WHERE tId=100) AS A
ON A.id=B.Aid
Order BY B.aid
For Sum of qty
SELECT SUM(B.qty)
FROM B
INNER JOIN
(SELECT Aid,MAX(version) AS version FROM B WHERE itemId=44 GROUP BY AId) AS B1
ON B.Aid=B1.Aid AND B.version=B1.version
INNER JOIN
(SELECT * FROM A WHERE tId=100) AS A
ON A.id=B.Aid
GROUP BY A.tid
Output
itemid version qty aid
44 2 2 200
44 1 2 201
Demo
http://sqlfiddle.com/#!17/092dd/5
The most efficient solution greatest-n-per-group problems in Postgres are typically using the (proprietary) operator distinct on ()
So to get the latest version for each a.id, you can use:
select distinct on (a.id) b.*
from a
join b on a.id = b.aid
order by a.id, b.version desc;
The above returns:
itemid | version | qty | aid
-------+---------+-----+----
44 | 2 | 2 | 200
44 | 1 | 2 | 201
You can then sum over the result:
select sum(qty)
from (
select distinct on (a.id) b.qty
from a
join b on a.id = b.aid
order by a.id, b.version desc
) t;
Note that normally an order by in a derived table is useless, but in this case it's needed because otherwise distinct on () wouldn't work.
Online example: http://rextester.com/DRHK19268
Postgresql 9.1: I have a query that must return the values of a second table only if the aggregate function SUM of two columns is greater than zero.
This is the data:
Table a
id
---
1
2
3
Table b
id fk(table a)
---------------
1 1
2 null
3 3
Table c
id fk(table b) amount price
-----------------------------------
1 1 1 10 --positive
2 1 1 -10 --negative
3 3 2 5
As you can see, table b has some ids from table a, and table c can have 1 or more references to table b, table c is candidate to be retrieved only if the sum(amount * price ) > 0.
I wrote this query:
SELECT
a.id, b.id, SUM(c.amount * c.price) amount
FROM
tablea a
LEFT JOIN
tableb b ON b.fk = a.id
LEFT JOIN
tablec c ON c.fk = b.id
GROUP BY
a.id, b.id
HAVING
SUM(c.amount * c.price) > 0
But this query is not retrieving all rows from table a just the row 1 and I need the two rows. I understand this is happening because of the HAVING clause but I don't know how to rewrite it.
Expected result
a b sum
------------------
1 null null -- the sum of 1 * 10 (rows 1 and two) = 0 so its not retrieved.
2 null null -- no foreign key in second table
3 3 10 -- the sum of 2 * 5 (row 3) > 0 so it's ok.
Try this:
SELECT A.ID, B.ID, C.ResultSum
FROM TableA A
LEFT JOIN TableB B ON (B.FK = A.ID)
LEFT JOIN (
SELECT FK, SUM(Amount * Price) AS ResultSum
FROM TableC
GROUP BY FK
) C ON (C.FK = B.ID) AND (ResultSum > 0)
See demo here.
I'm a humble programmer that hates SQL ... :) Please help me with this query.
I have 4 tables, for example:
Table A:
Id Total
1 100
2 200
3 500
Table B
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table C
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
Table D
ExtId Amount
1 10
1 20
1 13
2 12
2 43
3 43
3 22
I need to make a SELECT that shows the Id, the Total and the SUM of the Amount fields of tables B, C and D like this
Id Total AmountB AmountC AmountD
1 100 43 43 43
2 200 55 55 55
3 500 65 65 65
I've tried with a inner join of the three tables by the Id and doing a sum of the amount fields but results are not rigth. Here is the wrong query:
SELECT dbo.A.Id, dbo.A.Total, SUM(dbo.B.Amount) AS Expr1, SUM(dbo.C.Amount) AS Expr2, SUM(dbo.D.Amount) AS Expr3
FROM dbo.A INNER JOIN
dbo.B ON dbo.A.Id = dbo.B.ExtId INNER JOIN
dbo.C ON dbo.A.Id = dbo.C.ExtId INNER JOIN
dbo.D ON dbo.A.Id = dbo.D.ExtId
GROUP BY dbo.A.Id, dbo.A.Total
Thanks in advance, its just that I hate SQL (or that SQL hates me).
EDIT: I had a typo. This query is not giving the right results. Extended the example.
Or you can take advantage of using SubQueries:
select A.ID, A.Total, b.SB as AmountB, c.SC as AmountC, d.SD as AmountD
from A
inner join (select ExtID, sum(Amount) as SB from B group by ExtID) b on A.ID = b.ExtID
inner join (select ExtID, sum(Amount) as SC from C group by ExtID) c on c.ExtID = A.ID
inner join (select ExtID, sum(Amount) as SD from D group by ExtID) d on d.ExtID = A.ID
From your description, this query should give you an error as you are using the non-existent column dbo.A.Amount in your group by. Changing this to dbo.A.Total might be what you need.
If you need all the amounts together, then try this query:
select A.Id, A.Total, sum(B.Amount + C.Amount + D.Amount) AS Total_Amount
from A
inner join B on A.Id = B.ExtId
inner join C on A.Id = C.ExtId
inner join D on A.Id = D.ExtId
group by A.Id, A.Total;
This one also works well
SELECT (SELECT SUM(Amount) FROM TableA) AS AmountA,
(SELECT SUM(Amount) FROM TableB) AS AmountB,
(SELECT SUM(Amount) FROM TableC) AS AmountC,
(SELECT SUM(Amount) FROM TableD) AS AmountD
This might help other users.
SELECT Total=(Select Sum(Amount) from table a)+(Select Sum(Amount) from table b)+(Select Sum(Amount) from table c)
Try this code
SELECT Total=isnull((Select Sum(Isnull(Amount,0)) from table a),0)+isnull((Select Sum(isnull(Amount,0)) from table b),0)+isnull((Select Sum(isnull(Amount,0)) from table c),0)