Query - Find new and repeating users in MySQL - php

I have a visit table with user_id and visited_at columns. I would like to find how many are new and repeat customer in this month.
user_id visited_at
--------------------------------------------------------------------------
1750 2015-04-06 10:39:20
1870 2015-04-05 15:48:11
1990 2015-04-04 12:38:35
1920 2015-04-03 10:18:21
1080 2015-04-01 10:18:21
1750 2015-01-28 12:38:59
1920 2015-01-19 17:20:20
1920 2015-01-17 15:10:10
1080 2015-01-13 20:18:41
1920 2014-04-04 10:31:15
1750 2013-10-04 10:39:20
In January 2015, user 1750 and 1920 visited the same place so total repeated customers are 2. In April 2015, user 1750, 1920 and 1080 visited the same place so total repeated customers are 3. The output should be something like this
Month New Repeat
----------------------------------------------
October 2013 1 0
April 2014 1 0
January 2015 1 2
April 2015 2 3

One approach is to get the date of the first visit for each user using a subquery. Then join in this information, and use count(distinct) to count the number of users:
select year(v.visited_at) as yyyy, month(visited_at) as mm,
count(distinct user_id) as num_users,
count(case when v.visited_at = vv.minva then user_id end) as num_new_users
from visits v join
(select user_id, min(visited_at) as minva
from visits t
group by user_id
) vv
on v.user_id = vv.user_id
group by year(v.visited_at), month(visited_at)
order by year(v.visited_at), month(visited_at);
I note that this gives the total and new users; the repeats are the difference.

Something like this will work:
SELECT * FROM table_name WHERE updated_at >= CAST('2014-02-01' AS DATE) AND updated_at <= CAST('2014-02-28' AS DATE);

SELECT
MONTH(created_at) as _Month,
YEAR(created_at) as _Year,
COUNT(*) as New
FROM
yourtable
GROUP BY 0,1
You can also filter results using where clause.

Related

PHP/SQL - How to count saturdays in each month?

I have two MySQL tables, called "accounts" and "events".
Accounts
ID
name
1
Pete
2
Josh
3
Harry
Events
ID
date
account_id
1
2021-10-09
1
2
2021-09-25
1
3
2021-10-23
2
4
2021-11-06
1
5
2021-10-13
1
6
2021-11-17
2
7
2021-11-06
3
8
2021-12-04
3
The account_id in the events table is linked to the id in the accounts table.
My question is: which query can I use to count saturdays in each month (date YYYY-mm-dd format) for each unique user in the accounts table? So I get the next result:
Name
September
October
November
December
Josh
0
1
0
0
Pete
1
1
1
0
Harry
0
0
1
1
I've tried many queries (with i.e. the (inner) JOIN, DISTINCT and GROUP BY keywords) but I don't get the exact result. Can you please help me?
Many thanks in advance!
Basically you can use DAYOFWEEK function and GROUP BY MONTH
SELECT
account_id,
MONTH(date),
COUNT(*)
FROM Events
WHERE DAYOFWEEK(date) = 7
GROUP BY account_id, MONTH(date);
SQL Fiddle here
and when you can use PIVOT on received table like:
WITH res AS (
SELECT
account_id,
MONTH(date) mnth,
COUNT(*) cnt
FROM Events
WHERE DAYOFWEEK(date) = 7
GROUP BY account_id, MONTH(date)
) SELECT
account_id,
name,
SUM(mnth=1) Januar,
--
SUM(mnth=9) September,
SUM(mnth=10) October,
SUM(mnth=11) November,
SUM(mnth=12) December
FROM res
JOIN Accounts ON Accounts.id = account_id
GROUP BY account_id, name;
SQL Pivot Fiddle

How to filter the result Mysql

