Month-end and weekend logic - mysql

Pull the data month end and weekend without weekends.if get the weekend then retrieve the before that weekend.
Ex:the date is 20 or 21 Of AUGUST(WEEKENDS),Then i need the 19th(WEEKDAY) data..

O r a c l e
You could use CASE expression with To_Char(Date_column, 'd').
The WITH clause is here just to generate some sample data and, as such, it is not a part of the answer.
Here is the answer including the order number of the day of the week ('d') and short name of the day of the week ('DY') because the day one of the week depends on NLS_TERRITORY.
Here is the code...
WITH
tbl AS
(
Select SYSDATE - (LEVEL - 1) "A_DATE", 101 - LEVEL "A_VALUE" From Dual CONNECT BY LEVEL <= 18
)
SELECT
A_DATE "A_DATE",
To_Char(A_DATE, 'd') "A_DAY_OF_WEEK",
To_Char(A_DATE, 'DY') "A_DAY_OF_WEEK_NAME",
A_VALUE "TBL_VALUE",
CASE WHEN To_Char(A_DATE, 'd') = '6' THEN
(Select A_VALUE From tbl Where A_DATE = t1.A_DATE - 1)
WHEN To_Char(A_DATE, 'd') = '7' THEN
(Select A_VALUE From tbl Where A_DATE = t1.A_DATE - 2)
ELSE
A_VALUE
END "VALUE_OUT"
FROM
tbl t1
ORDER BY A_DATE
... and the result
--
-- R e s u l t
--
-- A_DATE A_DAY_OF_WEEK A_DAY_OF_WEEK_NAME TBL_VALUE VALUE_OUT
-- --------- ------------- ------------------ ---------- ----------
-- 03-AUG-22 3 WED 83 83
-- 04-AUG-22 4 THU 84 84
-- 05-AUG-22 5 FRI 85 85
-- 06-AUG-22 6 SAT 86 85
-- 07-AUG-22 7 SUN 87 85
-- 08-AUG-22 1 MON 88 88
-- 09-AUG-22 2 TUE 89 89
-- 10-AUG-22 3 WED 90 90
-- 11-AUG-22 4 THU 91 91
-- 12-AUG-22 5 FRI 92 92
-- 13-AUG-22 6 SAT 93 92
-- 14-AUG-22 7 SUN 94 92
-- 15-AUG-22 1 MON 95 95
-- 16-AUG-22 2 TUE 96 96
-- 17-AUG-22 3 WED 97 97
-- 18-AUG-22 4 THU 98 98
-- 19-AUG-22 5 FRI 99 99
-- 20-AUG-22 6 SAT 100 99

Related

Creating custom week number in sql

I have a table with ID and Date columns.
Table A:
ID
Date
24
2019-10-29
24
2019-10-30
24
2019-10-31
.....
....
I need to add a column called "Week_Num" such that:
If there is a new "ID" and the first date begins on a Tuesday (eg: 29th Oct,2019 in ID 24 is Tuesday) then the week will start with 1
Week will always end on Saturday irrespective of whether 7 days are over or not with only one exception (see point 3)
If there is a new "ID" and the first date begins before Tuesday (eg: 25th Oct,2020 in ID 25 is Sunday) then the week will start with 0 and once it reaches Tuesday the week_num will become 1.
Expected Output:
ID
Date
Day_Of_Week
Week_Num
24
2019-10-29
Tue
1
24
2019-10-30
Wed
1
24
2019-10-31
Thur
1
24
2019-11-01
Fri
1
24
2019-11-02
Sat
1
24
2019-11-03
Sun
2
24
2019-11-04
Mon
2
24
2019-11-05
Tues
2
24
2019-11-06
Wed
2
24
2019-11-07
Thurs
2
24
2019-11-08
Fri
2
24
2019-11-09
Sat
2
24
..........
.
..
24
2020-03-14
.
..
25
2020-10-25
Sun
0
25
2020-10-26
Mon
0
25
2020-10-27
Tue
1
25
2020-10-28
Wed
1
25
2020-10-29
Thur
1
25
2020-10-30
Fri
1
25
2020-10-31
Sat
1
What I have so far:
select
distinct ID,min(Date) over (partition by ID order by date) as firstTuesdayOfSeason
from
TableA
group by ID,Date
having datepart(weekday,Date)=3
which gets the first Tuesday for every new ID and gives the following output:
ID
firstTuesdayOfSeason
24
2019-10-29
25
2020-10-27
I was thinking of joining this table with the Table A (the one with ID, Date as columns) but I don't know how to implement the weird Saturday logic.
This might work for you.
Find min-date, offset to Tuesday for each ID, and calculate using date-diff for each row against the min-date
select a.ID, a.Date, weekday(a.Date), greatest(0, 1 + floor((datediff(a.Date, b.since) - b.off) / 7)) week_num
from TableA a
join (
select ID, min(Date) As since, (case when weekday(min(Date)) > 1 then 8 - weekday(min(Date)) else 1 - weekday(min(Date)) end) off
from TableA
group by ID
) b ON a.ID = b.ID
order by a.ID, a.Date
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=657c96465338a398ced73bc256ff92c0

