Write SQL query for the below output - mysql

The table is as below.
Emp_ID Emp_Name Emp_Manager_ID
01 A 10
02 B 11
03 C 10
04 D 11
05 E 10
06 F 11
07 G 10
08 H 11
09 I 10
10 J 11
11 K 10
12 L 11
If the requirement is to get the emp_ID and their manager's name, how to write the query?
Like below.
Emp_ID Emp_Name Emp_Manager_ID Emp_Manager_Name
01 A 10 J
02 B 11 K

A simple self join should do it.
SELECT t1.emp_id,
t1.emp_name,
t1.emp_manager_id,
t2.emp_name emp_manager_name
FROM elbat t1
LEFT JOIN elbat t2
ON t2.emp_id = t1.emp_manager_id;

Related

Month-end and weekend logic

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

GROUP BY with MAX(date), but the date is in two separate columns

I'm trying to get the list of IDs of all the rows with latest posting date for each author in a table, for example:
id author_id date
1 12 2020-12-23
2 12 2021-01-06
3 12 2021-04-12
4 12 2021-02-10
5 17 2021-09-16
6 17 2021-05-20
7 17 2021-02-23
8 17 2021-07-02
9 24 2021-03-24
10 24 2021-02-10
11 24 2020-08-18
12 24 2020-12-14
The desired result should be:
id
3
5
9
I used this query and it works perfect:
SELECT a.id
FROM (
SELECT author_id, MAX(`date`) as MaxDate
FROM `posts_log`
GROUP BY author_id
) b
INNER JOIN `posts_log` a
ON a.author_id = b.author_id AND a.date = b.MaxDate
But let's imagine that situation changed. Now author is allowed to post only once per month. So the table changed too and 'date' column became separated:
id author_id month year
1 12 12 2020
2 12 1 2021
3 12 4 2021
4 12 2 2021
5 17 9 2021
6 17 5 2021
7 17 2 2021
8 17 7 2021
9 24 3 2021
10 24 2 2021
11 24 8 2020
12 24 12 2020
Yeah, I know, looks a little bit stupid, but this wasn't my decision. Now I have such table and I'm not allowed to change the structure.
The question is: How to get the same result with this new table. Is it possible in MySQL?
You can use similar logic. Just instead of the date, use a calculated value from year and month:
SELECT a.id
FROM (
SELECT p.author_id, MAX(p.year*100+p.month) as MaxMonth
FROM posts_log p
GROUP BY p.author_id
) b
INNER JOIN posts_log a
ON a.author_id = b.author_id AND a.year*100+a.month = b.MaxMonth;

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

Join on matching records and create combinations when no match

I am trying to create a new table using two others. I want to create a record all combinations of records while merging a 'value' column. I want another column that tells me where the value is from
Something like this.:
A:
Day Month Random1 Random2 value1
01 Jan AA XX 12
24 Mar BB YY 34
13 Feb CC ZZ 7
B:
Day Month value2
03 Jan 16
24 Mar 2
I am trying to join them on Day and Month, however I want it to create a row with all combinations if there is no row match.
I want a table as follows:
C:
Day Month Random1 Random2 value Type
01 Jan AA XX 12 value1
24 Mar BB YY 34 value1
13 Feb CC ZZ 7 value1
03 Jan AA XX 16 value2
03 Jan AA YY 16 value2
03 Jan AA ZZ 16 value2
03 Jan BB XX 16 value2
03 Jan BB YY 16 value2
03 Jan BB ZZ 16 value2
03 Jan CC XX 16 value2
03 Jan CC YY 16 value2
03 Jan CC ZZ 16 value2
24 Mar AA XX 2 value2
24 Mar AA YY 2 value2
24 Mar AA ZZ 2 value2
24 Mar BB XX 2 value2
24 Mar BB YY 2 value2
24 Mar BB ZZ 2 value2
24 Mar CC XX 2 value2
24 Mar CC YY 2 value2
24 Mar CC ZZ 2 value2
My sql query is unusually complicated and am sure there is a simple way of doing this.
(I am actually writing this query in R using sqldf(), I looking for an sql suggestion but am open to alternatives.)
It appears as though the result set includes set A, plus the set that is the combination of unique values of Random1, unique values of Random2 and set B.
I would use this
SELECT Day, Month, Random1, Random2, value1, 'value1' AS type
FROM tableA
UNION
SELECT tableB.Day, tableB.Month, r1.Random1, r1.Random2, tableB.value2, 'value2'
FROM tableB
JOIN (SELECT DISTINCT Random1
FROM tableA) AS r1
JOIN (SELECT DISTINCT Random2
FROM tableA) AS r2;

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)