Hard to describe what i want, but I will try:
First of all, i have 2 tables: employee and salary. I joined 2 tables by this SQL command:
"SELECT employee.id, employee.employee_name, employee.image, salary.year, salary.month, salary.day, salary.total_salary, salary.id, salary.created
FROM employee
JOIN salary ON salary.employee_id=employee.id"
to get all value i inserted, after execute, i got:
Created name year month day(working) total_salary
------------------------------------------------------------------------------
2016-12-17 20:41 A 2016 1 31 1550000
2016-12-17 21:49 A 2016 1 20 2000000
2016-12-17 22:49 A 2016 2 20 2000000
2016-12-18 22:43 B 2016 2 15 1550000
2016-12-18 23:43 B 2016 2 10 1000000
2016-12-18 23:49 B 2016 2 1 100000
After that, i want to get the newest value per month, so i add this command to the end of sql above:
GROUP BY employee.employee_name, salary.year, salary.month"
and got this:
Created name year month day(working) total_salary
------------------------------------------------------------------------------
2016-12-17 20:41 A 2016 1 31 1550000
2016-12-17 22:49 A 2016 2 20 2000000
2016-12-18 22:43 B 2016 2 15 1550000
What query will return the following result?
Created name year month day(working) total_salary
------------------------------------------------------------------------------
2016-12-17 21:49 A 2016 1 20 2000000
2016-12-17 22:49 A 2016 2 20 2000000
2016-12-18 23:49 B 2016 2 1 100000
My starting point was after your joins, I just made a table that has the data as your first result.
With this query:
SELECT created, name, year, month, day, total_salary FROM
( SELECT * FROM employees
ORDER BY created DESC
) AS sub
GROUP BY name, month, year;
I've got the results you asked for:
Created name year month day(working) total_salary
------------------------------------------------------------------------------
2016-12-17 21:49 A 2016 1 20 2000000
2016-12-17 22:49 A 2016 2 20 2000000
2016-12-18 23:49 B 2016 2 1 100000
Basically the trick was to handle the ordering before you pack them up into groups with GROUP BY
So I made a subQuery that just handles the ordering. This post helped me figure out how to do this.
Here's a Fiddle where you can play around and adjust it to your starting query.
Before you group you should sort the entries by created date the newest entries are first:
ORDER BY salary.created DESC
Change the first query (you have to remove or alias one of the id's because you will have two columns with the same name):
SELECT employee.id as employee_id, employee.employee_name, employee.image, salary.year, salary.month, salary.day, salary.total_salary, salary.id, salary.created
FROM employee JOIN salary ON salary.employee_id=employee.id
ORDER BY salary.created DESC
So the last created are shown first. Then group the results like you did:
SELECT * FROM (
SELECT employee.id as employee_id, employee.employee_name, employee.image, salary.year, salary.month, salary.day, salary.total_salary, salary.id, salary.created
FROM employee
JOIN salary ON salary.employee_id=employee.id
ORDER BY salary.created DESC
) as employee_salary
GROUP BY employee_salary.employee_name, employee_salary.year, employee_salary.month

check availability of room in hotel

There are two tables in my database. First table is room and second table is reservation. In my room table
id room_no type rate
1 13 1b 1000
2 14 2b 2000
3 15 3b 3000
4 16 1b 1000
5 17 2b 2000
6 18 3b 3000
In my reservation table
id room_no check_in check_out
1 13 23-2-2016 24-2-2016
2 14 24-2-2016 25-2-2016
1 13 25-2-2016 26-2-2016
1 13 27-2-2016 29-2-2016
1 13 1-3-2016 2-3-2016
1 13 7-3-2016 7-3-2016
"SELECT room_no,type,rate
FROM room
WHERE room_no not in
(select IFNULL(GROUP_CONCAT(room_no),0)
FROM reservation
WHERE check_out >= '$check_in' AND check_in <= '$check_out')"
when I select a date 24-2-2016 to 27-2-2016 then it display
room_no check_in check_out
14 24-2-2016 25-2-2016
15 25-2-2016 26-2-2016
16 27-2-2016 29-2-2016
17 1-3-2016 2-3-2016
18 7-3-2016 7-3-2016
but I want all available rooms.
To get occupied rooms for the period specified, i.e '2016-02-27'-'2016-02-24', you can use:
SELECT DISTINCT room_no
FROM reservation
WHERE check_in <= '2016-02-27' AND check_out >= '2016-02-24'
Output:
room_no
=======
13
14
To get available rooms you can use the previous query like this:
SELECT *
FROM room
WHERE room_no NOT IN (
SELECT DISTINCT room_no
FROM reservation
WHERE check_in <= '2016-02-27' AND check_out >= '2016-02-24')
Output:
id, room_no, type, rate
=======================
3, 15, 3b, 3000
4, 16, 1b, 1000
5, 17, 2b, 2000
6, 18, 3b, 3000
Demo here
Using a LEFT JOIN should do the trick without using a subquery.
Something like this :
SELECT
room.room_no,
room.`type`,
room.rate,
COUNT(reservation.room_no) AS countReservation
FROM
room
LEFT JOIN reservation
ON (room.room_no = reservation.room_no)
AND (check_in <= '2016-02-24' AND check_out >= '2016-01-27')
GROUP BY
room.room_no
HAVING
countReservation = 0
An other advantage in this query is the extra column countReservation that will even tell you if you have 1 or more reservations for the for the given timeframe for each room.
You should use something like this:
"SELECT room_no, type, rate
FROM room
WHERE room_no not in
(select room_no FROM reservation
WHERE ('$check_in' BETWEEN check_in AND check_out) AND ('$check_out' BETWEEN check_in AND check_out))"
I don't know if the query is correct, but you surely have to check for between.
You can't just test for check_out > than date, and check_in < date. IF you have multiple reservations this will give you Errors!!

Show MySQL Count Including Zero Count with Group By Statement

I am generating mysql query to show the number of orders received in current month group by days of month.
The table structure of mysql is as follow:
order_id date
======== ==========
1234 2012-07-02
1235 2012-07-02
1236 2012-07-04
1237 2012-07-07
1238 2012-07-08
Now I want it to return following results using mysql statement
count(order_id) day
=============== ===
0 01
2 02
0 03
1 04
0 05
0 06
1 07
1 08
So on and so forth till the end of the month 30/31 depends on the days in month.
Looking forward to your suggestions and help.
Thanks.
SELECT
count(order_id),
dates.dte
FROM
(
SELECT '2011-02-01' + INTERVAL a + b DAY dte
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
UNION SELECT 8 UNION SELECT 9 ) d,
(SELECT 0 b UNION SELECT 10 UNION SELECT 20
UNION SELECT 30 UNION SELECT 40) m
WHERE '2011-02-01' + INTERVAL a + b DAY < '2011-03-01'
ORDER BY a + b
) dates
LEFT JOIN
orders ON orders.`date` = dates.dte
GROUP BY
dates.dte
ORDER BY
dates.dte
generate day column values in your programming language
Thanks to #The Scrum Master for nice answer here
but I also agree this shouldn't be done in database. if you think about it you actually don't need rows with 0 count.
Prepare the calendar table with a list of months and days.
To retrieve all orders from 2012-07:
select day(c.date), count(*)
from calendar c
left join orders o on c.date=o.date
where year(c.date) = 2012
and month(c.date) = 07
group by day(c.date)

