How to update one table in MySQL after insertion in another table - mysql

I have two table first is "employee_details" second is "attendance_rule"
employee_details
e_code | e_name | e_type
01 | Ram | Regular
02 | Shyam | Contract
03 | Mohan | Regular
attendance_rule
e_code | e_type | casual_leaves
01 | Regular | 7
02 | Contract | 6
03 | Regular | 7
I have manually insert values in "attendance_rule".
Now the problem is that when the attendance rule changes in the organisation. The user has to manually update the casual_leave coloumn for all the employees.
What I want is that when an employee details are added in employee_details table , the entry in the attendance_rule table should be automatically made having e_code and e_type same as e_code and e_type of employee_details table and casual_leaves equals to the casual_leaves of the same type of employee.
I think that a trigger should be used here.
but I dont know how to use trigger for this condition i.e. for the entry of casual leaves.
Please help me...how should I do that? Is there a way to do it other that trigger?

It sounds like you don't need a separate entry in attendance_rule for every employee, just for every employee type, so you don't need a trigger at all.
Create employee_details like you suggested:
e_code | e_name | e_type
01 | Ram | Regular
02 | Shyam | Contract
03 | Mohan | Regular
But create attendance_rule with only the rules for each type:
e_type | casual_leaves
Regular | 7
Contract | 6
If you need to find the number of casual leaves for a particular employee, join the two tables:
select
e.e_code,
e.e_name,
e.e_type,
a.casual_leaves
from employee_details e
inner join attendance_rule a on e.e_type = a.e_type
to get
e_code | e_name | e_type | casual_leaves
01 | Ram | Regular | 7
02 | Shyam | Contract | 6
03 | Mohan | Regular | 7
And if you want to make it as easy to use as a table, you can create a view:
create view emp_all_details as
select
e.e_code,
e.e_name,
e.e_type,
a.casual_leaves
from employee_details e
inner join attendance_rule a on e.e_type = a.e_type
Now you can simply say: select * from emp_all_details to get:
e_code | e_name | e_type | casual_leaves
01 | Ram | Regular | 7
02 | Shyam | Contract | 6
03 | Mohan | Regular | 7

Related

Find most recent records with specific criteria in Access

I have a set of records that I would like to display the most recent records that match certain criteria. I've done it wrong in the past where it would first pull the most recent records and THEN go and try and match criteria which would cause some of the records to disappear. What I want to have the query do is to find the records that match criteria first and THEN have it pull the most recent records from that data set. I need to have this query INSERT INTO a Table in Access.
I thought I had it sorted out, but I get an error "Your query does not include the specified expression 'SufGrpID' as part of an aggregate function
An example of the data:
When the query runs, I would like the results to be:
An example of the data:
SufGrpID 03 would be removed from the set because it is not the newest record for CaseID 123
SufGrpID 04 would be removed from the set because it is not of SufTypeID 14 and it is not of Status F
How the data looks
+----------+---------+-------------------------+-----------+--------+
| SufGrpID | CaseID | CreateDate | SufTypeID | Status |
+----------+---------+-------------------------+-----------+--------+
| 01 | 123 | 2010-08-20 07:42:32.000 | 14 | F |
| 02 | 234 | 2010-04-28 10:33:56.000 | 14 | F |
| 03 | 123 | 2010-04-20 10:05:04.000 | 14 | F |
| 04 | 345 | 2010-08-20 11:18:42.000 | 12 | I |
| 05 | 345 | 2010-04-20 11:18:42.000 | 14 | F |
+----------+---------+-------------------------+-----------+--------+
Here's the code that did not work for me...
INSERT INTO [aStudent Base Data] ( [Self Suff ID], [Self Suff Create Date] )
SELECT dbo_sufscrgrp.SufGrpID, Max(dbo_sufscrgrp.CreateDate)
FROM dbo_sufscrgrp
WHERE (((dbo_sufscrgrp.SufTypeID)=14) AND ((dbo_sufscrgrp.Status)="F"))
GROUP BY dbo_sufscrgrp.CaseID;
What I'd like the results to be. (EDITED at 1:33 CST)
+--------------+------------------------+
| Self Suff ID | Self Suff Create Date |
+--------------+------------------------+
| 01 | 2010-08-20 07:42:32.000 |
| 02 | 2010-04-28 10:33:56.000 |
| 05 | 2010-04-20 11:18:42.000 |
+--------------+-------------------------+
Thanks for any help you can give!
Based on the minimal dataset example, consider:
SELECT dbo_sufscrgrp.*
FROM dbo_sufscrgrp
WHERE SufGrpID
IN (SELECT TOP 1 SufGrpID FROM dbo_sufscrgrp As Dupe
WHERE Dupe.CaseID=dbo_sufscrgrp.CaseID AND SufTypeID=14 and Status="F"
ORDER BY Dupe.CreateDate DESC, Dupe.SufGrpID DESC);

