I have the following query:
SELECT from_unixtime(table1.eventTime, '%Y %D %M') AS DAY, table1.ID, table1.eventTime, COUNT(*)
FROM table1 table1
GROUP BY from_unixtime(table1.eventTime, '%Y %D %M'), table1.ID, table1.eventTime
This is giving me the following output:
DAY ID eventTime COUNT(*)
2017 10th November 815 1510275600 1
2017 10th November 902 1510275600 1
2017 10th November 1202 1510275600 1
2017 10th November 1202 1510279200 1
2017 10th November 1202 1510282800 1
2017 10th November 1202 1510286400 1
2017 10th November 1342 1510275600 1
2017 10th November 1404 1510275600 1
2017 10th November 1404 1510275600 1
How can i achieve this?
DAY ID eventTime COUNT(*)
2017 10th November 815 1510275600 1
2017 10th November 902 1510275600 1
2017 10th November 1202 1510275600 1
2017 10th November 1202 1510279200 2
2017 10th November 1202 1510282800 3
2017 10th November 1202 1510286400 4
2017 10th November 1342 1510275600 1
2017 10th November 1404 1510275600 1
2017 10th November 1404 1510275600 2
In fact what i need is to group by day and based on the eventTime to make a numbering where the ID is same.
You are basically after mysql row number simulation. There are loads of examples in SO and here's another
drop table if exists t;
create table t
(Dt date, ID int ,eventtime int);
insert into t values
('2017-11-10' ,815 ,1510275600),
('2017-11-10' ,902 ,1510275600),
('2017-11-10' ,1202 ,1510275600),
('2017-11-10' ,1202 ,1510279200),
('2017-11-10' ,1202 ,1510282800),
('2017-11-10' ,1202 ,1510286400),
('2017-11-10' ,1342 ,1510275600),
('2017-11-10' ,1404 ,1510275600),
('2017-11-10' ,1404 ,1510275600);
select dt,id,eventtime,
if(id <> #p,#rn:=1,#rn:=#rn+1) rownumber,
#p:=id p
from t , (select #rn:=0,#p:=0) r
order by id,dt,eventtime
result
+------------+------+------------+-----------+------+
| dt | id | eventtime | rownumber | p |
+------------+------+------------+-----------+------+
| 2017-11-10 | 815 | 1510275600 | 1 | 815 |
| 2017-11-10 | 902 | 1510275600 | 1 | 902 |
| 2017-11-10 | 1202 | 1510275600 | 1 | 1202 |
| 2017-11-10 | 1202 | 1510279200 | 2 | 1202 |
| 2017-11-10 | 1202 | 1510282800 | 3 | 1202 |
| 2017-11-10 | 1202 | 1510286400 | 4 | 1202 |
| 2017-11-10 | 1342 | 1510275600 | 1 | 1342 |
| 2017-11-10 | 1404 | 1510275600 | 1 | 1404 |
| 2017-11-10 | 1404 | 1510275600 | 2 | 1404 |
+------------+------+------------+-----------+------+
9 rows in set (0.00 sec)
Related
I am trying to get the number of appointments for each month.
The results are grouped into each month for a rolling-12-months graph.
I have the following Query:
SELECT a.time AS appointmentdatetime,
m.text AS ref_month_text,
m.month AS ref_month_int,
YEAR(TIME) AS appointmentyear,
COUNT(a.id) AS COUNT
FROM ref_months m LEFT JOIN
appointment a
ON m.month = MONTH(a.time) AND
a.time >= DATE_ADD(NOW(), INTERVAL - 12 MONTH)
AND a.dealershipid = '1' AND a.dealerstatus != 'No-Show'
GROUP BY m.month
ORDER BY appointmentyear ASC, m.month ASC
This is the result:
+----------------+--------------------+-------+--+
| ref_month_text | appointmentyear | COUNT | |
+----------------+--------------------+-------+--+
| February | 2019 | 16 | |
| March | 2019 | 18 | |
| April | 2019 | 10 | |
| May | 2019 | 15 | |
| June | 2019 | 18 | |
| July | 2019 | 10 | |
| August | 2019 | 12 | |
| September | 2019 | 20 | |
| October | 2019 | 7 | |
| November | 2019 | 13 | |
| December | 2019 | 7 | |
| January | 2020 | 11 | |
+----------------+--------------------+-------+--+
The grouping by month, on a rolling-12-months, and showing null when no data, is what I am getting, but the issue I am having is that the count is wrong for each month.
Eg. March 2019 should be 20.
I have tried all variations of JOIN types. But still returning wrong figures.
I simplified your query
SELECT
YEAR(a.time) AS year,
ANY_VALUE(MONTHNAME(a.time)) AS month,
ANY_VALUE(COUNT(a.id)) AS counter,
MONTH(a.time) AS mo
FROM
appointment AS a
GROUP BY
year,mo
ORDER BY
year ASC,
mo ASC
these are my tables
RESERVATIONS
+--------+--------------------+-----------------+
| id | reservation_date | reservation_time|
+--------+--------------------+-----------------+
| 1 | November 05, 2019 | 9:00am-12:00pm |
| 2 | November 05, 2019 | 12:00pm-3:00pm |
| 3 | November 05, 2019 | 3:00pm-6:00pm |
| 4 | November 05, 2019 | 6:00pm-9:00pm |
| 5 | November 06, 2019 | 9:00am-12:00pm |
| 6 | November 06, 2019 | 12:00pm-3:00pm |
| 7 | November 06, 2019 | 3:00pm-6:00pm |
| 8 | November 12, 2019 | 9:00am-12:00pm |
| 9 | November 13, 2019 | 9:00am-12:00pm |
+--------+--------------------+-----------------+
reservation_date is in VARCHAR format
TIME_AVAILABILITY
+--------+------------------+
| id | reservation_time |
+--------+------------------+
| 1 | 9:00am-12:00pm |
| 2 | 12:00pm-3:00pm |
| 3 | 3:00pm-6:00pm |
| 4 | 6:00pm-9:00pm |
+--------+------------------+
so here's the thing, I want to display the values in my TIME_AVAILABILITY table based on a $_POST variable and RESERVATIONS table. For example if a user's input is November 05, 2019 It will display nothing because all the values in TIME_AVAILABILITY table are already in the RESERVATIONS table, but if the user input is November 06, 2019 it will only display 6:00pm-9:00pm
I tried using INNER JOIN but I just can't make it work
The TIME_AVAILABILITY table joined to a subquery of the RESERVATIONS table will produce only the null matches (which is what you are looking for since null represents a TIME_AVAILABILITY that has not been filled for the date put in the where clause your "POST" date as it were):
select t.reservation_time
from TIME_AVAILABILITY t
left join (
select reservation_time, reservation_date
from RESERVATIONS
where reservation_date = 'November 05, 2019'
) as q
on t.reservation_time = q.reservation_time
where q.reservation_date is null;
Alternative to above answer you can do it with not in clause.
select t.reservation_time
from TIME_AVAILABILITY t where t.reservation_time not in (
select reservation_time
from RESERVATIONS
where reservation_date = 'November 05, 2019'
)
I am trying to find previous flight from the historical flight table, i have only 1 historical table wit tail number of plane and scheduled date departure in it, i want to make a new table with information of previous flight from that plane, below is example of the table
Original Table :
|flight number|scheduled departure flight|
| A | 1 Jan 2018 10:00 |
| A | 1 Jan 2018 19:00 |
| B | 1 Jan 2018 11:00 |
| B | 1 Jan 2018 19:00 |
| B | 1 Jan 2018 21:00 |
Result expected :
|flight number|scheduled departure flight| previous scheduled departure |
| A | 1 Jan 2018 10:00 | NULL |
| A | 1 Jan 2018 19:00 | 1 Jan 10:00 |
| B | 1 Jan 2018 11:00 | NULL |
| B | 1 Jan 2018 19:00 | 1 Jan 2018 11:00 |
| B | 1 Jan 2018 21:00 | 1 jan 2018 19:00 |
i have been working on it for a day, appreciate any help from you
You are looking for LAG window function, but which support mysql version higher than 8.0
You can try to use a subquery to make a lag window function.
Schema (MySQL v5.7)
Query #1
SELECT `flight number`,
`scheduled departure flight`,
(select `scheduled departure flight`
from T tt
where t1.`scheduled departure flight` > tt.`scheduled departure flight`
AND t1.`flight number` = tt.`flight number`
order by tt.`scheduled departure flight` desc
limit 1
) 'previous scheduled departure'
FROM T t1;
| flight number | scheduled departure flight | previous scheduled departure |
| ------------- | -------------------------- | ---------------------------- |
| A | 2018-06-01 10:00:00 | |
| A | 2018-06-01 19:00:00 | 2018-06-01 10:00:00 |
| B | 2018-06-01 11:00:00 | |
| B | 2018-06-01 19:00:00 | 2018-06-01 11:00:00 |
| B | 2018-06-01 21:00:00 | 2018-06-01 19:00:00 |
View on DB Fiddle
If your mysql version support LAG you can try this.
Schema (MySQL v8.0)
CREATE TABLE T(
`flight number` varchar(5),
`scheduled departure flight` datetime
);
INSERT INTO T VALUES ('A','2018-06-01 10:00');
INSERT INTO T VALUES ('A','2018-06-01 19:00');
INSERT INTO T VALUES ('B','2018-06-01 11:00');
INSERT INTO T VALUES ('B','2018-06-01 19:00');
INSERT INTO T VALUES ('B','2018-06-01 21:00');
Query #1
SELECT `flight number`,
`scheduled departure flight`,
LAG(`scheduled departure flight`) OVER(PARTITION BY `flight number` ORDER BY `scheduled departure flight`) 'previous scheduled departure'
FROM T t1;
View on DB Fiddle
I have the following data in my webinar_timing table in mysql database
start_time and end_time are of type datetime
id | webinar_id | start_time | end_time
-------------------------------------------------------------------
1 | 5 | 3/18/2015 6:00:00 PM | 3/18/2015 7:00:00 PM
2 | 5 | 3/19/2015 6:00:00 PM | 3/19/2015 7:00:00 PM
3 | 5 | 3/20/2015 6:00:00 PM | 3/20/2015 7:00:00 PM
4 | 5 | 3/21/2015 6:00:00 PM | 3/21/2015 7:00:00 PM
5 | 5 | 3/22/2015 6:00:00 PM | 3/22/2015 7:00:00 PM
6 | 11 | 3/20/2015 8:00:00 PM | 3/20/2015 9:00:00 PM
7 | 11 | 3/21/2015 8:00:00 PM | 3/21/2015 9:00:00 PM
8 | 11 | 3/22/2015 8:00:00 PM | 3/22/2015 9:00:00 PM
9 | 22 | 3/25/2015 8:00:00 PM | 3/25/2015 9:00:00 PM
10 | 22 | 3/27/2015 8:00:00 PM | 3/27/2015 9:00:00 PM
11 | 22 | 3/29/2015 8:00:00 PM | 3/27/2015 9:00:00 PM
Basically, for each webinar, I want the total occurences and number of classes completed or remaining AND the NEXT upcoming class
Egs: When I run this query say at 3/21/2015 at 4:00 PM - this is the result I am expecting
webinar_id | total | Classes Completed | Next Class
----------------------------------------------------------
5 | 5 | 3 | 3/21/2015 6:00:00 PM
11 | 3 | 1 | 3/21/2015 8:00:00 PM
22 | 3 | 0 | 3/25/2015 8:00:00 PM
OR
webinar_id | total | Classes Remaining | Next Class
----------------------------------------------------------
5 | 5 | 2 | 3/21/2015 6:00:00 PM
11 | 3 | 2 | 3/21/2015 8:00:00 PM
22 | 3 | 3 | 3/25/2015 8:00:00 PM
Based on a previous question - a fellow SO Peter assisted with the following
select webinar_id, count(*) AS total,
SUM(IF(end_time<NOW(), 1, 0)) AS completed,
SUM(IF(start_time>=NOW(), 1, 0)) AS remaining
from webinar_times
group by webinar_id;
SQL Fiddle
http://sqlfiddle.com/#!9/c4e71/1
Any help will be appreciated
Thanks in advance
Something like:
select webinar_id
, count(*) AS total
, count(case when end_time<NOW() then 1 end) as completed
, (select count(1)
from webinar_times y
where x.webinar_id = y.webinar_id
and y.start_time > NOW()) as remaining
, min(case when x.start_time > NOW() then x.start_time end) as next_class
from webinar_times x
group by webinar_id;
should do
EDIT: realized that the sub-select is un-necessary:
select webinar_id
, count(*) AS total
, count(case when end_time<NOW() then 1 end) as completed
, count(case when start_time>NOW() then 1 end) as remaining
, min(case when x.start_time > NOW() then x.start_time end) as next_class
from webinar_times x
group by webinar_id;
You can make an outer join between two grouped queries, e.g. one that counts the total number of webinars and another that both counts the remaining webinars and obtains the start time of the next one:
SELECT * FROM (
SELECT webinar_id, COUNT(*) total
FROM webinar_times
GROUP BY webinar_id
) totals NATURAL LEFT JOIN (
SELECT webinar_id, COUNT(*) remaining, MIN(start_time) next
FROM webinar_times
WHERE start_time > NOW()
GROUP BY webinar_id
) future
See it on sqlfiddle:
+------------+-------+-----------+-------------------------+
| webinar_id | total | remaining | next |
+------------+-------+-----------+-------------------------+
| 6 | 5 | 1 | March, 22 2015 06:00:00 |
| 11 | 3 | 1 | March, 22 2015 07:00:00 |
| 22 | 3 | 3 | March, 25 2015 07:00:00 |
+------------+-------+-----------+-------------------------+
A composite index defined over (webinar_id, start_time) would benefit this query, and avoids the full table scans that the approach outlined in your question would otherwise require.
Consider the following example and this will give you what you need
mysql> create table test (id int, webinar_id int, start_time datetime);
Query OK, 0 rows affected (0.16 sec)
mysql> insert into test values (1,5,'2015-03-18 18:00:00'),
(2,5,'2015-03-19 18:00:00'),
(3,5,'2015-03-20 18:00:00'),
(4,5,'2015-03-21 18:00:00'),
(5,5,'2015-03-21 18:00:00'),
(6,11,'2015-03-20 20:00:00'),
(7,11,'2015-03-21 20:00:00'),
(8,11,'2015-03-22 20:00:00'),
(9,22,'2015-03-25 20:00:00'),
(10,22,'2015-03-27 20:00:00'),
(11,22,'2015-03-29 20:00:00');
Query OK, 11 rows affected (0.05 sec)
Records: 11 Duplicates: 0 Warnings: 0
mysql> select * from test ;
+------+------------+---------------------+
| id | webinar_id | start_time |
+------+------------+---------------------+
| 1 | 5 | 2015-03-18 18:00:00 |
| 2 | 5 | 2015-03-19 18:00:00 |
| 3 | 5 | 2015-03-20 18:00:00 |
| 4 | 5 | 2015-03-21 18:00:00 |
| 5 | 5 | 2015-03-21 18:00:00 |
| 6 | 11 | 2015-03-20 20:00:00 |
| 7 | 11 | 2015-03-21 20:00:00 |
| 8 | 11 | 2015-03-22 20:00:00 |
| 9 | 22 | 2015-03-25 20:00:00 |
| 10 | 22 | 2015-03-27 20:00:00 |
| 11 | 22 | 2015-03-29 20:00:00 |
+------+------------+---------------------+
11 rows in set (0.00 sec)
select
t.webinar_id,
count(*) as total,
sum( case when t.start_time < now() then 1 else 0 end) as completed ,
sum( case when t.start_time > now() then 1 else 0 end) as remaining,
t1.next_date from test t
join (
select
webinar_id,
min(start_time) as next_date
from test where start_time > now()
group by webinar_id
)t1 on t.webinar_id= t1.webinar_id
group by t.webinar_id;
+------------+-------+-----------+-----------+---------------------+
| webinar_id | total | completed | remaining | next_date |
+------------+-------+-----------+-----------+---------------------+
| 5 | 5 | 3 | 2 | 2015-03-21 18:00:00 |
| 11 | 3 | 1 | 2 | 2015-03-21 20:00:00 |
| 22 | 3 | 0 | 3 | 2015-03-25 20:00:00 |
+------------+-------+-----------+-----------+---------------------+
3 rows in set (0.00 sec)
I will be getting some data which I need to filter out based on some conditions. Sample data:
Cust_ID Date Result
1 2013-08-15 On hold
2 2013-08-16 NULL
3 2013-08-18 WIP
1 2013-08-20 Completed
3 2013-08-25 NULL
4 2013-08-28 NULL
4 2013-08-29 NULL
Conditions:
Fetch the distinct Cust_ID, based on latest Date.(i.e Max(Date))
If the Result is Null for latest Date then get the latest record with any other Result apart from NULL.
If the Result is NULL for all the records with same Cust_ID, pick the latest one based on Date
The desired output should be:
Cust_ID Date Result
1 2013-08-20 Completed
2 2013-08-16 NULL
3 2013-08-18 WIP
4 2013-08-29 NULL
Please advise.
You can do it easy with a CTE, note the CTE is not "needed" (you could use sub-queries) but I think it makes it clear what you are doing.
WITH NonNull AS
(
SELECT CustID, MAX(Date) as Date
FROM tablename
GROUP BY CustID
WHERE Result is not null
), Others AS
(
SELECT CustID, MAX(Date) as Date
FROM tablename
GROUP BY CustID
WHERE CustID NOT IN (SELECT CustID FROM NonNull)
), AlltogetherNow -- not really needed but clearer
(
SELECT CustID, Date
FROM NonNull
UNION ALL
SELECT CustID, Date
FROM Others
)
SELECT A.CustID, A.Date, J.Results
FROM AlltogetherNow A
JOIN tablename J ON A.CustID = J.CustID AND A.Date = J.Date
First you need an IS NULL indicator on each row:
SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE dbo.Results
([CustID] int, [Date] datetime, [Result] varchar(9))
GO
INSERT INTO dbo.Results
([CustID], [Date], [Result])
VALUES
(1, '2013-08-15 00:00:00', 'On Hold'),
(2, '2013-08-16 00:00:00', NULL),
(3, '2013-08-18 00:00:00', 'WIP'),
(1, '2013-08-20 00:00:00', 'Completed'),
(3, '2013-08-25 00:00:00', NULL),
(4, '2013-08-28 00:00:00', NULL),
(4, '2013-08-29 00:00:00', NULL)
GO
Query 1:
SELECT *,CASE WHEN Result IS NULL THEN 0 ELSE 1 END IsNotNull
FROM dbo.Results
Results:
| CUSTID | DATE | RESULT | ISNOTNULL |
|--------|-------------------------------|-----------|-----------|
| 1 | August, 15 2013 00:00:00+0000 | On Hold | 1 |
| 2 | August, 16 2013 00:00:00+0000 | (null) | 0 |
| 3 | August, 18 2013 00:00:00+0000 | WIP | 1 |
| 1 | August, 20 2013 00:00:00+0000 | Completed | 1 |
| 3 | August, 25 2013 00:00:00+0000 | (null) | 0 |
| 4 | August, 28 2013 00:00:00+0000 | (null) | 0 |
| 4 | August, 29 2013 00:00:00+0000 | (null) | 0 |
Then you need to determine the first NULL row and the first NOT NULL row for each customer. You can use the ROW_NUMBER() function for that. You also need to know for each customer if there are any NOT NULL rows:
Query 2:
SELECT *,
ROW_NUMBER()OVER(PARTITION BY CustID,IsNotNull ORDER BY [Date] DESC) _rn,
COUNT(Result)OVER(PARTITION BY CustID) NotNullCount
FROM(
SELECT *,CASE WHEN Result IS NULL THEN 0 ELSE 1 END IsNotNull
FROM dbo.Results
)X1
Results:
| CUSTID | DATE | RESULT | ISNOTNULL | _RN | NOTNULLCOUNT |
|--------|-------------------------------|-----------|-----------|-----|--------------|
| 1 | August, 20 2013 00:00:00+0000 | Completed | 1 | 1 | 2 |
| 1 | August, 15 2013 00:00:00+0000 | On Hold | 1 | 2 | 2 |
| 2 | August, 16 2013 00:00:00+0000 | (null) | 0 | 1 | 0 |
| 3 | August, 25 2013 00:00:00+0000 | (null) | 0 | 1 | 1 |
| 3 | August, 18 2013 00:00:00+0000 | WIP | 1 | 1 | 1 |
| 4 | August, 29 2013 00:00:00+0000 | (null) | 0 | 1 | 0 |
| 4 | August, 28 2013 00:00:00+0000 | (null) | 0 | 2 | 0 |
Finally you can just filter out the first NOT NULL row if there are any or the first NULL row if there are no NOT NULL rows by using the calculated row number:
Query 3:
SELECT CustID,[Date],Result
FROM(
SELECT *,
ROW_NUMBER()OVER(PARTITION BY CustID,IsNotNull ORDER BY [Date] DESC) _rn,
COUNT(Result)OVER(PARTITION BY CustID) NotNullCount
FROM(
SELECT *,CASE WHEN Result IS NULL THEN 0 ELSE 1 END IsNotNull
FROM dbo.Results
)X1
)X2
WHERE _rn = 1 AND SIGN(NotNullCount) = IsNotNull
Results:
| CUSTID | DATE | RESULT |
|--------|-------------------------------|-----------|
| 1 | August, 20 2013 00:00:00+0000 | Completed |
| 2 | August, 16 2013 00:00:00+0000 | (null) |
| 3 | August, 18 2013 00:00:00+0000 | WIP |
| 4 | August, 29 2013 00:00:00+0000 | (null) |