query to get the SUM - sql

Supposed I have a data of
code_table
code_id | code_no | stats |
2 60 22A3
3 60 22A3
value_table
value_no | amount_value_one | amount_value_two | amount_diff | code_no | sample_no | code_id
1 1200.00 400.00 800.00 60 90 2
1 600.00 200.00 400.00 60 100 3
1 1800.00 600.00 1200.00 60 110 2
2 1200.00 1200.00 0.00 60 110 2
2 800.00 600.00 200.00 60 90 2
2 400.00 0.00 400.00 60 100 3
What I want to happen is to get all the SUM of amount_value_two and just retain the first amount_value_one which has the value_no = 1
the output can be conclude as
amount_value_one | SUM_of_amount_value_two | amount_diff | sample_no
1200.00 1000.00 200.00 90
600.00 200.00 400.00 100
1800.00 1.800.00 0.00 110
so far i have this following query
SELECT SUM(p.amount_value_one) as value_one,
SUM(p.amount_value_two) as value_two,
SUM(p.amount_diff) as amount_diff,
p.sample_no as sampleNo FROM value_table p
INNER JOIN code_table On code_table.code_no = p.code_no
WHERE code_table.code_id = p.code_id
AND code_table.stats = '22A3'
GROUP BY p.sample_no
the query above that I used is wrong because it gets the sum of both p.amount_value_one
and p.amount_diff
its just a test query because i cant imagine what would the query will look like.

Assuming that you have a column that specifies the ordering, then you can use that to figure out the "first" row. Then use conditional aggregation:
SELECT SUM(CASE WHEN seqnum = 1 THEN p.amount_value_one END) as value_one,
SUM(p.amount_value_two) as value_two,
SUM(p.amount_diff) as amount_diff,
p.sample_no as sampleNo
FROM (SELECT p.*,
ROW_NUMBER() OVER (PARTITION BY p.sample_no ORDER BY <ordering column>) as seqnum
FROM value_table p
) p JOIN
code_table ct
ON ct.code_no = p.code_no AND
ct.code_id = p.code_id
WHERE ct.stats = '22A3'
GROUP BY p.sample_no

Related

How to calculate the running balance of an asset based on INPUT and OUTPUT

I'm looking at different blockchain transactions and wanted to create a running balance of a given asset based on INPUT_ADDRESS (the address sending the currency) INPUT_AMOUNT (the amount being sent by an INPUT_ADDRESS), OUTPUT_ADDRESS (the address receiving the currency) and OUTPUT_AMOUNT (the amount being received by an OUTPUT_ADDRESS)
Here's a sample of a table I'm using:
BLOCK_DATE | BLOCK_HEIGHT | TRANS_HASH | INPUT_ADDRESS | OUTPUT_ADDRESS | INPUT_AMOUNT | OUTPUT_AMOUNT
01/11/2020 190 15c7853 abc xyz1 -0.01 0.0001
01/11/2020 190 14v9876 abc xyz2 -0.50 0.70
01/11/2020 191 19vc842 abc xyz3 -5.03 0.413
01/12/2020 192 20ff4d3 abc xyz4 -0.06 0.201
01/12/2020 192 154gf34 xyz1 abc -0.07 0.18
01/12/2020 192 45f4ti5 ggg abc -0.10 0.24
01/12/2020 192 33cv5c5 jjj abc -0.08 1.13
If I were to calculate a running sum of address abc, what's an efficient way of going about this? I tried using something like:
SELECT BLOCK_DATE, BLOCK_HEIGHT, TRANS_HASH, INPUT_ADDRESS, OUTPUT_ADDRESS, INPUT_AMOUNT, OUTPUT_AMOUNT, SUM (INPUT_AMOUNT) OVER (ORDER BY DATE) AS RunningAgeTotal
FROM TRANSACTION_TABLE
WHERE INPUT_ADDRESS = abc
In this particular example, the total balance for abc would be the sum of OUTPUT_AMOUNT where abc is the OUTPUT_ADDRESS (i.e 0.18 + 0.24 + 1.13) + the sum of INPUT_AMOUNT where abc is the INPUT_ADDRESS (i.e. -0.01 + -0.50 + -5.03 + -0.06). So, 1.55 + (-5.60) = -4.05
But I don't think this is the right way of going about this and I'm not sure how to account for the OUTPUT_AMOUNT (e.g. when abc receives is an OUTPUT_ADDRESS and receives an OUTPUT_AMOUNT)
Is this what you want?
select t.*,
sum(case when input_address = 'ABC' then input_amount
when output_address = 'ABC' then output_amount
end) over (order by block_date) as running_amount
from transaction_table t
where 'ABC' in (input_address, output_address);
This is a cumulative sum of the amounts aligned with the input/output columns.
EDIT:
You may want:
sum(case when input_address = 'ABC' then input_amount
when output_address = 'ABC' then output_amount
end) over (order by block_date, block_height) as running_amount