MySQL Count within an IF

+-------------+--------------+----------+-------+
| ticketRefNo | nameOnTicket | boughtBy | event |
+-------------+--------------+----------+-------+
| 38 | J XXXXXXXXX | 2 | 13 |
| 39 | C YYYYYYY | 1 | 13 |
| 40 | M ZZZZZZZZZZ | 3 | 14 |
| 41 | C AAAAAAA | 3 | 15 |
| 42 | D BBBBBB | 3 | 16 |
| 43 | A CCCCC | 3 | 17 |
+-------------+--------------+----------+-------+
+-------------+------------------+--------------+---------------------+--------+
| ticketRefNo | cardNo | cardHolder | exp | issuer |
+-------------+------------------+--------------+---------------------+--------+
| 38 | 4444111133332222 | J McKenny | 2016-01-01 00:00:00 | BOS |
| 39 | 4434111133332222 | C Dempsey | 2016-04-01 00:00:00 | BOS |
| 40 | 4244111133332222 | M Gunn-Davis | 2018-02-01 00:00:00 | RBS |
+-------------+------------------+--------------+---------------------+--------+
+-------------+-------------+----------+
| ticketRefNo | boxOfficeID | paidWith |
+-------------+-------------+----------+
| 41 | 1 | card |
| 42 | 2 | cash |
| 43 | 3 | chequ |
+-------------+-------------+----------+
I have a database with the data shown above. It represents a ticket-buying system. I would like to be able to see a list of tickets bought with the name of the event and either the boxOfficeID or the issuer of the debit card.
I have tried running the following code, to no avail.
SELECT t.ticketRefNo AS 'Reference', t.event AS 'Event',
IF(COUNT(SELECT * FROM Online WHERE t.ticketRefNo=o.ticketRefNo;) >= 1,
o.issuer, InPerson.boxOfficeID) AS 'Card Issuer or Box Office'
FROM Ticket AS t, InPerson, Online AS o
WHERE t.ticketRefNo=o.ticketRefNo;
Cheers in advance!
Some notes: the semicolon character isn't valid syntax; if you have a need to delimit the subquery, wrap it in parens. Escape column aliases like you'd escape any other identifier: use backticks, not single quotes. Single quotes are used around string literals.
Assuming that issuer in the Online table is NOT NULL, and assuming that ticketRefNo is unique in both the Online and InPerson tables, you could do something like this:
SELECT t.ticketRefNo AS `Reference`
, t.event AS `Event`
, IF(o.ticketRefNo IS NOT NULL,o.issuer,i.boxOfficeId)
AS `Card Issuer or Box Office`
FROM Ticket t
LEFT
JOIN InPerson i
ON i.ticketRefNo = t.ticketRefNo
LEFT
JOIN Online o
ON o.ticketRefNo = t.ticketRefNo
Use outer join operations to find matching rows in the InPerson and Online tables, and use a conditional test to see if you got a matching row from the Online table. A NULL will be returned if there wasn't a matching row found.
It's not a good idea to have one column JOINing to two different tables with some values in each of the two tables.
But here goes anyway:
( SELECT ... FROM Ticket t JOIN InPerson x USING(ticketRefNo) ... )
UNION ALL
( SELECT ... FROM Ticket t JOIN Online x USING(ticketRefNo) ... )
ORDER BY ...
The ALL assumes that InPerson and Online never have any overlapping ticketRefNos.
The ORDER BY an the end is in case you want to sort things, although I see no need for it in your attempted SELECT.
The two SELECTs must have the same number of columns.

