I'm trying to get two counts of separate columns for data in one table.
I have a database that tracks issues, and one table, Issue, has the 2 relevant columns that each contain a date. Very similar to the following.
DateOpened DateClosed
2015-01-08 2015-01-08
2015-01-08 2015-01-08
2015-01-06 2015-01-08
2015-01-06 2015-01-08
2015-01-04 2015-01-07
2015-01-02 2015-01-07
2015-01-02 2015-01-07
My goal is to be able to count the number of entries opened and closed on each date. An example of the expected output from above would be.
Date CountDateOpened CountDateClosed
2015-01-08 2 4
2015-01-07 0 3
2015-01-06 2 0
2015-01-05 0 0
2015-01-04 1 0
2015-01-03 0 0
2015-01-02 2 0
I know I need to group by Date, but there should be days where more issues are closed than opened, but my COUNT(DateClosed) never seems to exceed my Count(DateOpened). I am doing on the fly date conversions in the query, but I do not believe them to be relevant since I always round to the nearest day. Here is the query I'm running so far, skinned down for simplicity.
SELECT
CREATEDATE AS [Date],
COUNT(CREATEDATE) AS [Number Opened],
COUNT(CLOSEDATE) AS [Number Closed]
FROM
ISSUE
GROUP BY
CREATEDATE
ORDER BY
[Date] DESC
One way of doing this is to use union all to create a single column for both dates and then group according to its type:
SELECT `Date`,
COUNT(`open`) AS `CountDateOpened`
COUNT(`closed`) AS `CountDateClosed`
FROM (SELECT `DateOpened` AS `Date`, 1 AS `open`, NULL AS `closed`
FROM `issue`
UNION ALL
SELECT `DateClosed` AS `Date`, NULL AS `open`, 1 AS `closed`
FROM `issue`
) t
GROUP BY `Date`
ORDER BY `Date` DESC
Try this
select
d.dt,(select COUNT(DateOpened) ct from ISSUE where
CAST(DateOpened as DATE)=CAST(d.dt as DATE) )
,(select COUNT(DateClosed) ct from ISSUE where
CAST(DateClosed as DATE)=CAST(d.dt as DATE) )
from (
select number,DATEADD(D,number-7,GETDATE()) dt
from master.dbo.spt_values sp
where type='P' and DATEADD(D,number-7,GETDATE())<'2015-01-09'
)
d
ORDER BY d.dt desc
OUTPUT
Date DateOpened DateClosed
2015-01-08 2 4
2015-01-07 0 3
2015-01-06 2 0
2015-01-05 0 0
2015-01-04 1 0
2015-01-03 0 0
2015-01-02 2 0
Same as Mureinik's answer, just a little less typing...
SELECT date,SUM(status='opened') opened, SUM(status = 'closed') closed
FROM
( SELECT dateopened date,'opened' status FROM my_table
UNION ALL
SELECT dateclosed,'closed' FROM my_table
) x
GROUP
BY date DESC;
Related
My mysql database resembles the following and am struggling with the proper use of case, group by and order by statements. The sample dataset:
ID Date Direction
1 2017-04-01 1
2 2017-04-01 1
3 2017-04-01 -1
4 2017-04-01 1
5 2017-04-01 -1
6 2017-04-01 1
7 2017-04-02 -1
8 2017-04-02 -1
9 2017-04-02 -1
10 2017-04-02 1
11 2017-04-02 -1
12 2017-04-03 -1
I am trying to understand the best way to aggregate this table and group by date so that the query returns the following recordset. The "positive" column below is simply a count of the direction column (above) where direction > 0. Similarly, the "negative" column is a count of the direction column where direction < 0 like so:
DATE positive negative
2017-04-01 4 2
2017-04-02 1 4
2017-04-03 0 1
I have tried:
SELECT DATE,
CASE
WHEN direction < 0 THEN 'negative'
WHEN direction > 0 THEN 'positive'
END AS updownType, count(*) AS updownCount
FROM table WHERE DATE BETWEEN '2017-04-01' AND '2017-04-03'
GROUP BY DATE, updownType
ORDER BY DATE ASC
I've reviewed dozens of SO threads on this topic, but just haven't run across what I am looking for yet. Any suggestions are appreciated
oops you just miss it . see below
SELECT DATE,
count(CASE WHEN direction < 0 THEN '1' END) AS negative,
Count(CASE WHEN direction > 0 THEN '1' END) AS positive
FROM table WHERE DATE BETWEEN '2017-04-01' AND '2017-04-03'
GROUP BY DATE
ORDER BY DATE ASC
I am trying to find out which customers have defaulted on their loans. I would like to query the dataset to find the User_id of customers who have not paid in the last 60 days, but and not sure how to implement this in SQL.
User_id Due_Date Loan_Amount Paid_Amount
1 2012-04-04 16:14:12 500 40
1 2012-05-04 16:14:12 500 40
1 2012-06-04 16:14:12 500 0
1 2012-07-04 16:14:12 500 0
1 2012-08-04 16:14:12 500 0
2 2012-02-15 03:30:55 2030 100
2 2012-03-15 03:30:55 2030 100
2 2012-04-15 03:30:55 2030 100
3 2012-01-03 12:24:42 777 10
3 2012-02-03 12:24:42 777 0
3 2012-03-03 12:24:42 777 0
3 2012-04-03 12:24:42 777 0
In pseudocode (shown in bold) would look something like this, but I can't seem to implement it in MySQL:
SELECT User_id from TABLE_NAME WHERE Loan_Amount > 0 AND [the value Paid_Amount has been null for over 60 days]
Desired Output:
Users 1 and 3 in the above query would be returned because they have not paid for three consecutive periods.
NOTE: Due_Date is a time stamp
Any ideas would be very much appreciated!
Looks like you can use the DATEDIFF(date1, date1) function to obtain a list of delinquent borrowers.
SELECT DISTINCT
user_id
FROM table_name n
JOIN (SELECT user_id, max(due_date) maxDate FROM table_name GROUP BY user_id) t
ON n.user_id = t.user_id
AND n.due_date = t.maxDate
WHERE
loan_amount > 0
AND paid_amount IS NULL
AMD DATEDIFF(due_date, getdate()) > 60
My previous query was wrong, try this
select distinct t1.User_id
from TABLE_NAME t1
inner join (
select ts1.User_id, sum(ts1.Paid_Amount) as Paid_Amount_Total
from TABLE_NAME ts1
group by ts1.User_id
) t2
on t1.User_id=t2.User_id and t1.Loan_Amount>t2.Paid_Amount_Total
)
where
t1.Loan_Amount > 0
and t1.User_id not in (
select ts2.User_id
from TABLE_NAME ts2
where ts2.Due_Date>=DATE_SUB(NOW(), INTERVAL 60 DAY) and ts2.Paid_Amount>0
)
t1, ts1, ts2 - are aliases for TABLE_NAME
From MySQL table I have the list amount based on the dates. I need to get the sum of amount for each date:
ex:
id type date amount
1 1 2015-01-01 100
2 1 2015-01-01 150
3 1 2015-01-02 10
4 1 2015-01-03 250
Here 2015-01-01 appears more than once.
so i need the result like
date amount
2015-01-01 200
2015-01-02 10
2015-01-03 250
My Query getting between this week start and end
SELECT * from mytable WHERE YEARWEEK(`date`) = YEARWEEK(CURRENT_DATE) AND `type` = 1 ORDER BY `date` ASC
You need a group by clause:
SELECT `date`, SUM(amount)
FROM mytable
GROUP BY `date`
I think the result should be
date amount
2015-01-01 250
2015-01-02 10
2015-01-03 250
you can use this mysql query to get that result:
Select date, sum(amount) as amount
from mytable
GROUP BY date
ORDER BY date asc
dont forget to add "ORDER BY" clause if you want the result in good order
Use GROUP BY
Use AS clause to change the column Name
SELECT `date`, SUM(amount) AS amount
FROM mytable
GROUP BY `date`
I have a table like the following:
PARENTREF TRANSTYPE(BIT(1)) DUEDATE(DateTime) TOTAL
2038 0 2015-01-01 1000
2038 1 2015-03-05 500
2039 0 2015-01-01 1000
2040 0 2015-01-01 1000
2041 0 2015-01-01 1000
2040 1 2015-04-07 200
I want a SELECT query that returns SUM(TOTAL) when TRANSTYPE=1 subtracted from SUM(TOTAL) when TRANSTYPE=0 for each distinct PARENTREF. I also would like to get in a separate column the DUEDATE for the PARENTREF when TRANSTYPE=0. There may be only one PARENTREF with TRANSTYPE=0 so that won't be a problem. In other words, I should get the following table:
PARENTREF DUEDATE(DateTime) TOTAL
2038 2015-01-01 500
2039 2015-01-01 1000
2040 2015-01-01 800
2041 2015-01-01 1000
(1-transtype*2) is 1 when transtype=0 and is -1 when transtype=1, so query subtract values of total where transtype=1 from value of total where transtype=0. max ignore null values, so it select only not null value where transtype=0.
select
parentref,
sum((1-transtype*2)*total) as total,
max(if(transtype=0,duedate,null)) as duedate
from tablename
group by parentref
Try this....
select t.PARENTREF,t.DueDate,(t.Total-isnull(m.Total,0)) as total
from tabl t LEFT outer join tabl m on t.PARENTREF=m.PARENTREF and t.TRANSTYPE <> m.TRANSTYPE
where (t.Transtype=0 ) and (isnull(m.Transtype,1)=1 )
Please Check out this fiddle http://sqlfiddle.com/#!3/d4988/1
or use thiss...
select t.PARENTREF,t.DueDate,(sum(t.Total)-sum(isnull(m.Total,0))) as total
from tabl t LEFT outer join tabl m on t.PARENTREF=m.PARENTREF and t.TRANSTYPE <> m.TRANSTYPE
where (t.Transtype=0 ) and (isnull(m.Transtype,1)=1 )
group by t.PARENTREF,t.DueDate
Check this fiddle http://sqlfiddle.com/#!3/d4988/2
Let's say you have the following table (the column of interest here is binid):
id datetime agid binid status
1 2013-02-01 11:03:49 0 25 1
2 2013-02-01 11:03:53 0 25 1
3 2013-02-01 11:04:21 0 26 1
4 2013-02-01 11:04:23 0 26 0
5 2013-03-01 11:04:26 0 25 0
6 2013-03-01 11:04:30 0 36 0
7 2013-03-01 11:04:34 0 36 1
8 2013-03-01 11:04:35 0 36 1
9 2013-03-01 11:04:36 0 36 1
10 2013-03-01 11:04:39 0 36 0
11 2013-03-01 11:04:41 0 36 1
13 2013-03-01 11:04:50 0 25 1
14 2013-03-01 11:04:53 0 26 1
15 2013-03-01 11:15:25 0 25 1
16 2013-03-01 11:15:30 0 25 0
17 2013-03-01 11:15:39 0 23 1
18 2013-03-01 11:15:43 0 26 1
How can I extract the last occurrence of each binid that occurs in a certain timeframe?
This is what I am using so far:
SELECT * FROM ( reports ORDER BY datetime ASC )
WHERE datetime >= TIMESTAMP('2013-03-01')
GROUP BY binid
but it returns the first occurrences instead. How can I return the last occurrence of each unique binid?
You should use a subquery to get the result:
select r1.*
from reports r1
inner join
(
select max(datetime) MaxDate, binid
from reports
WHERE datetime >= TIMESTAMP('2013-03-01')
group by binid
) r2
on r1.binid = r2.binid
and r1.datetime = r2.maxdate
WHERE r1.datetime >= TIMESTAMP('2013-03-01')
See SQL Fiddle with Demo
The problem is that when you are using a GROUP BY on a single column then MySQL can return an unexpected value for the other columns not in the GROUP BY. (see MySQL Extensions to GROUP BY).
From the MySQL Docs:
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. ... You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values the server chooses.
SELECT binid,
SUBSTRING_INDEX(GROUP_CONCAT(agid ORDER BY datetime DESC), ',', 1) AS agid,
SUBSTRING_INDEX(GROUP_CONCAT(status ORDER BY datetime DESC), ',', 1) AS status
FROM reports
WHERE datetime <= TIMESTAMP('2013-03-01')
GROUP BY binid;
SELECT * FROM ( reports ORDER BY datetime DESC)
WHERE datetime >= TIMESTAMP('2013-03-01')
GROUP BY binid LIMIT 1
Change ORDER BY ASC to ORDER BY DESC. Should do the trick.