'WHERE' clause does not work with both conditions - mysql

SHOW CREATE TABLE:
CREATE TABLE `calls` (
`fullname` varchar(201) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
`lastname` text COLLATE utf8_unicode_ci,
`firstname` text COLLATE utf8_unicode_ci,
`call` datetime DEFAULT NULL,
`phoneNumber` char(12) COLLATE utf8_unicode_ci DEFAULT NULL,
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
call stores information regarding the date and time of the call made by the user
I am trying to select all the persons that called at least three times between 8 P.M. and 10 P.M. in the last month.
My query:
SELECT fullname, call, COUNT(fullname) AS NumberOfCalls
FROM calls
WHERE HOUR(call) IN (20,21) AND datediff(CURDATE(), call) < 30
GROUP BY fullname
HAVING NumberOfCalls >= 3;
The query does not provide a result.
If i comment /* AND datediff(CURDATE(), call) < 30 */ i get all persons that called between 8 pm and 10 pm.
If i comment /* HOUR(call) IN (20,21) AND */ i get all persons that called in the last month.
The WHERE clause does not work with both conditions, and I do not understand why. How can i make it accept both conditions? Thank you!

Based on your description, I think your code should work. The call in the SELECT is inappropriate (because it is not part of the GROUP BY). And I recommend direct comparisons on the date/time values:
SELECT fullname, COUNT(*) AS NumberOfCalls
FROM calls c
WHERE HOUR(call) IN (20, 21) AND call >= curdate() - interval 30 day
GROUP BY fullname
HAVING NumberOfCalls >= 3;

Related

Item exclusions by date in MySQL

I have a very simple reservations system I have built for an RV Park. It only has 8 RV parking spaces in it. The issue I am having is it seems the available RV spots for reservation is spotty at best. Each spot has a check out time of 11am and a check in time of 2pm similar to a hotel.
Effectively a user hits the site, choose an arrival and departure date and clicks search. A list then shows up from an ajax query that shows all 8 RV spots and whether or not they are available for reservation. Apparently I have something effed up in my query that is not taking into consideration whether the arrival date falls into a range of dates for another reservation.
I have read a couple of other similar but not the same questions on SE and none of the proposed solutions fixed what I needed since I am not combining any other tables or keys. This is a simple 1 table system that is basically just a record of the registrations.
$sql = "SELECT id AS rid, sid, paid, arriveDate, departDate FROM saved_reservations
WHERE
arriveDate BETWEEN ".$db->quote($formattedArrival.' 14:00:00')." AND ".$db->quote($formattedDeparture.' 11:00:00')."
OR
departDate BETWEEN ".$db->quote($formattedArrival.' 14:00:00')." AND ".$db->quote($formattedDeparture.' 11:00:00')."
";
$sql .= " AND paid = 1 ORDER BY arriveDate ASC";
sid is the ID of the specific RV site. Just a numeric value 1-8.
I think where I am going wrong is my system is not picking up reservations from before the submitted arrival date but I am not 100% sure. Any ideas or suggestions for this query?
Here is my table structure:
CREATE TABLE `saved_reservations` (
`id` int(4) NOT NULL,
`sid` int(2) NOT NULL,
`arriveDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`departDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`paid` tinyint(1) NOT NULL DEFAULT '0',
`amount` int(4) NOT NULL,
`payment_date` int(15) NOT NULL,
`txn_id` varchar(100) NOT NULL,
`first_name` varchar(65) NOT NULL,
`last_name` varchar(65) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(15) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Saved Reservations';
You query does not take into consideration a case when existing reservation is within desired reservation interval.
Anyway, here is my take on your problem, given user inputs are arriveDate and departDate the logic should be as follows.
# find unavailable sports for provided period
select sid from reservations R where arriveDate < R.departDate and departDate > R.arriveDate
# find available spots for provided period
select sid from reservations R where not (arriveDate < R.departDate and departDate > R.arriveDate)
SQL Fiddle

How to get average sum for every weekday? (MySQL)

I'm struggling with one task - I need to get average number of users for every weekday. Unfortunately, I'm stuck at this point.
SELECT dayname(DAY) as week, SUM(VISITORS_NUMBER) as vis
FROM mytable
GROUP BY week
The result of code above looks like this Sum results
From this moment I want to get same weekday column but with average values.
What can I do? I've tried subqueries, but I'm still a beginner and can't use it properly
Edit 1:
AVG() is not working. I'm getting results like this: AVG() RESULTS
I checked in excel, average for friday should be 572, not 53.
That's how my dataset looks like: Data set
edit 2:
CREATE TABLE `mytable` (
`DAY` date NOT NULL,
`BROWSER` varchar(22) COLLATE utf8_unicode_ci DEFAULT NULL,
`PLATFORM` varchar(13) COLLATE utf8_unicode_ci DEFAULT NULL,
`VISITORS_NUMBER` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
INSERT INTO mytable(DAY, BROWSER, PLATFORM,VISITORS_NUMBER)
VALUES('2020-02-01','Android Webkit Browser','Android','9'),
('2020-02-01','Safari','iOs','5'),
('2020-02-01','Android Webkit Browser','Android','15');
Test
SELECT DAYNAME(`day`) as `week`, SUM(visitors_number) / COUNT(DISTINCT `day`) as avg_vis
FROM mytable
GROUP BY `week`
You need 2 levels of aggregation:
SELECT DAYNAME(t.day) AS day, AVG(t.visitors) AS vis
FROM (
SELECT day, SUM(VISITORS_NUMBER) AS visitors
FROM mytable
GROUP BY day
) t
GROUP BY DAYNAME(t.day)
See a simplified demo.

MySQL AVG TIME Duration Calculation and Related Functions?

table with login data of the website users with two datetime columns. One is logged in time and other one is logged out time.
table has following columns
user_id (user id of the
datetime (start login time DATETIME )
datetime_end (end logout time DATETIME)
From this data I need to generate a report or calculate the following
Daily AVG Login Duration for Users (i.e 01 March 2015 its 21 mins , 03 November 2016 its 25 mins ..etc )
second report is
Current Day (Last 24 hours) based on Hour AVG Login Duration (i.e same as above but only per hour AVG)
is there a way i can achieve this via MySQL query ? (or SQL query)
table is create is
CREATE TABLE IF NOT EXISTS `users_login` (
`login_id` int(11) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL DEFAULT '0',
`last_ip` varchar(45) NOT NULL DEFAULT '0.0.0.0',
`server_ip` varchar(225) DEFAULT '0.0.0.0',
`country` varchar(2) NOT NULL DEFAULT '00',
`continent` tinytext,
`datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`datetime_end` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Something like this for the first one
SELECT DATE(datetime),AVG(TIMESTAMPDIFF(MINUTE,datetime,datetime_end)) as DailyAvg
FROM users_login
GROUP BY DATE(datetime)
And for hourly :
SELECT DATE(datetime),extract(hour from datetime) as HourCol,
AVG(TIMESTAMPDIFF(MINUTE,datetime,datetime_end)) as HourlyAvg
FROM users_login
WHERE DATE(datetime) = date(now())
GROUP BY DATE(datetime),extract(hour from datetime)
Of course this queries have a few exceptions.. You didn't explain you entire logic so I assumed you want to group by the hour of the login and the date of the login..

Mysql Subquery between specific dates

I'm a newbie to MySQL querying and need some assistance with the subqueries.
I am using ASP .NET charting control that retrieves data from MySQL.I want to display a drill down chart and need some help on MySQL subquery.
Below is my table:
CREATE TABLE IF NOT EXISTS `data` (
`runtime` smallint(6) NOT NULL,
`app` varchar(60) NOT NULL,
`process` varchar(40) NOT NULL,
`username` varchar(51) NOT NULL,
`time` time NOT NULL,
`date` date NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Step 1 :
Showing a pie chart of Top 10 users with highest time between 2 dates.
I get the top 10 users used between 2 dates using the below query:
SELECT username ,SUM(runtime) as Runtime,
process,ROUND(SUM(runtime/201600),2) as 'Total Time',
role ,
date
FROM data
WHERE `date` BETWEEN 'date1' AND 'date2'
Group BY process LIMIT 10.
Step 2:
When user clicks on the individual user in chartArea, I wan to display the top 10 apps/process between specific dates.

Return multiple copies slightly modified

In my events table there are records that have a daily flag that indicate that this event must be repeated each day:
CREATE TABLE IF NOT EXISTS `events` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`start` datetime DEFAULT NULL,
`title` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`description` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`daily` tinyint(1) NOT NULL,
) ENGINE=InnoDB;
When I try to fill a calendar with this data I need a row for each item, it is, if the calendar ask for all events this week, daily flaged events must return 7 events (one for each week day) with the same data (title, description, etc), but with a different start day.
Is it possible to do from MySQL?
Usually I would use a table that contains each of the single date.
Example
create table daily
(
/* FYI, date is not a reserved keyword */
date date
);
insert into daily values ('2011-09-11'), ('2011-09-12'),
('2011-09-13'), ('2011-09-14'), ('2011-09-15'),
('2011-09-16'), ('2011-09-17');
alter table daily add index (date);
select daily.date as daily_date,
weekly.start, weekly.id, weekly.title, weekly.description
from daily
inner join
(
select events.id, events.title,
events.description, events.start, events.daily
from events
where events.start between '2011-09-11' and '2011-09-17'
) as weekly
on date(weekly.start)=daily.date
union
/* query for recurr */
select daily.date as daily_date,
recurr.start, recurr.id, recurr.title, recurr.description
from daily
inner join
(
select events.id, events.title,
events.description, events.start, events.daily
from events
where events.daily=1 AND events.start between '2011-09-11' and '2011-09-17'
)as recurr
on date(recurr.start)<=daily.date
order by daily_date;
It would be more efficient if you break the start column to two column (date, time).
The drawback of this method is on the pre-create of table daily and loaded it with lots of day value.
This should be one time cost and can easily inserted via a for.
Alternatively, you can do a repeat of (from a week start to week end) on the query for recurr