how to get balance per recored in sqlite - sqlite

I have table called transaction_table so I write the this code
select
t._id,
t.description,
t.debit,
t.credit,
(t.debit - t.credit) blnc,
t.curr_id,
t.cus_id
from transaction_table t
the result:
this col
_id description debit credit blnc curr_id cuss_id
-------------------------------------------------------------------------
1 cr for customer 1 0.0 30.0 -30.0 1 1
2 cr for customer 1 0.0 500.0 -500.0 1 1
3 dbt for customer 1 70.0 0.0 70.0 1 1
4 cr for customer 2 0.0 600.0 -600.0 1 2
5 dat for customer 2 100.0 0.0 100.0 1 2
6 dat for customer 2 300.0 0.0 300.0 1 2
but I want some thing like this:
_id description debit credit blnc curr_id cuss_id
-------------------------------------------------------------------------
1 cr for customer 1 0.0 30.0 -30.0 1 1
2 cr for customer 1 0.0 500.0 -530.0 1 1
3 dbt for customer1 70.0 0.0 470.0 1 1
4 cr for customer 2 0.0 600.0 -600.0 1 2
5 dat for customer 2 100.0 0.0 -500.0 1 2
6 dat for customer 2 300.0 0.0 -200.0 1 2
So, how to achieve the second table using sqlite? thank you.

Use SUM() window function:
SELECT _id, description, debit, credit,
SUM(debit - credit) OVER (PARTITION BY curr_id, cus_id ORDER BY _id) blnc,
curr_id, cus_id
FROM transaction_table;
Depending on your requirement you may remove the column curr_id from the PARTITION BY clause.
For versions of SQLite prior to 3.25, that do not support window functions, use a self join and aggregation:
SELECT t1._id, t1.description, t1.debit, t1.credit,
SUM(t2.debit - t2.credit) blnc,
t1.curr_id, t1.cus_id
FROM transaction_table t1 INNER JOIN transaction_table t2
ON t2.curr_id = t1.curr_id AND t2.cus_id = t1.cus_id AND t2._id <= t1._id
GROUP BY t1._id;
Depending on your requirement you may remove the condition t2.curr_id = t1.curr_id from the ON clause.
See the demo.

Related

How to get balance according date and ID for every customer_id and currency_id using INNER JOIN

I have a table named as transaction_table:
CREATE TABLE transaction_table
(
_id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT,
debit REAL,
credit REAL,
curr_id INTEGER,
cus_id INTEGER,
FOREIGN KEY (curr_id) REFERENCES currencies(_id) ON DELETE CASCADE,
FOREIGN KEY (cus_id) REFERENCES customers(_id) ON DELETE CASCADE
)
And assume this data in it:
_id date debit credit curr_id cus_id
-------------------------------------------------------------------
1 2022-12-08T00:00:00.000 10.0 0.0 1 1
2 2022-12-07T00:00:00.000 0.0 20.0 1 1
3 2022-12-06T00:00:00.000 0.0 30.0 1 1
4 2022-12-07T00:00:00.000 40.0 0.0 1 1
5 2022-12-08T00:00:00.000 100.0 0.0 1 1
So I just make SELECT statement that will get balance according date then _id but the balance is wrong:
SELECT t1._id,
t1.date ,
t1.description ,
t1.debit ,
t1.credit,
SUM(t2.debit - t2.credit) as blnc,
t1.curr_id,
t1.cus_id
FROM transaction_table t1 INNER JOIN transaction_table t2
ON t2.curr_id = t1.curr_id AND t2.cus_id = t1.cus_id AND t2._id <= t1._id AND t2.date <= t1.date
GROUP BY t1._id
ORDER BY t1.date DESC, t1._id DESC;
the result:
_id date debit credit balance curr_id cus_id
-----------------------------------------------------------------------------
5 2022-12-08T00:00:00.000 100.0 0.0 100.0 1 1
1 2022-12-08T00:00:00.000 10.0 0.0 10.0 1 1
4 2022-12-07T00:00:00.000 40.0 0.0 -10.0 1 1
2 2022-12-07T00:00:00.000 0.0 20.0 -20.0 1 1
3 2022-12-06T00:00:00.000 0.0 30.0 -30.0 1 1
the result is wrong and it should be like this:
_id date debit credit balance curr_id cus_id
-----------------------------------------------------------------------------
5 2022-12-08T00:00:00.000 100.0 0.0 100.0 1 1
1 2022-12-08T00:00:00.000 10.0 0.0 0.0 1 1
4 2022-12-07T00:00:00.000 40.0 0.0 -10.0 1 1
2 2022-12-07T00:00:00.000 0.0 20.0 -50.0 1 1
3 2022-12-06T00:00:00.000 0.0 30.0 -30.0 1 1
which I can achieve it by this code:
SELECT _id,date, description, debit, credit,
SUM(debit - credit) OVER (PARTITION BY curr_id, cus_id ORDER BY date, _id) blnc,
curr_id, cus_id
FROM transaction_table
order by date desc, _id desc;
but I don't need it cause its not working in old android.
I just need to use INNER JOIN.
The conditions about the dates and the ids in the ON clause need correction:
SELECT t1._id,
t1.date,
t1.description,
t1.debit,
t1.credit,
SUM(t2.debit - t2.credit) AS blnc,
t1.curr_id,
t1.cus_id
FROM transaction_table t1 INNER JOIN transaction_table t2
ON t2.curr_id = t1.curr_id AND t2.cus_id = t1.cus_id
AND (t2.date < t1.date OR (t2.date = t1.date AND t2._id <= t1._id))
GROUP BY t1._id
ORDER BY t1.date DESC, t1._id DESC;
See the demo.
You may substitute the SUM() analytic function call with a correlated subquery:
SELECT _id, date, description, debit, credit,
(SELECT SUM(t2.debit - t2.credit)
FROM transaction_table t2
WHERE t2.curr_id = t1.curr_id AND
t2.cus_id = t1.cus_id AND
(t2.date <= t1.date OR
t2.date = t1.date AND t2._id <= t1._id)) AS blnc,
curr_id, cus_id
FROM transaction_table t1
ORDER BY date DESC, _id DESC;

