Get Data According to Group by date field - mysql

Here is my table
Which have field type which means 1 is for income and 2 is for expense
Now requirement is for example in table there is two transaction made on 2-10-2018 so i want data as following
Expected Output
id created_date total_amount
1 1-10-18 10
2 2-10-18 20(It calculates all only income transaction made on 2nd date)
3 3-10-18 10
and so on...
it will return an new field which contains only incom transaction made on perticulur day
What i had try is
SELECT * FROM `transaction`WHERE type = 1 ORDER BY created_date ASC
UNION
SELECT()
//But it wont work
SELECT created_date,amount,status FROM
(
SELECT COUNT(amount) AS totalTrans FROM transaction WHERE created_date = created_date
) x
transaction
You can Also See Schema HERE http://sqlfiddle.com/#!9/6983b9

You can Count() the total number of expense transactions using conditional function If(), on a group of created_date.
Similarly, you can Sum() the amount of expense done using If(), on a created_date.
Try the following:
SELECT
`created_date`,
SUM(IF (`type` = 2, `amount`, 0)) AS total_expense_amount,
COUNT(IF (`type` = 2, `id`, NULL)) AS expense_count
FROM
`transaction`
GROUP BY `created_date`
ORDER BY `created_date` ASC

Do you just want a WHERE clause?
SELECT t.created_date, SUM(amount) as total_amount
FROM transaction t
WHERE type = 2
GROUP BY t.created_date
ORDER BY created_date ASC ;

Related

SQL query for cumulative sum or subtract

how to create columns from unique values of a column and do a cumulative addition or subtraction.
I have a record of transactions like this
transaction_id
created_at
transaction_type
amount
124
2020-08-06 17:00:09
2
25.00
123
2020-08-06 17:00:03
1
50.00
There are various types of transactions, which in turn have different effects .Some results are withdrawals from th account, some are deposits and others don’t affect it at all. This information is summarized in another table (let’s call it ‘transaction_types’), as shown below:
id
description
effect
1
Manual Deposit
add
2
Direct Payment
subtract
id in the table transaction_type is a foreign key transactions. transaction_type = transactions_type.id
now if the initial amount is $10000 I need to create a table like this
transaction_id
initial_balance
deposit
withdrawal
final_balance
123
100000
50
100050
124
100050
25
100025
I don't know how to create new columns based on unique values in some columns also to start a cumulative sum from 10000. This is the query I tried select f.transaction_id, t.created_at, sum(case when d.effect = 'subtract' then -1 else 1 end * amount) from f inner join d on f.transaction_type = d.id
WITH RECURSIVE RowNums AS
(
SELECT
transaction_id,
created_at,
CAST(amount AS SIGNED) AS amount,
effect,
ROW_NUMBER() OVER
(
ORDER BY
created_at,
transaction_id
) AS RowNum
FROM transactions t
JOIN transaction_types tt
ON t.transaction_type = tt.id
),
Balances AS
(
SELECT
transaction_id,
created_at,
amount,
effect,
100000 AS initial_balance,
100000 +
(
CASE effect
WHEN 'add' THEN amount
WHEN 'subtract' THEN (-(amount))
END
) AS final_balance,
RowNum
FROM RowNums
WHERE RowNum = 1
UNION ALL
SELECT
rn.transaction_id,
rn.created_at,
rn.amount,
rn.effect,
b.final_balance,
b.final_balance +
(
CASE rn.effect
WHEN 'add' THEN rn.amount
WHEN 'subtract' THEN (-(rn.amount))
END
),
rn.RowNum
FROM Balances b
JOIN RowNums rn
ON (b.RowNum + 1) = rn.RowNum
)
SELECT
transaction_id,
initial_balance,
CASE effect
WHEN 'add'
THEN CAST(amount AS CHAR(20))
ELSE ''
END AS deposit,
CASE effect
WHEN 'subtract'
THEN CAST(amount AS CHAR(20))
ELSE ''
END AS withdrawal,
final_balance
FROM Balances
ORDER BY
created_at,
transaction_id
source : https://www.reddit.com/r/sqltutorial/comments/sx3ycb/comment/hxr6f9l/?utm_source=share&utm_medium=web2x&context=3

How to select last and last but one records

I have a table with 3 columns id, type, value like in image below.
What I'm trying to do is to make a query to get the data in this format:
type previous current
month-1 666 999
month-2 200 15
month-3 0 12
I made this query but it gets just the last value
select *
from statistics
where id in (select max(id) from statistics group by type)
order
by type
EDIT: Live example http://sqlfiddle.com/#!9/af81da/1
Thanks!
I would write this as:
select s.*,
(select s2.value
from statistics s2
where s2.type = s.type
order by id desc
limit 1, 1
) value_prev
from statistics s
where id in (select max(id) from statistics s group by type) order by type;
This should be relatively efficient with an index on statistics(type, id).
select
type,
ifnull(max(case when seq = 2 then value end),0 ) previous,
max( case when seq = 1 then value end ) current
from
(
select *, (select count(*)
from statistics s
where s.type = statistics.type
and s.id >= statistics.id) seq
from statistics ) t
where seq <= 2
group by type

MYSQL Query : How to get values per category?

