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
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;
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.
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 )
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;
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..