SQLite : Need to combine results from one table with another result

I have 2 tables :
payments:
id amount type code
1 1200 0 111
2 100 1 111
3 200 0 111
4 50 0 112
5 500 2 112
6 300 3 113
bills:
id details code
-----------------------
1 bill-1 111
2 bill-2 112
3 bill-3 113
4 bill-4 114
I wanted to sum the amounts in payments table and join it with bills like below
result:
bills.code type0Sum type1Sum type2Sum type3Sum
-------------------------------------------------------------------------
111 1400 100 0 0
112 50 0 500 0
113 0 0 0 300
114 0 0 0 0
Sorry if this is a newbie question
[Edit]
I have used a similar query as below :
SELECT *
FROM bills,
(SELECT SUM(amount) AS type0Sum, code
FROM payments
WHERE type = 0
GROUP BY code)
AS sub1,
(SELECT SUM(amount) AS type1Sum, code
FROM payments
WHERE type = 1
GROUP BY ref_code)
AS sub2
WHERE bills.code = sub1.code
AND bills.code = sub2.code
But I am getting only the rows those having the type like :
bills.code type0Sum type1Sum type2Sum type3Sum
-------------------------------------------------------
111 1400 100
I've modified that final query to do proper joins, not the old joins that you were doing (read up on cartesian joins). Give this one a go for you, see if it works;
SELECT b.code
,sub1.type0Sum
,sub2.type1Sum
FROM bills b
LEFT JOIN (
SELECT SUM(amount) AS type0Sum
,code
FROM payments
WHERE type = 0
GROUP BY code
) AS sub1 ON b.code = sub1.code
LEFT JOIN (
SELECT SUM(amount) AS type1Sum
,code
FROM payments
WHERE type = 1
GROUP BY ref_code
) AS sub2 ON b.code = sub2.code
There are other ways of doing this that are more efficient but I've kept to your query in order to help you learn.

BigQuery subsselect example (count and sum)

In google BigQuery I have done a simple query to get how many music someone has listened.
What I need is to make a sum for all rows returned from the query below (some type of subquery)?
select count(1) cnt
from OF7.PETERV_TEST
where gender='F'
group by userId
Row f0_
1 14
2 1
3 7
4 18
5 1
6 4
7 2
8 2
expected result:
49
you can use:
SELECT sum(cnt)
FROM
(SELECT count(1) cnt
FROM OF7.PETERV_TEST
WHERE gender='F'
GROUP BY userId )

SQL Count Data 1/2 hourly