I have huge table with millions of records that store stock values by timestamp. Structure is as below:
Stock, timestamp, value
goog,1112345,200.4
goog,112346,220.4
Apple,112343,505
Apple,112346,550
I would like to query this table by timestamp. If the timestamp matches,all corresponding stock records should be returned, if there is no record for a stock for that timestamp, the immediate previous one should be returned. In the above ex, if I query by timestamp=1112345 then the query should return 2 records:
goog,1112345,200.4
Apple,112343,505 (immediate previous record)
I have tried several different ways to write this query but no success & Im sure I'm missing something. Can someone help please.
SELECT `Stock`, `timestamp`, `value`
FROM `myTable`
WHERE `timestamp` = 1112345
UNION ALL
SELECT `Stock`, `timestamp`, `value`
FROM `myTable`
WHERE `timestamp` < 1112345
ORDER BY `timestamp` DESC
LIMIT 1
select Stock, timestamp, value from thisTbl where timestamp = ? and fill in timestamp to whatever it should be? Your demo query is available on this fiddle
I don't think there is an easy way to do this query. Here is one approach:
select tprev.*
from (select t.stock,
(select timestamp from t.stock = s.stock and timestamp <= <whatever> order by timestamp limit 1
) as prevtimestamp
from (select distinct stock
from t
) s
) s join
t tprev
on s.prevtimestamp = tprev.prevtimestamp and s.stock = t.stock
This is getting the previous or equal timestamp for the record and then joining it back in. If you have indexes on (stock, timestamp) then this may be rather fast.
Another phrasing of it uses group by:
select tprev.*
from (select t.stock,
max(timestamp) as prevtimestamp
from t
where timestamp <= YOURTIMESTAMP
group by t.stock
) s join
t tprev
on s.prevtimestamp = tprev.prevtimestamp and s.stock = t.stock

PHP MySQL Group By question

I have a column inside my table: tbl_customers that distinguishes a customer record as either a LEAD or a CUS.
The column is simply: recordtype, with is a char(1). I populate it with either C, or L.
Obviously C = customer, while L = lead.
I want to run a query that groups by the day the record was created, so I have a column called: datecreated.
Here's where I get confused with the grouping.
I want to display a result (in one query) the COUNT of customers and the COUNT of leads for a particular day, or date range. I'm successful with only pulling the number for either recordtype:C or recordtype:L , but that takes 2 queries.
Here's what I have so far:
SELECT COUNT(customerid) AS `count`, datecreated
FROM `tbl_customers`
WHERE `datecreated` BETWEEN '$startdate."' AND '".$enddate."'
AND `recordtype` = 'C'
GROUP BY `datecreated` ASC
As expected, this displays 2 columns (the count of customer records and the datecreated).
Is there a way to display both in one query, while still grouping by the datecreated column?
You can do a group by with over multiple columns.
SELECT COUNT(customerid) AS `count`, datecreated, `recordtype`
FROM `tbl_customers`
WHERE `datecreated` BETWEEN '$startdate."' AND '".$enddate."'
GROUP BY `datecreated` ASC, `recordtype`
SELECT COUNT(customerid) AS `count`,
datecreated,
SUM(`recordtype` = 'C') AS CountOfC,
SUM(`recordtype` = 'L') AS CountOfL
FROM `tbl_customers`
WHERE `datecreated` BETWEEN '$startdate."' AND '".$enddate."'
GROUP BY `datecreated` ASC
See Is it possible to count two columns in the same query
There are two solutions, depending on whether you want the two counts in separate rows or in separate columns.
In separate rows:
SELECT datecreated, recordtype, COUNT(*)
FROM tbl_customers
WHERE datecreated BETWEEN '...' AND '...'
GROUP BY datecreated, recordtype
In separate colums (this is called pivoting the table)
SELECT datecreated,
SUM(recordtype = 'C') AS count_customers,
SUM(recordtype = 'L') AS count_leads
FROM tbl_customers
WHERE datecreated BETWEEN '...' AND '...'
GROUP BY datecreated
Use:
$query = sprintf("SELECT COUNT(c.customerid) AS count,
c.datecreated,
SUM(CASE WHEN c.recordtype = 'C' THEN 1 ELSE 0 END) AS CountOfC,
SUM(CASE WHEN c.recordtype = 'L' THEN 1 ELSE 0 END) AS CountOfL
FROM tbl_customers c
WHERE c.datecreated BETWEEN STR_TO_DATE('%s', '%Y-%m-%d %H:%i')
AND STR_TO_DATE('%s', '%Y-%m-%d %H:%i')
GROUP BY c.datecreated",
$startdate, $enddate);
You need to fill out the date format - see STR_TO_DATE for details.

mysql 2 set of sum using groupby rollup

I have a query
select user_id,sum(hours),date, task_id from table where used_id = 'x' and date >='' and date<= '' group by user_id, date, task_id with roll up
The query works fine. But I also need to find a second sum(hours) where the group by order is changed.
select user_id,sum(hours),date, task_id from table where used_id = 'x' group by user_id,task_id
(The actual where condition is much longer.)
Is it possible to get both the sum in a single query since the where condition almost the same?
SELECT * FROM (
SELECT 1 AS list_id
, user_id
, sum(hours) AS total_hours
, `date`
, task_id
FROM table WHERE used_id = 'x' AND `date` BETWEEN #thisdate AND #thatdate
GROUP BY user_id, `date`, task_id /*WITH ROLLUP*/
UNION ALL
SELECT 2 AS list_id
, user_id
, sum(hours) AS total_hours
, `date`
, task_id
FROM table
WHERE used_id = 'x'
GROUP BY user_id,task_id WITH ROLLUP ) q
/*ORDER BY q.list_id, q.user_id, q.`date`, q.task_id*/
Depending on your needs, you should only need one with rollup, or two.