mysql calculation based on the conditions into a column - mysql

I have a t_personne table.
I encodes a general form for each person.
I also encodes a table "interview" (t_entretien) a presence per project (proj_id).
For the project, it can have multiple actions.
The project action "RAE" are encoded: 2-01.01, 2-02.01, 2-02.02 ...... 2-03.01, 2-03.02, etc.
I have a following calculation rule: A unit is equal to 2 actions from two different categories into the actions encoded.
For example, a person with one action 2-02.01 and 2-03.01 with 2-03.04 actions will only be counted as one unit.
A person who has 4 shares of 2-03 types will not count.
I have to calculate the total number of units.
I started thinking:
SELECT COUNT(*) AS Expr1
FROM (SELECT t_entretien.id
FROM t_entretien
INNER JOIN
t_action on t_action.cact_caction = t_entretien.ent_id
GROUP BY t_entretien.id
HAVING(COUNT(DISTINCT t_action.cact_caction) > 1)) AS derivedtbl_1
Here is a little FIDDLE http://sqlfiddle.com/#!2/6c831/1
Thanks for all !
EDITION
The context is the following.
I get a person (t_personne) and using a form I introduce general data.
This person, I enrolled into a project (t_projet) at the time of the interview (t_entretien).
During the interview, I realize actions.
Every actions are specific projects (t_action).
For the project, including the "cact_code" is 2, I chose different actions encoded (see table t_codeaction).
My problem is the following. I must calculate the number of actions based on a formula that is imposed on me: one unit = 2 actions belonging to different categories. Categories are identified as follows (t_codeaction): 2-01 this category has only one action (2-01.01), the following category includes 4 actions 2-02 and 2-03 in the third category includes 12 actions, etc.
Imagine that the person "ent_id" = 8105 received four actions, one in the category 2-01.01 and 2-03 in the other 3. It is one and only one unit under the rule as it has received at least two actions two different categories. 3 actions in the 2-03 category account for an action. Thus, the person whose "ent_id" = 8114 received only 3 actions of the same class 2-03, this unit is 0.

I am probably wildguessing because the question is bad described, but anyway, something like this?
SELECT id as entretiedId, count(*)/2 as units from
(SELECT t_entretien.id, SUBSTRING(t_action.cact_caction,1,4) as CATEGORY, COUNT(*)
FROM t_entretien
INNER JOIN
t_action on t_action.ent_id = t_entretien.ent_id
GROUP BY t_entretien.id, CATEGORY) as t_derived
GROUP BY id having count(distinct category) > 1
The derived table counts actions, but with one row per ent per category. then the outer group by counts the subactions per category, and divides by two for calculating the units.
fiddle: http://sqlfiddle.com/#!2/6c831/22/0

Related

Polymorphic relation use cases with Laravel - Design Database

I try to design my database and I get confuse.
In my app, an user belong to a group and this group may have multiple stocks of only one type of equipement.
Those stocks can be of two types:
Stock of power lines
Stock of windturbine
Each stock has an identifier representing the area.
Each stock has multiple equipements.
So, to summarize :
User A belongs to group A.
Group A has :
Windturbine1 which has 5 individual windturbines
Windturbines2 which has 10 individual windturbines
User B belongs to group B.
Group B has :
power_lines1 which has 10 individual powerlines
I tried to represent this scheme like this :
However, I'm not totally convinced. I'm not sure if the stock table need to be polymorphic with windturbine_area and power_line_area.
Any insights on this please ?

Include a complex logic in a single MySQL Query