Displaying only records that don't have an update this month

MySQL and PHP
I am attempting to write a SQL statement that will allow me to identify an individual that has not checked in this month. I am stuck on how to write the code.
I have 2 tables
tbl_cust c
tbl_attend a
SELECT
c.custRFID,
a.attendID,
a.RFID,
a.attendDate,
a.attendStatus,
a.attendStatusCode,
a.attendNotes
FROM
tbl_cust c RIGHT OUTER JOIN tbl_attend a ON c.custRFID = a.RFID
WHERE
MONTH(a.attendDate) <> MONTH(CURDATE()) AND YEAR(a.attendDate) =
YEAR(CURDATE())
The code filters out this month, however, it returns every date prior to this month. I only want to display the names from table c that don't have an entry in table a for this month. I don't need all the records.
-------------------------------------------------------------
ID RFID Date Time Status Status Code
-------------------------------------------------------------
1 01 02 03 E1 2018-01-03 1835 1 1
2 02 02 04 E2 2018-01-06 1235 1 1
3 01 02 03 E1 2018-02-07 1801 1 1
4 02 02 04 E2 2018-02-11 1109 1 1
5 01 02 03 E1 2018-03-03 1835 1 1
6 02 02 04 E2 2018-03-06 1235 1 1
7 01 02 03 E1 2018-04-07 1801 1 1
8 02 02 04 E2 2018-04-11 1109 1 1
9 01 02 03 E1 2018-05-01 1032 1 1
If this was May 16, 2018 the following should be the output:
-----------------------------------------------------------
ID RFID Date Time Status Status Code
-------------------------------------------------------------
8 02 02 04 E2 2018-04-11 1109 1 1
This is only using 2 customers, as the actual table will eventually have over 5,000 customers in it. with at least 1 entry per month. Some will have 3 of 4 entries per month, however, I only want to see those with no entry in the current calendar month. I.e.... If they checked in anytime during the calendar month of May 2018, they should not be displayed on the output.
Thank you in advance.
If you want someone who has ever checked in, then you can use aggregation:
select RFID
from attend a
group by RFID
having max(attendDate) < date_add(curdate(), interval 1 - day(curdate()) day);
I would write this as an EXISTS query:
SELECT
c.custRFID
FROM
tbl_cust c
WHERE NOT EXISTS (SELECT 1 FROM tbl_attend a
WHERE c.custRFID = a.RFID AND
MONTH(a.attendDate) = MONTH(CURDATE()) AND
YEAR(a.attendDate) = YEAR(CURDATE()));
You can do this using LEFT JOIN.
Also, try not to use YEAR(column) & MONTH(column) functions in ON/WHERE clauses as SQL will not be able to use indeces in this case.
Something like this should do the trick:
SELECT
c.custRFID,
a.attendID,
a.RFID,
a.attendDate,
a.attendStatus,
a.attendStatusCode,
a.attendNotes
FROM
tbl_cust c
LEFT JOIN tbl_attend a ON (
c.custRFID = a.RFID
AND a.attendDate > DATE_SUB(LAST_DAY(CURDATE()), INTERVAL 1 MONTH)
AND a.attendDate <= LAST_DAY(CURDATE())
)
WHERE
a.RFID IS NULL

create table su AS select don't work