Exclude rows where keys match, but are on different rows

I'm looking for the best way to produce the result set in the scenario provided. My cust3 column isn't identifying the repeated values in the indvid2 column. The end result I'm looking for is to exclude the rows where key1 and key2 match (ids:1,2,6 and 7), then sum accounts where the acctids match.If there's a better way to code this, I welcome all suggestions. Thanks!
WITH T10 as (
SELECT acctid,invid,(
case
when invid like '%-R' then left (InvID,LEN(invid) -2) else InvID
END) as InvID2
FROM table x
GROUP BY acctID,invID
),
T11 as (
SELECT acctid, Invid2, COUNT(InvID2) as cust3
FROM T10
GROUP BY InvID2,acctid
HAVING
COUNT (InvID2) > 1
)
select DISTINCT
a.acctid,
a.name,
b.invid,
C.invid2,
D.cust3,
b.amt,
b.key1,
b.key2
from table a
inner join table b (nolock) on a.acctid = b.acctid
inner join T10 C (nolock) on b.invid = c.invid
inner join T11 D (nolock) on C.invid2 = D.invid2
Resultset
id acctID name invid invid2 Cust3 amt key1 key2
1 123 James 101 101 2 $500 NULL 6789
2 123 james 101-R 101 2 ($500) 6789 NULL
3 123 James 102 102 2 $350 NULL NULL
4 123 James 103 103 2 $200 NULL NULL
5 246 Tony 98-R 98 2 ($750) 7423 NULL
6 432 David 45 45 2 $100 NULL 9634
7 432 David 45-R 45 2 ($100) 9634 NULL
8 359 Stan 39-R 39 2 ($50) 6157 NULL
9 753 George 95 95 2 $365 NULL NULL
10 753 George 108 108 2 $100 NULL NULL
Desired Resultset
id acctID name invid invid2 Cust3 amt key1 key2
1 123 James 101 101 2 $500 NULL 6789
2 123 james 101-R 101 2 ($500) 6789 NULL
3 123 James 102 102 1 $350 NULL NULL
4 123 James 103 103 1 $200 NULL NULL
5 246 Tony 98-R 98 1 ($750) 7423 NULL
6 432 David 45 45 2 $100 NULL 9634
7 432 David 45-R 45 2 ($100) 9634 NULL
8 359 Stan 39-R 39 1 ($50) 6157 NULL
9 753 George 95 95 1 $365 NULL NULL
10 753 George 108 108 1 $100 NULL NULL
Then to sum amt by acctid
id acctid name amt
1 123 James $550
2 246 Tony ($750)
3 359 Stan ($50)
4 753 George $465
Something like:
;WITH Keys as (
SELECT Key1.acctID, [Key] = Key1.Key1
FROM YourTable as Key1
INNER JOIN YourTable as Key2
ON Key1.Key1 = Key2.Key2 and Key1.acctID = Key2.acctID
)
SELECT t.acctID, t.name, amt = SUM(t.amt)
FROM YourTable as t
LEFT JOIN Keys as k
ON t.acctID = k.acctID and (t.Key1 = [Key] or t.Key2 = [Key])
WHERE k.acctID is Null
GROUP BY t.acctID, t.name

Writing SQL INSERT which retrieves its data from two separate related rows

I am writing a SQL script that is to insert a new record using data from two rows that are under the same AccountID.
My table looks like the following:
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
My fix is to find find each 7,8 combination and insert a new row with ActivityId 78 that gets the DisplayDetails from ActivityId 7 and TransactionDate from ActivityId 8.
My queries looks like the following:
SELECT *
INTO #ActivityEight
FROM Account A
WHERE A.ActivityId = 8
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM #temp2 VL WITH(NOLOCK)
JOIN #ActivityEight S
ON VL.AccountId = S.AccountId
WHERE VL.ActivityId = 7
However when I run SELECT * FROM Account I get a 78 row for each 7 and 8 row, when I should only get 1 78 row per 7 and 8 combination.
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
=============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
1 78 DisplayThis1 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis2 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis1 1999-02-02 00:00:00.000 NULL
1 78 DisplayThis2 1999-02-02 00:00:00.000 NULL
I believe I can utilize the EnvironmentId to achieve the desired functionality, but I'm not sure how.
Any help would be appreciated.
Thanks!
I think this will help you
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM Account VL WITH(NOLOCK)
JOIN Account S ON VL.AccountId = S.AccountId and VL.EnvironmentId = S.EnvironmentId
WHERE VL.ActivityId = 7 and S.ActivityId = 8