SQL COUNT query similar to UNION but with results in multiple columns

I have a single-table SQL database built from DHCPD logs, structured as below:
+------+-------+------+----------+---------+-------------------+-----------------+
| id | Month | Day | Time | Type | MAC | ClientIP |
+------+-------+------+----------+---------+-------------------+-----------------+
| 9305 | Nov | 24 | 03:20:00 | DHCPACK | 00:04:f2:4b:dd:51 | 10.123.246.116 |
| 9307 | Nov | 24 | 03:20:07 | DHCPACK | 00:04:f2:99:4c:ba | 10.123.154.176 |
| 9310 | Nov | 24 | 03:20:08 | DHCPACK | 00:19:bb:cf:cd:28 | 10.99.107.3 |
| 9311 | Nov | 24 | 03:20:08 | DHCPACK | 00:19:bb:cf:cd:28 | 10.99.107.3 |
Every DHCP event from the log will eventually make its way into this database, so events from any point in time will be potentially used in the construction of graphs. To make use of the data for graphing, I need to be able to create an output table with multiple columns, but with values derived from a count of those in a single column matching a specific pattern.
The closest thing I've managed to come up with is this query:
select 'Data' as ClientIP, count(*) from Log where ClientIP like '10.99%' and MAC like '00:04:f2%'
union
select 'Voice' as ClientIP, count(*) from Log where ClientIP like '10.123%' and MAC like '00:04:f2%';
Which yields the following result:
+-----------+-------+
| ClientIP | Count |
+-----------+-------+
| Data | 4618 |
| Voice | 13876 |
+-----------+-------+
Fine for a one-off query, but I want to take those two rows, turn them into two columns, and run the same query with one row per hour (for instance). I want something like this:
+------+-------+------+
| Hour | Voice | Data |
+------+-------+------+
| 03 | 22 | 4 |
| 04 | 123 | 23 |
| 05 | 45 | 5 |
Any advice is greatly welcomed.
Thanks
You can group by hour and use conditional computation to count Data and Voice traffic.
For example:
SELECT
HOUR(time) AS `Hour`,
SUM(CASE WHEN ClientIP like '10.99%' and MAC like '00:04:f2%' THEN 1 ELSE 0 END) AS `Data`,
SUM(CASE WHEN ClientIP like '10.123%' and MAC like '00:04:f2%' THEN 1 ELSE 0 END) AS `Voice`
FROM log
GROUP BY HOUR(time)
Create a separate table for (as you want) :
+------+-------+------+
| Hour | Voice | Data |
+------+-------+------+
and update it every hour using triggers.

Troubles conceptualizing a query

