PHP mysql get subtraction between 2 dates - php

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

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

Retrieving the last record in each group not getting expected result - MySQL

I want to fetch data of last two months of each category from table.
Table looks like:
Id
Year
month
category
value
1
2019
1
TEST1
10
2
2018
12
TEST1
10
3
2018
10
TEST1
10
4
2018
1
TEST2
10
5
2018
12
TEST2
10
6
2018
1
TEST3
10
Expected output:
Id
Year
month
category
value
1
2019
1
TEST1
10
2
2018
12
TEST1
10
5
2018
12
TEST2
10
4
2018
1
TEST2
10
6
2018
1
TEST3
10
I tried using:
SELECT a.year,a.month,a.value, a.category
FROM test_data AS a
WHERE
(
SELECT COUNT(*)
FROM test_data AS b
WHERE b.category = a.category AND (b.year >= a.year AND b.month >= a.month)) <= 2
ORDER BY a.year DESC, a.month DESC
But it is giving extra record of TEST1 category. I guess because it is not working as expected for year condition. Please provide solution for this
Your first effort should go into fixing your data model and using a date-like datatype to store the date information, rather than spreading it over different columns. This should be as simple as adding a new column to the table and updating it from the existing columns:
alter table test_data add mydate date;
update test_data set mydate = concat(year, '-', month, '-01');
That said, to make your current query work you need to fine-tune the conditions on the dates as follows. One option uses arithmetics:
SELECT a.year, a.month, a.value, a.category
FROM test_data AS a
WHERE (
SELECT COUNT(*)
FROM test_data AS b
WHERE
b.category = a.category
AND 100 * b.year + b.month >= 100 * a.year + a.month
) <= 2
ORDER BY a.year DESC, a.month DESC
Alternatively, if you are running MySQL 8.0, you can use row_number():
SELECT a.year, a.month, a.value, a.category
FROM (
SELECT
a.*,
ROW_NUMBER() OVER(PARTITION BY a.category ORDER BY a.year DESC, a.month DESC)
FROM test_data AS a
) a
WHERE rn <= 2

Query - Find new and repeating users in MySQL

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.

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 asc/desc order

TABLE:
**timeslot**:
----------
id_timeslot times
1 09:00
2 09:30
3 10:00
4 10:30
5 11:00
**bookslot**
id id_timeslot date b_ref
-------------------------------------------
1 2 2010-02-22 001
2 3 2010-02-22 001
3 4 2010-02-22 001
4 5 2010-02-22 001
5 2 2010-02-25 002
6 3 2010-02-27 003
7 4 2010-02-27 003
8 5 2010-02-27 003
PHP
$q = $mysqli->query("SELECT * FROM bookslot
LEFT JOIN timeslot ON bookslot.id_timeslot = timeslot.id_timeslot
WHERE bookslot.status = 1
GROUP BY bookslot.b_ref
ORDER BY bookslot.date ASC, bookslot.id_timeslot ASC LIMIT 20");
HTML RESULT:
DATE TIMES
2010-02-22 10:30
2010-02-25 09:30
2010-02-27 11:00
anyone notice that on the table result. the times is incorrect order?
i changed another way round with ASC / DESC, and still the times showing the last id_timeslot?
EXPECTED RESULT:
DATE TIMES
2010-02-22 09:30
2010-02-25 09:30
2010-02-27 10:00
Your GROUP BY bookslot.b_ref is grouping the records, so you're only seeing the last time in each case.
Try using
SELECT date, time, MIN(bookslot.id_timeslot)
FROM bookslot
LEFT JOIN timeslot ON bookslot.id_timeslot = timeslot.id_timeslot
WHERE bookslot.status = 1
GROUP BY bookslot.b_ref
ORDER BY bookslot.date ASC, bookslot.id_timeslot ASC LIMIT 20
While your SQL is syntactically correct but it will produce unexpected results.
Normally, the columns that you SELECT must be specified in the GROUP BY clause or should be enclosed inside an aggregate function. Otherwise, MySQL will determine, at its own discretion, which records to eliminate in the GROUP BY operation. The ORDER BY does not matter because it is applied after the GROUP BY operation. You should better revise your query like this:
SELECT b_ref, MIN(ADDTIME(date, times)) AS complete_datetime
FROM bookslot
LEFT JOIN timeslot ON bookslot.id_timeslot = timeslot.id_timeslot
WHERE bookslot.status = 1
GROUP BY bookslot.b_ref
ORDER BY bookslot.date, bookslot.id_timeslot
Since the goal appears to be about collecting the earliest timeslots for each bookslot then it's required to narrow the results with MIN
SELECT b.id, b.id_timeslot, b.date, MIN(`date`) , t.times
FROM bookslot b
LEFT JOIN timeslot t ON b.id_timeslot = t.id_timeslot
GROUP BY b.b_ref

Categories