I have a stored procedure that counts data for each hour,
Declare #DateTimeToFilter DATETIME;
--set #DateTimeToFilter = GetDate();
set #DateTimeToFilter = '6/5/14'
SET NOCOUNT ON;
WITH H ([Hour]) AS
( SELECT 7 UNION
SELECT 8 UNION
SELECT 9 UNION
SELECT 10 UNION
SELECT 11 UNION
SELECT 12 UNION
SELECT 13 UNION
SELECT 14 UNION
SELECT 15 UNION
SELECT 16 UNION
SELECT 17 UNION
SELECT 18 UNION
SELECT 19
)
SELECT H.[Hour],
COUNT(T.BookingID) AS NoOfUsers
FROM H
LEFT JOIN tbl_Visitor T
ON H.[Hour] = DATEPART(HOUR, T.TimeofArrival) AND
((DATEDIFF(dd, T.TimeofArrival, #DateTimeToFilter) = 0) AND (DATEDIFF(mm, T.TimeofArrival, #DateTimeToFilter) = 0) AND
(DATEDIFF(yy, T.TimeofArrival, #DateTimeToFilter) = 0))
GROUP BY H.[Hour];
This forces the data returned for each hour irrespective of whether there is any data or not.
How could I add the half hourly data to be added also, so the returned data look like.
Hour Count
7 0
7.5 0
8 0
8.5 0
9 0
9.5 0
10 4
10.5 0
11 0
11.5 0
12 0
12.5 0
13 0
13.5 0
14 5
14.5 0
15 2
15.5 0
16 2
16.5 0
17 0
17.5 0
18 0
18.5 0
19 0
19.5 0
The data is stored in the database as a smalltimedate, i.e. 2014-06-05 14:00:00
Any help is appreciated.
You can use minutes instead of hours:
with h ([Minute]) as (
select 420 union all
select 450 union all
select 480 union all
select 510 union all
select 540 union all
...
Divide the minutes to get fractional hours:
select h.[Minute] / 60.0 as [Hour], ...
Calculate the start and stop time for the interval to filter the data:
... on T.TimeofArrival >= dateadd(minute, h.[Minute], #DateTimeToFilter) and
T.TimeofArrival < dateadd(minute, h.[Minute] + 30, #DateTimeToFilter)
Below is an example that groups by half-hour intervals and can easily be extended for other intervals. I suggest you avoid applying functions to columns in the WHERE clause as that prevents indexes on those columns from being used efficiently.
DECLARE
#DateTimeToFilter smalldatetime = '2014-06-05'
, #IntervalStartTime time = '07:00:00'
, #IntervalEndTime time = '20:00:00'
, #IntervalMinutes int = 30;
WITH
t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n))
, t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d)
, t64k AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b)
, intervals AS (SELECT DATEADD(minute, (num - 1) * #IntervalMinutes, #DateTimeToFilter) AS interval
FROM t64k
WHERE num <= 1440 / #IntervalMinutes)
SELECT
interval
, CAST(DATEDIFF(minute, #DateTimeToFilter, interval) / 60.0 AS decimal(3, 1)) AS Hour
, COUNT(T.BookingID) AS NoOfUsers
FROM intervals
LEFT JOIN dbo.tbl_Visitor T
ON T.TimeofArrival >= intervals.interval
AND T.TimeofArrival < DATEADD(minute, #IntervalMinutes, intervals.interval)
WHERE
interval >= DATEADD(minute, DATEDIFF(minute, '', #IntervalStartTime), #DateTimeToFilter)
AND interval < DATEADD(minute, DATEDIFF(minute, '', #IntervalEndTime), #DateTimeToFilter)
GROUP BY interval
ORDER BY Hour;

SQLite query with LAST and DISTINCT

I have an example table:
ID | ArticleID | Price | SupplierID | dateAdded
1 1 100 1 2014-08-01
2 1 110 2 2014-08-01
3 2 105 1 2014-08-01
4 2 106 1 2014-08-01
5 2 101 2 2014-08-01
6 3 100 1 2014-08-01
7 1 107 2 2014-09-01
8 3 343 2 2014-09-01
9 3 232 2 2014-09-01
10 1 45 1 2014-09-01
I want to use .query on this table and select LAST value entered for each DISTINCT ArticleID for each SupplierID, resulting in:
ID | ArticleID | Price | SupplierID
10 1 45 1
9 3 232 2
6 3 100 1
7 1 107 2
4 2 106 1
5 2 101 2
I want to get price for last ArticleID entered for each SupplierID.
What should I enter into
public Cursor query (boolean distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
I came up with this so far:
String[] columns = new String[]{DatabaseOpenHelper.KEY_ID, DatabaseOpenHelper.KEY_CENA, DatabaseOpenHelper.KEY_IZDELEK_ID};
Cursor crs = database.query(true,"prices", columns, selection, selectionArgs, null, null, null, null);
but now I'm stuck:S
Any hint how to do this?
You can also suggest raw query if possible..
Raw query would be like this:
SELECT ID, ArticleID, Price, SupplierID FROM your_table WHERE ID IN (SELECT max(ID) from your_table GROUP BY ArticleID, SupplierID);
I assumed the IDs are autoincremented and the more recent entries have higher ids. If that's not the case change the HAVING clause to operate on DATE column.
After fidling around a bit and help of a friend I have came with SQL query that does what I want, not sure about optimization:
select tab.* from cene tab inner join (
select izdelek_id, trgovina_id, Max(enter_date) as maxDate
from cene group by izdelek_id, trgovina_id) art
on (art.izdelek_id = tab.izdelek_id) and (art.trgovina_id = tab.trgovina_id) and (art.maxDate = tab.enter_date)
izdelek_id = ArticleID
trgovina_id = SupplierID
cene is the name of a table.
Hope it helps to somebody..

Resources