I am having a resultset/table which is as below
user_id |date_time |name |
---------|------------------|------|
1 |05/04/2017 08:00 |Jack |
2 |05/04/2017 09:00 |Adams |
1 |05/04/2017 13:06 |Jack |
1 |05/04/2017 13:45 |Jack |
1 |06/04/2017 09:15 |Jack |
1 |07/04/2017 10:00 |Jack |
1 |10/04/2017 12:00 |Jack |
2 |10/04/2017 12:30 |Adams |
1 |10/04/2017 15:44 |Jack |
I want to sort the date_time in ascending order for each user for each day.
I am expecting the result to be as below: (I am having problem with the second row and the last but one). All rows for Jack on April 5 should be together, followed by Adams; whether the date_time of Adams is in between the date_time of Jack for that day
user_id |date_time |name |
---------|------------------|------|
1 |05/04/2017 08:00 |Jack |
1 |05/04/2017 13:06 |Jack |
1 |05/04/2017 13:45 |Jack |
2 |05/04/2017 09:00 |Adams |
1 |06/04/2017 09:15 |Jack |
1 |07/04/2017 10:00 |Jack |
1 |10/04/2017 12:00 |Jack |
1 |10/04/2017 15:44 |Jack |
2 |10/04/2017 12:30 |Adams |
Adding the query I had used to arrive at this resultset:
SELECT DISTINCT user_table.user_id
,diary_table.date_time
,user_table.NAME
FROM user_table
INNER JOIN diary_table ON user_table.user_id = diary_table.diary_user_id
AND (
date_time >= '06-Apr-2017 00:00:00'
AND date_time <= '15-Apr-2017 23:59:59'
)
AND diar_user_id IN (
SELECT DISTINCT diar_user_id
FROM diary_table
INNER JOIN event_table ON event_table.event_id = diary_table.diar_event_id
WHERE event_table.event_name = 'Lunch'
AND (
date_time >= '06-Apr-2017 00:00:00'
AND date_time <= '15-Apr-2017 23:59:59'
)
)
ORDER BY date_time ASC
,NAME
,ASC
Got this solved by using a day column. Here goes the query:
SELECT DISTINCT DISTINCT DATEADD(DAY, DATEDIFF(DAY, 0, date_time), 0) AS theDay
,user_table.user_id
,diary_table.date_time
,user_table.NAME
FROM user_table
INNER JOIN diary_table ON user_table.user_id = diary_table.diary_user_id
AND (
date_time >= '06-Apr-2017 00:00:00'
AND date_time <= '15-Apr-2017 23:59:59'
)
AND diar_user_id IN (
SELECT DISTINCT diar_user_id
FROM diary_table
INNER JOIN event_table ON event_table.event_id = diary_table.diar_event_id
WHERE event_table.event_name = 'Lunch'
AND (
date_time >= '06-Apr-2017 00:00:00'
AND date_time <= '15-Apr-2017 23:59:59'
)
)
ORDER BY theDay
,NAME ASC
,date_time ASC
Related
I want to get Daily, Weekly and Monthly report from a sql-server table.
Table structure as as follow:
------------------------------------------
| ItemID | CommentDate |
-----------------------------------------
|989898797 | 2019-04-01 02:51:11.153 |
|----------------------------------------|
|989898797 | 2019-04-01 02:51:11.153 |
|----------------------------------------|
|989898797 | 2019-04-03 02:51:11.153 |
|----------------------------------------|
|989898797 | 2019-04-09 02:51:11.153 |
|----------------------------------------|
|989898797 | 2019-04-11 02:51:11.153 |
|----------------------------------------|
So far I have tried the following,
select (select count(itemid) from ebayfeedback where ((year(commentdate) = year(getdate()))
and datepart(m,commentdate)=datepart(m,dateadd(month,-1,getdate())))) as lastmonth,
(select count(itemid) from ebayfeedback where (year(commentdate) = year(getdate()))
and datepart(m,commentdate)=datepart(m,dateadd(month,0,getdate()))) as thismonth,
(select count(itemid) from ebayfeedback where (year(commentdate) = year(getdate()))
and datepart(wk,commentdate)=datepart(wk,dateadd(week,1,getdate()))) as lastweek,
(select count(itemid) from ebayfeedback where (year(commentdate) = year(getdate()))
and datepart(wk,commentdate)=datepart(wk,getdate()) group by datepart(wk,commentdate) ) as thisweek,
(select count(itemid) from ebayfeedback where convert(varchar,commentdate,101)=
convert(varchar,dateadd(day,-1,getdate()),101)) as yesterday,
(select count(itemid) from ebayfeedback where convert(varchar,commentdate,101)=
convert(varchar,getdate(),101) ) as today
from ebayfeedback
The Result I receive result in multiple rows from the above query is like below.
---------------------------------------------------------
| lastmonth | thismonth | lastweek | thisweek | today |
---------------------------------------------------------
|5 | 5 | 2 | 2 | 1 |
|-------------------------------------------------------|
|5 | 5 | 2 | 2 | 1 |
|-------------------------------------------------------|
|5 | 5 | 2 | 2 | 1 |
|-------------------------------------------------------|
|5 | 5 | 2 | 2 | 1 |
|-------------------------------------------------------|
|5 | 5 | 2 | 2 | 1 |
|-------------------------------------------------------|
I want single row (1 result) for each period only. Please advise me as how to achieve this. Also is there any best approach other than the one I used.
Desired Result should be one row like below.
| lastmonth | thismonth | lastweek | thisweek | today |
---------------------------------------------------------
|5 | 5 | 2 | 2 | 1 |
|-------------------------------------------------------|
Note: The data I given in the as example in above both tables not the actual I have.
One way to solve this is using conditional aggregation query to create a report based on it.
First, create and populate sample table (Please save is this step in your future questions):
DECLARE #T AS TABLE
(
ItemID int,
CommentDate datetime
);
INSERT INTO #T (ItemId, CommentDate) VALUES
(989898797, '2019-04-01T02:51:11.153'),
(989898797, '2019-04-01T02:51:11.153'),
(989898797, '2019-04-03T02:51:11.153'),
(989898797, '2019-04-09T02:51:11.153'),
(989898797, '2019-04-11T02:51:11.153');
Declaring local variable to make the query more readable and to prevent some code repetitions:
DECLARE #Today date = GETDATE(), -- today's date
#ThisWeek date = DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), GETDATE()), -- first date of the week
#ThisMonth date = DATEADD(DAY, 1 - DATEPART(DAY, GETDATE()), GETDATE()); -- first date of the month
DECLARE #LastMonth date = DATEADD(MONTH, -1, #ThisMonth), -- first date of last month
#LastWeek date = DATEADD(WEEK, -1, #ThisWeek) -- first date of last week
The query:
SELECT COUNT(CASE WHEN CommentDate >= #LastMonth AND CommentDate < #ThisMonth THEN ItemId END) As LastMonth,
COUNT(CASE WHEN CommentDate >= #ThisMonth AND CommentDate < DATEADD(MONTH, 1, #ThisMonth) THEN ItemId END) As thismonth,
COUNT(CASE WHEN CommentDate >= #LastWeek AND CommentDate < #ThisWeek THEN ItemId END) As lastweek,
COUNT(CASE WHEN CommentDate >= #ThisWeek AND CommentDate < DATEADD(WEEK, 1, #ThisWeek) THEN ItemId END) As thisweek,
COUNT(CASE WHEN CommentDate >= #Today AND CommentDate < DATEADD(DAY, 1, #Today) THEN ItemId END) As today
FROM #T
Results:
LastMonth thismonth lastweek thisweek today
0 5 2 0 0
I have two working mysql select statements which I'd like to combine:
SELECT
t2.*,
t1.Lang,
Filmname,
ColFI
FROM Timetable t2, Contenttable t1
WHERE DATE_ADD(STR_TO_DATE(CONCAT('201825',' Thursday'), '%x%v %W'), INTERVAL 0 DAY) = DateSZ
AND RoomSZ =1 AND t2.idFI = t1.id
AND deleteSZ = false
ORDER BY TimeSZ
giving me (and of course some other irrelevant columns) for a specific day:
+----------+-------+------+------+------------+
| Filmname | time | idFI | Lang | DateSZ |
+----------+-------+------+------+------------+
| firstfi | 12:00 | 22 | eng | 2018-06-29 |
+----------+-------+------+------+------------+
| sencofi | 15:00 | 44 | fra | 2018-06-29 |
second:
SELECT
idFI,
COUNT(DISTINCT (case when Yweek < 201825 then Yweek end)) AS Week
FROM `Timetable`
GROUP BY idFI
giving me
+-------+------+
| Week | idFI |
+-------+------+
| 2 | 22 |
+-------+------+
| 1 | 44 |
My Timetable table is looking somewhat like this (plus some more columns):
+----------+-------+------+--------+------------+
| Filmname | time | idFI | Yweek | DateSZ |
+----------+-------+------+--------+------------+
| firstfi | 12:00 | 22 | 201825 | 2018-06-29 |
+----------+-------+------+--------+------------+
| firstfi | 18:00 | 22 | 201824 | 2018-06-21 |
+----------+-------+------+--------+------------+
| firstfi | 13:00 | 22 | 201823 | 2018-06-12 |
+----------+-------+------+--------+------------+
| sencofi | 15:00 | 44 | 201825 | 2018-06-29 |
+----------+-------+------+--------+------------+
| sencofi | 18:00 | 44 | 201823 | 2018-06-12 |
+----------+-------+------+--------+------------+
| sencofi | 10:00 | 44 | 201823 | 2018-06-13 |
My problem is, that if I insert the count(distinct) into the first select statement, it isn't working because it only counts rows witch meets all the where clauses in statement nr. 1. How can I combine these statements?
Edit:
Answer from #MKhalidJunaid, but not working with my formatting:
SELECT t2.*, t1.Lang, Filmname, ColFI, t3.Week DATE_FORMAT(DateSZ, '%d.%m.%y') AS DateSZ, TIME_FORMAT(TimeSZ, '%H:%i') AS TimeSZ
FROM Timetable t2
JOIN Contenttable t1 ON t2.idFI = t1.id
JOIN (
SELECT idFI, COUNT(DISTINCT (case when Yweek < 201825 then Yweek end)) AS Week
FROM Timetable
GROUP BY idFI
) t3 ON t2.idFI = t3.idFI
WHERE DATE_ADD(STR_TO_DATE(CONCAT('201825',' Thursday'), '%x%v %W'), INTERVAL 0 DAY) = DateSZ
AND RoomSZ =1
AND deleteSZ = false
ORDER BY TimeSZ
You could use a derived sub select for your count query and then join with your first query as
SELECT t2.*, t1.Lang, Filmname, ColFI , t3.Week
FROM Timetable t2
JOIN Contenttable t1 ON t2.idFI = t1.id
JOIN (
SELECT idFI, COUNT(DISTINCT (case when Yweek < 201825 then Yweek end)) AS Week
FROM Timetable
GROUP BY idFI
) t3 ON t2.idFI = t3.idFI
WHERE DATE_ADD(STR_TO_DATE(CONCAT('201825',' Thursday'), '%x%v %W'), INTERVAL 0 DAY) = DateSZ
AND RoomSZ =1
AND deleteSZ = false
ORDER BY TimeSZ
Also don't use old syntax for joining tables use explicit syntax using join keyword
Please how do I sum records in my MySQL table for the last 3 months but group them by month.
I want something like this:
select SUM(amount) from table where.....
group by month
I am doing the below but it is not returning any results
SELECT MONTHNAME(a.created_at) MONTH, YEAR(a.created_at) YEAR, SUM(a.credit) as credit, SUM(a.debit)
FROM telco_transactions AS a
WHERE a.telco_id = '1' and DATE(a.created_at) = DATE_ADD(NOW(), INTERVAL -3 MONTH)
GROUP BY MONTHNAME(a.created_at), YEAR(a.created_at);
select T.date_time, SUM(T.amount) from (
-> select * from TEST_TABLE where date_time >= DATE_ADD(CURDATE(), INTERVAL -3 MONTH) and date_time <= CURDATE())
-> as T GROUP BY MONTH(T.date_time);
The table test_table looks like
+------------+--------+
| date_time | amount |
+------------+--------+
| 2017-12-24 | 30 |
| 2017-09-24 | 30 |
| 2017-12-04 | 30 |
| 2017-11-24 | 30 |
| 2017-11-09 | 30 |
| 2017-10-24 | 30 |
+------------+--------+
and the output of the query looks like
+------------+---------------+
| date_time | SUM(T.amount) |
+------------+---------------+
| 2017-09-24 | 30 |
| 2017-10-24 | 30 |
| 2017-11-24 | 60 |
| 2017-12-24 | 60 |
+------------+---------------+
I would try this:
SELECT SUM(records)
FROM TABLE_NAME
WHERE Date_Column >= DATEADD(MONTH, -3, GETDATE())
GROUP BY DATEPART(MONTH, Date_Column)
I found a answer
SELECT MONTHNAME(a.created_at) as tmonth, YEAR(a.created_at) as tYear,
SUM(a.credit) as credit, SUM(a.debit)
FROM telco_transactions AS a
WHERE a.telco_id = '1' and DATE(a.created_at) BETWEEN DATE(NOW())-INTERVAL 3 MONTH AND DATE(NOW())
GROUP BY MONTHNAME(a.created_at), YEAR(a.created_at);
Consider this sample data:
+----------+------+--------+-----------------+
| username | qnum | qvalue | date |
+----------+------+--------+-----------------+
| Linda | 1 | 2 | 11/14/2017 7:25 |
+----------+------+--------+-----------------+
| Fred | 1 | 1 | 11/23/2017 7:59 |
+----------+------+--------+-----------------+
| Brian | 5 | 2 | 11/17/2017 7:25 |
+----------+------+--------+-----------------+
| Sandra | 6 | 1 | 11/25/2017 7:26 |
+----------+------+--------+-----------------+
| Tom | 6 | 1 | 11/22/2017 7:32 |
+----------+------+--------+-----------------+
| Paul | 6 | 1 | 11/22/2017 7:36 |
+----------+------+--------+-----------------+
| Andrew | 7 | 2 | 11/23/2017 7:37 |
+----------+------+--------+-----------------+
| Luke | 3 | 1 | 11/23/2017 8:03 |
+----------+------+--------+-----------------+
| William | 8 | 1 | 11/23/2017 8:03 |
+----------+------+--------+-----------------+
| Linda | 9 | 2 | 11/15/2017 8:03 |
+----------+------+--------+-----------------+
| Brian | 3 | 2 | 11/17/2017 8:04 |
+----------+------+--------+-----------------+
| Joan | 9 | 1 | 11/23/2017 8:04 |
+----------+------+--------+-----------------+
| Chris | 8 | 1 | 11/23/2017 8:04 |
+----------+------+--------+-----------------+
| Kim | 8 | 1 | 11/15/2017 8:04 |
+----------+------+--------+-----------------+
I am attempting to get the person who has the highest sum of qvalue for last week. I am able to get this information with the following SQL but my problem is that if more than one user has the top score then it does not show both of their names because I am using the LIMIT function. Is there a way to use max and sum together to get the desired result? The desired result would be a result set with both Linda and Brian listed because last week they both had a sum score of 4 and were tied.
SELECT username, SUM(qvalue) AS score FROM trivia_scoreboard
WHERE `date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND `date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
ORDER BY score DESC
LIMIT 1
You have to join that query with a query that gets everyone's total.
SELECT t1.*
FROM (
SELECT username, SUM(qvalue) AS score FROM trivia_scoreboard
WHERE `date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND `date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
) AS t1
JOIN (
SELECT SUM(qvalue) AS score FROM trivia_scoreboard
WHERE `date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND `date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
ORDER BY score DESC
LIMIT 1
) AS t2 ON t1.score = t2.score
DEMO
You can also phrase this using having:
SELECT ts.username, SUM(ts.qvalue) AS score
FROM trivia_scoreboard fs
WHERE ts.`date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND
ts.`date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
HAVING score = (SELECT SUM(ts2.qvalue) as score
FROM trivia_scoreboard ts2
WHERE ts2.`date` >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+6 DAY AND
ts2.`date` < CURDATE() - INTERVAL DAYOFWEEK(CURDATE())-1 DAY
GROUP BY username
ORDER BY score DESC
LIMIT 1
);
The difference between this and the version using join is really a matter of taste. This might have slightly better performance, because of details about how aggregations scale on larger amounts of data.
Sample Data
id | order_id | instalment_num | date_due
---------------------------------------------------------
1 | 10000 | 1 | 2010-07-09 00:00:00
2 | 10000 | 1 | 2010-09-06 11:39:56
3 | 10001 | 1 | 2014-04-25 15:46:52
4 | 10002 | 1 | 2010-01-11 00:00:00
5 | 10003 | 1 | 2010-01-04 00:00:00
6 | 10003 | 1 | 2016-05-31 00:00:00
7 | 10003 | 1 | 2010-01-08 00:00:00
8 | 10003 | 1 | 2010-01-06 09:06:26
9 | 10004 | 1 | 2010-01-11 11:25:07
10 | 10004 | 1 | 2010-01-12 07:06:42
Desired Result
id | order_id | instalment_num | date_due
---------------------------------------------------------
1 | 10000 | 1 | 2010-07-09 00:00:00
2 | 10000 | 2 | 2010-09-06 11:39:56
3 | 10001 | 1 | 2014-04-25 15:46:52
4 | 10002 | 1 | 2010-01-11 00:00:00
5 | 10003 | 1 | 2010-01-04 00:00:00
8 | 10003 | 2 | 2010-01-06 09:06:26
7 | 10003 | 3 | 2010-01-08 00:00:00
6 | 10003 | 4 | 2016-05-31 00:00:00
9 | 10004 | 1 | 2010-01-11 11:25:07
10 | 10004 | 2 | 2010-01-12 07:06:42
As you can see, I have an instalment_num column which should show the number/index of each row belonging to the order_id, determined by the date_due ASC, id ASC order.
How can I update the instalment_num column like this?
Additional Notes
The date_due column is not unique, and there may be many ids or order_ids with the exact same timestamp.
If the timestamp is the same for two rows belonging to the same order_id, it should order them by id as a fallback.
I require a query which will update this column.
This is how I would do it:
SELECT a.id,
a.order_id,
COUNT(b.id)+1 AS instalment_num,
a.date_due
FROM sample_data a
LEFT JOIN sample_data b ON a.order_id=b.order_id AND (a.date_due>b.date_due OR (a.date_due=b.date_due AND a.id>b.id))
GROUP BY a.id, a.order_id, a.date_due
ORDER BY a.order_id, a.date_due, a.id
UPDATE version attempt:
UPDATE sample_data
LEFT JOIN (SELECT a.id,
COUNT(b.id)+1 AS instalment_num
FROM sample_data a
JOIN sample_data b ON a.order_id=b.order_id AND (a.date_due>b.date_due OR (a.date_due=b.date_due AND a.id>b.id))
GROUP BY a.id) c ON c.id=sample_data.id
SET sample_data.instalment_num=c.instalment_num
For the numbering to begin with 1:
UPDATE sample_data
LEFT JOIN (SELECT a.id,
COUNT(b.id) AS instalment_num
FROM sample_data a
JOIN sample_data b ON a.order_id = b.order_id AND (a.date_due > b.date_due OR (a.date_due=b.date_due AND a.id + 1 > b.id))
GROUP BY a.id) c ON c.id = sample_data.id
SET sample_data.instalment_num = c.instalment_num
You are trying to achieve what ROW_NUMBER with a partition would do using something like SQL Server or Oracle. You can simulate this with an approriate query:
SELECT t.id, t.order_id,
(
SELECT 1 + COUNT(*)
FROM sampleData
WHERE (date_due < t.date_due OR (date_due = t.date_due AND id < t.id)) AND
order_id = t.order_id
) AS instalment_num,
t.date_due
FROM sampleData t
ORDER BY t.order_id, t.date_due
This query will order the instalment_num by due_date in ascending order. And in the case of a tie in due_date, it will order by the id in ascending order.
Follow the link below for a demo:
SQLFiddle
select
sub.order_id, sub.date_due,
#group_rn:= case
when #group_order_id=sub.order_id then #group_rn:=#group_rn:+1
else 1
end as instalment_num,
#group_order_id:=sub.order_id
FROM (select #group_rn:=0, group_order_id=0) init,
(select *
from the_table
order by order_id, date_due) sub