i have this table
ID |user |Contact |Duration
1 asif 11 00
2 bob 22 65
3 cena 33 00
4 asif 44 00
5 cena 33 00
6 cena 33 00
7 bob 55 43
8 asif 44 33
9 bob 66 00
i want use this sql;
CREATE TABLE su
AS (select user,
contactcount,
duration,
case when durationcount = 0 then 0 else duration/durationcount end
from (
select user,
count(distinct contact) contactcount,
sum(duration) duration,
sum(case when duration > 0 then 1 else 0 end) durationcount
from table4
group by user
) t)
But phpmyadmin, give error. #1166 - Incorrect column name 'case when durationcount = 0 then 0 else duration/durationcount end'
expected ouput;
|user |count |duration_total |case when durationcount = 0 then 0 else duration/durationcount end
asif 2 33 33
bob 3 108 54
cena 1 00 00
what is wromg in this sql ?
the goal is to create new table whit ID, user, total duration per user and average time by user when duration >0

Get difference between values in MySQL

I have a table with following columns
id pl_date month scores kID
1 20015/02/04 02 9 244
2 20015/02/05 02 12 244
3 20015/02/08 02 8 244
4 20015/02/22 02 24 244
5 20015/03/10 03 10 244
6 20015/03/11 03 12 244
7 20015/03/12 03 10 244
8 20015/03/13 03 12 244
My goal is to calculate the score's difference using a specific SELECT with MySQL
id pl_date month scores kID diff
1 2015/02/04 02 9 244 -3
2 2015/02/05 02 12 244 +4
3 2015/02/08 02 8 244 -16
4 2015/02/22 02 24 244 +14
5 2015/03/10 03 10 244 -2
6 2015/03/11 03 12 244 +2
7 2015/03/12 03 10 244 -2
8 2015/03/13 03 12 244 12
I tried to use the subquery as shown below, but it does not work.
SELECT b.id, (b.max_count-b.min_count) AS DIFF
FROM
(SELECT id, MAX(scores) as max_count, MIN(scores) as min_count
FROM myTable
WHERE month = 03 AND kID = 244
GROUP BY kID) b
You can join the table with itself (a self-join), but with the id shifted by one to do this:
select t1.*, ifnull(t1.scores - t2.scores, t1.scores) as diff
from table1 t1
left join table1 t2 on t1.id + 1 = t2.id
If you only want the diff to be calculated within some grouping (like kID), just add those conditions to the join.
Another approach would be to use a correlated subquery (this uses dates instead of id to determine the successor):
select
t1.*,
t1.scores
- ifnull(
(select scores
from table1
where pl_date > t1.pl_date
limit 1)
,0) as diff
from table1 t1
order by id;
Sample SQL Fiddle (both approaches)

sql for the one entry in each group that meets a condition

I have a query
SELECT ckt, setpt, clock FROM progs
WHERE feed = "80302" AND day=4 AND clock<"12:15:00"
ORDER BY ckt, clock DESC
That gets me this:
ckt setpt clock
0 69 06:06:00
0 62 00:30:00
1 57 10:30:00
1 67 04:30:00
1 57 01:30:00
2 69 11:00:00
2 62 00:30:00
How could I modify this query to give me the MAX(clock) for each CKT
In total:
Each cktand day has a number of setpt and clock entries. I am looking for the (1 or none) clock record < some_time for each ckt and day. ie
0 69 06:06:00
1 67 10:30:00
2 69 11:00:00
in mysql.
Something like this?
SELECT ckt, MAX(setpt), MAX(clock)
FROM progs
WHERE feed = "80302" AND day=4 AND clock<"12:15:00"
GROUP BY ckt
ORDER BY ckt, clock DESC
Result
| CKT | MAX(SETPT) | MAX(CLOCK) |
-----------------------------------------------------
| 0 | 69 | January, 01 1970 06:06:00+0000 |
| 1 | 67 | January, 01 1970 10:30:00+0000 |
| 2 | 69 | January, 01 1970 11:00:00+0000 |
See the demo
Sounds like you need to JOIN the table to itself, joining on the MAX(clock):
SELECT p.ckt, p.setpt, p.clock
FROM progs p
JOIN (
SELECT MAX(clock) maxClock, ckt
FROM progs
WHERE feed = "80302"
AND day=4
AND clock<"12:15:00"
GROUP BY ckt
) p2 on p.ckt = p2.ckt AND p.clock = p2.maxclock
ORDER BY p.ckt, p.clock DESC
SQL Fiddle Demo (borrowed from other post)
Producing:
0 69 January, 01 1970 06:06:00+0000
1 57 January, 01 1970 10:30:00+0000
2 69 January, 01 1970 11:00:00+0000
Please note row with id 1 is different than your desired results, but match your question's desired results...