PHP mysql get subtraction between 2 dates

I have table structure like this:
Id Name Rank Date
-----------------------------------
1 test 1000 2012-1-11
2 test 7000 2012-1-10
3 test2 2000 2012-1-11
4 test2 200 2012-1-10
5 test3 4000 2012-1-10
6 test4 6500 2012-1-11
Consider today date is 2012-1-11
Yesterday date is 2012-1-10
In single query i get the difference between the each user name for today and yesterday's date.
i.e test has 7000 rank on yesterday and 1000 on today. So the result is 6000
Similarly test2 has -1800.
I need the output as:
Name Difference (Orderby the difference Desc)
--------------------
test 6000
test2 -1800
If the today date or yesterday date's record is not available then we will not take this record to calculation.
Is this possible in PHP MySQL?
How about this? (not very clear what you are trying to achieve though..) Pleaes comment.
SQLFIDDLE DEMO
Code:
select b.id, b.name, (b.rank-a.rank) diff
from t1 a
left join t1 b
on b.date < a.date
and b.name = a.name
having not diff is null
;
Results:
ID NAME DIFF
2 test 6000
4 test2 -1800
Edit as per OP's comment:
Notice that I have added extra few records to your sample table for triggering out conditions.
SQLFIDDLE DEMO2
Code2:
select b.id, b.name,b.rank AS New,
b.Date new_date,
a.Rank as Old, a.date as old_date,
(b.rank-a.rank) diff
from t1 a
left join t1 b
on b.name = a.name
where b.date > a.date and b.date <= Now()
and datediff(b.date, a.date) = 1
having not diff is null and diff <> 0
order by diff desc
;
Results:
ID NAME NEW NEW_DATE OLD OLD_DATE DIFF
3 test 8000 January, 12 2012 1000 January, 11 2012 7000
4 test2 2000 January, 11 2012 200 January, 10 2012 1800
1 test 1000 January, 11 2012 7000 January, 10 2012 -6000
Literally everything you need is on this page
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html

Categories