SQL get latest record for each ID

I have three tables that contains data as below:
Users
Id Name Other_Columns
---------------------------
1 John Blah
2 Ricky Blah
3 Stella Blah
4 Bob Blah
Saldo
Id User_id Saldo
--------------------
1 3 0.00
2 1 9.00
3 2 0.15
4 4 3.50
Payments
Id User_id Amount Paid_date
------------------------------------------
1 2 10.00 2014-09-01 08:10
2 2 25.00 2014-09-01 09:00
3 3 100.00 2014-05-10 12:47
4 1 20.50 2014-02-23 15:30
How to get result like this:
Id Name Saldo Last Payment
------------------------------------------
1 John 9.00 23.02.2014 20.50
2 Ricky 0.15 01.09.2014 25.00
3 Stella 0.00 0000-00-00 0.00
4 Bob 3.50 10.05.2014 100.00
Thank you.
select u.id, u.name, s.saldo, p.last_paid_date, p2.amount
from users u
join saldo s
on u.id = s.user_id
join (select user_id, max(paid_date) as last_paid_date
from payments
group by user_id) p
on u.id = p.user_id
join payments p2
on p.last_paid_date = p2.paid_date
and p.user_id = p2.user_id
This answer assumes:
(1) On table SALDO, there is one row per USER_ID
(2) On table PAYMENTS, there can be multiple rows per USER_ID
(I'm pretty confident about #2 being true, I don't know about #1, as you didn't say and your sample data doesn't indicate one way or the other)

sql Query on effective date

I would like to get report for drink purchased in whole month but price of the drink can change any time in month and I would like to get report for a month with price change
I have two tables
SELECT [ID]
,[DrinkID]
,[UserID]
,[qty]
,[DateTaken]
FROM [Snacks].[dbo].[DrinkHistory]
SELECT [ID]
,[DrinkID]
,[UserID]
,[qty]
,[DateTaken]
FROM [Snacks].[dbo].[DrinkHistory]
[DrinkHistory]:
ID DrinkID UserID qty DateTaken
----------------------------------------------------------------------
1 1 1 1 2014-05-10
2 1 1 2 2014-05-15
3 2 1 1 2014-06-01
4 2 1 4 2014-06-01
5 1 1 3 2014-05-20
6 1 1 4 2014-05-30
[DrinkPricesEffect]:
PriceID DrinkID DrinkPrice PriceEffectiveDate IsCurrent
-----------------------------------------------------------------------------------
1 1 10.00 2014-05-01 1
2 1 20.00 2014-05-20 1
3 2 9.00 2014-06-01 1
4 2 8.00 2014-01-01 1
5 1 30.00 2014-05-25 1
6 1 40.00 2014-05-28 1
I would like to have result as under date taken between 2014-05-1 to 2014-05-31
DrinkId Qty Price DateTaken PriceEffectiveDate
-----------------------------------------------------------------------
1 1 10 2014-05-10 2014-05-01
1 2 10 2014-05-15 2014-05-01
1 3 20 2014-05-20 2014-05-20
1 4 40 2014-05-30 2014-05-28
Is there any who can give me some idea or write query for me?
If your drink price can change any time in a month you could additionaly save the price for each purchase. I would add a column [PricePaid] to the table [DrinkHistory].
When adding a record to [DrinkHistory], the price for the drink at the moment is known, but later it might change so you save the current price to the history...
Then for your result you could just display the Whole [DrinkHistory]
SELECT * FROM DrinkHistory;
This should work:
Select
DH.DrinkId,
DH.Qty,
DPE.DrinkPrice AS Price,
DH.DateTaken,
DPE.PriceEffectiveDate
FROM DrinkHistory DH
JOIN DrinkPricesEffect DPE ON DPE.PriceID =
(
Select Top 1 PriceID FROM
(
Select PriceID,RANK() OVER(ORDER BY PriceEffectiveDate DESC ) AS rnk
FROM DrinkPricesEffect
WHERE DH.DrinkId = DrinkId AND
DH.DateTaken >= PriceEffectiveDate
)SubQ WHERE rnk = 1
)
WHERE DH.DateTaken Between '2014-05-01' AND '2014-05-30'
Here you can find the SQL Fiddle link: http://sqlfiddle.com/#!6/5f8fb/26/0