I have a 'Course' table and an 'Event' table.
I would like to have all the courses that actually take place, i.e. they are not cancelled by an event.
I have done this by a simple request for all the course and a script analysis (basically some loops), but this request take a time that I believe too long. I think what I want is possible in one query and no loops to optimize this request.
Here are the details :
'Course' c have the fields 'date', 'duration' and a many to many relation with the 'Grade' table
'Event' e have the fields 'begin', 'end', 'break' and a many to many relation with the 'Grade' table
A course is cancelled by an event if they occur at the same time and if the event is a break (e.break = 1)
A course is cancelled by an event if all the grades of the course are in the events that occurs at the same time (many events can occurs, I have to sum up the grades of these events and compare them to the grades of the courses). This is the part I'm doing with a loop, I have some trouble to conceptualize that.
Any help is welcome,
Thanks in advance,
PS : I'm using mysql
EDIT : Tables details
-Course
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| date | datetime | NO | | NULL | |
| duration | time | NO | | NULL | |
| type | int(11) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
+-------+---------------------+----------+------+
| id | date | duration | type |
+-------+---------------------+----------+------+
| 1 | 2013-12-10 10:00:00 | 02:00:00 | 0 |
| 2 | 2013-12-11 10:00:00 | 02:00:00 | 0 |
+-------+---------------------+----------+------+
-Event
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| begin | datetime | NO | | NULL | |
| end | datetime | YES | | NULL | |
| break | tinyint(1) | NO | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
+----+---------------------+---------------------+-------+
| id | begin | end | break |
+----+---------------------+---------------------+-------+
| 1 | 2013-12-10 00:00:00 | 2013-12-11 23:59:00 | 1 |
+----+---------------------+---------------------+-------+
-course_grade
+-----------+----------+
| course_id | grade_id |
+-----------+----------+
| 1 | 66 |
| 2 | 65 |
| 2 | 66 |
+-----------+----------+
-event_grade
+----------+----------+
| grade_id | event_id |
+----------+----------+
| 66 | 1 |
+----------+----------+
So here, only the course 2 should appear, because course 1 has only one grade, and this grade has an event.
I like riddles, this is a nice one, has many solutions, I think
As you say 'Any help is welcome', I give an answer altough its not the solution (and it does not fit into a comment)
I dont know, if you just want (A) the naked statement (over and out), or if you want (B) to understand how to get to the solution, I take (B)
I start with 'what would I change' before starting about the solution:
you are mixing date,datetime,start,end and duration, try to use only one logic (if it is your model ofcourse) ie.
an event/course has a start and an end time (or start/duration)
duration should (IMHO) not be a time
try to find a smallest timeslice for events/course (are there 1 sec events? or is a granularity of 5' (ie. 10:00, 10:05, 10:10 ans so on) a valid compromise?
My solution, a prgmatic one not academic
(sounds funny, but does work good in a simillar prob I had see annotation)
Create a table (T_TIME_OF_DAY) having all from 00:00, 00:05, .. 23:55
Create a Table (T_DAYS) in a valid and usefull range (a year?)
the carthesian product - call it points in time - (ie. select date, time from T_DAYS,T_TIME_OF_DAY no condition) of them (days x times) 300*24*12 ~ 100.000 rows if you need to look at a whole year (and 5' are ok for you) - thats not much and no prob
the next step is to join the curses fitting to your points in time (and the rows are down to <<100.000)
if you next join these with your events (again using point in time) you should get what you want.
simplyfied quarters of a day:
12 12 12 12 12 12 12 12
08 09 10 11 12 13 14 15
|...|...|...|...|...|...|...|...
grade 65 (C).............2..................
grade 66 (C).........1...2..................
grade 65 (E)................................
grade 66 (e)........1111..................
(annotation: I use this logic to calculate the availabillity of services regarding to their downtimes per Month / Year, and could use the already in timeslices prepared data for display)
(second answer, because it is a totaly different and mor3 standard aproach)
I made an SQLFiddle for you
so what to do:
and thats the a solution:
step one (in mind) select course,grades (lets call them C)
step two (in mind) select events, grades (lets call them E)
and - tada -
select all from C where there a no rows in E that have the same grade and the same date(somehow) and eventtype='break'
so your solution:
select
id, date start_time, date+duration end_time, grade_id
from Course c join course_grade cg on c.id=cg.course_id
where not exists (
select grade_id, begin start_time, end end_time
from event_grade eg join event e on eg.event_id=e.id
where
eg.grade_id=cg.grade_id
and e.break=1
and
(
(e.begin<=c.date and e.end >=c.date+c.duration)
or e.begin between c.date and c.date+c.duration
or e.end between c.date and c.date+c.duration
)
)
I did take no attention to optimize here

Query to retrieve values of similar primary keys

I have a table with two columns which looks like this:
+-----------+--------+
| Mobile_id | Person |
+-----------+--------+
| ME_02_05 | John |
| ME-02 05 | Barry1 |
| 02-05 | John |
| ME 03-02 | James |
+-----------+--------+
I want to retrieve all persons whose Mobile_id contains integers (02 05). It can be seen that there are different combinations of 02 05 in the table such as ME_02_05, ME-02 05 and 02-05.
Can anyone please tell me how to do this?
SELECT Person FROM Persons WHERE Mobile_Id LIKE "%02%05"
should work.
SELECT Person FROM t1 WHERE Mobile_id REGEXP '02[-_ ]05'
This selects each Person entry that has 02 followed by dash, underscore, or space followed by 05.