I wanted to reduce the programming logic in a code that search hotels by using a single query.
Let say this is the database table. There are several contracts from a single hotel. I wanted to get all the raws that satisfy input number of rooms for max_adults 1(capacity 1) rooms, number of rooms for rooms for max_adults 2(capacity 2) rooms and number of rooms for rooms for max_adults 3(capacity 3) rooms.
eg: Input : 2 rooms of max_adults=1(capacity 1) 1 rooms of max_adults=2(capacity 2) 3 rooms of max_adults=3(capacity 3)
The rows that satisfy all the 3 conditions with the same hotel id must be output.
As in here the output must contain all the raws of hotel 1 and hotel 2
Since they are two separate results, an extra column is needed to show a generated result_id (kind of serial number as in here which must has duplicates acording to this problem).
I'm thinking lots of ways to do this, but nothing works well. Will this be possible to do in a single query?
Use a self join:
SELECT r1.HOTEL_ID, r1.MAX_ADULTS, r1.NO_OF_ROOMS,
r2.MAX_ADULTS, r2.NO_OF_ROOMS,
r3.MAX_ADULTS, r3.NO_OF_ROOMS,
FROM rooms AS r1
INNER JOIN rooms AS r2 ON r1.HOTEL_ID=r2.HOTEL_ID
INNER JOIN rooms AS r3 ON r1.HOTEL_ID=r3.HOTEL_ID
WHERE r1.MAX_ADULTS=1
AND r2.MAX_ADULTS=2
AND r3.MAX_ADULTS=3
You will have to add clauses to check the input number of rooms conditions.
The generated result_id would be r1.HOTEL_ID.
You would get a single row per hotel.

MySQL Union (or similar) query

I have some booking data from a pair of views in MySQL. They match columns perfectly, and the main difference is a booking code that is placed in one of these rows.
The context is as follows: this is for calculating numbers for a sports camp. People are booked in, but can do extra activities.
View 1: All specialist bookings (say: a football class).
View 2: A general group.
Due to the old software, the booking process results in many people booking for the general group and then are upgraded to the old class. This is further complicated by some things elsewhere in the business.
To be clear - View 1 actually contains some (but are not exclusively all) people from within View 2. There's an intersection of the two groups. Obviously people can't be in two groups at once (there's only one of them!).
Finding all people who are in View 2 is of course easy... as is View 1. BUT, I need to produce a report which is basically:
"View 1" overwriting "View 2"... or put another way:
"View 1" [sort of] UNION "View 2"
However: I'm not sure the best way of doing this as there are added complications:
Each row is as approximately (with other stuff omitted) as follows:
User ID Timeslot Activity
1 A Football
1 A General
2 A General
3 A Football
As you can see, these rows all concern timeslot A:
- User 2 does general activities.
- User 3 does football.
- User 1 does football AND general.
AS these items are non unique, the above is a UNION (distinct), as there are no truly distinct rows.
The output I need is as follows:
User ID Timeslot Activity
1 A Football
2 A General
3 A Football
Here, Football has taken "precedence" over "general", and thus I get the picture of where people are at any time.
This UNION has a distinct clause on a number of fields, but ignores others.
So: does anyone know how to do what amounts to:
"add two tables together and overwrite one of them if it's the same timeslot"
Or something like a:
"selective distinct on UNION DISTINCT".
Cheers
Rick
Try this:
SELECT *
FROM
(SELECT *,
IF(Activity='General',1,0) AS order_column
FROM `Table1`
ORDER BY order_column) AS tmp
GROUP BY UserId
This will add an order_column to your original table that as value 1 if the Activity value is general; Doing this we can select this temporary table ordering by this column (ascending order) and all record with general activity comes after all others. After that we can simply select the result of this temporary table grouping by user id. The group by clouse without any aggregate function takes the first record that match.
EDIT:
If you don't to use group by without aggregate function this is an 'ugly' alternative:
SELECT UserId,
Timeslot,
SUBSTRING(MAX(CASE Activity WHEN "General" THEN "00General" WHEN "Football" THEN "01Football" ELSE Activity END) , 3)
FROM `Table1`
GROUP BY UserId,
Timeslot LIMIT 0 ,
30
Here we need to define each possible value for Activity.

list only rows that appeared thrice in mysql

I have tables called: activities and deficiencies.
activities table contains all activities registered by students. deficiencies table contains all deficiencies that the students might get due to the registered activity.
Here are the table structures with sample data:
activities table
activityid title
-------------------------------------------------------------
1 Student Retreat
2 Student Orientation
deficiencies table
deficiencyid activity_id deficiency status
-------------------------------------------------------------
1 1 NARRATION CLEARED
2 1 PHOTO CLEARED
3 1 REPORT CLEARED
4 2 NARRATION WAITING
5 2 PHOTO CLEARED
6 2 REPORT WAITING
For each activity entry, there will be three rows in the deficiencies table. I want to be able to list each activity once if all the statuses of the items listed there are already CLEARED. So if one or more is still WAITING - they don't get listed in the query.
I was attempting to do this using this query but I couldn't get any lucky:
SELECT * FROM deficiencies,activities WHERE status='CLEARED' AND activityid=activity_id AND COUNT(deficiencyid)=3 GROUP BY activity_id ORDER BY deficiencyid ASC
I was getting the following from MySQL:
Invalid use of group function
The output I was expecting is the first record in the activities table.
What could be the best solution using only one query without multiple SELECT in SELECT in another SELECT sub-queries? There will be thousands of records in the tables so I'm hoping that the most efficient query can be used.
If you want to do this with a JOIN:
SELECT A.activityid, A.title FROM activities A INNER JOIN deficiencies D
ON A.activityid = D.activityid WHERE D.status = 'CLEARED'
GROUP BY A.activityID, A.title HAVING COUNT(*) = 3
This JOINs the activity and deficiencies tables, filters out the records other than CLEARED, groups by activity, and the filters out the groups that do not have exactly three records in them.
It requires that the data is guaranteed to be as you described it (always three deficiency records). I wrote the GROUP BY to avoid using the MySQL extension allowing non-grouped, non-aggregated columns to be selected. Also, I assume that there's also a studentid field involved which you left out for the sake of clarity, otherwise this whole system will support only a single student.

Selecting multiple rows based on specific categories (mysql)

I don't think this is a duplicate posting because I've looked around and this seems a bit more specific than whats already been asked (but I could be wrong).
I have 4 tables and one of them is just a lookup table
SELECT exercises.id as exid, name, sets, reps, type, movement, categories.id
FROM exercises
INNER JOIN exercisecategory ON exercises.id = exerciseid
INNER JOIN categories ON categoryid = categories.id
INNER JOIN workoutcategory ON workoutid = workoutcategory.id
WHERE (workoutcategory.id = '$workouttypeid')
AND rand_id > UNIX_TIMESTAMP()
ORDER BY rand_id ASC LIMIT 6;
exercises table contains a list of exercise names, sets, reps, and an id
categories table contains an id, musclegroup, and type of movement
workoutcategory table contains an id, and a more specific motion (ie: upper body push, or upper body pull)
exercisecategory table is the lookup table that contains (and matches the id's) for exerciseid, categoryid, and workoutid
I've also added a column to the exercises table that generates a random number upon entering the row in the database. This number is then updated only for the specified category when it is called, and then sorted and displays the ascending order of the top 6 listings. This generates a nice random entry for me. (Found that solution elsewhere here on SO).
This works fine for generating 6 random exercises from a specific top level category. But I'd like to drill down further. Here's an example...
select all rows inside categoryid 4
then still within the category 4 results, find all that have movementid 2, and then find one entry with a typeid 1, then another for typeid 2, etc
TLDR; Basically there's a few levels of categories and I'm looking to select a few from here and a few from there and they're all within this top level. I'm thinking this could all be executed within more than one query but im not sure how... in the end I'm looking to end with one array of the randomized entries.
Sorry for the long read, its the best explanation I've got.
Just realized I never came back to this posting...
I ended up using several mysql queries within a switch based on what is needed during the request. Worked out perfectly.