Complicated request from the void - one table - mysql

I have a steps table. It describes the steps a person takes towards a specific goal. For example, 3 steps to one goal, 5 steps to the second. And every time I take a new step, I write a new step into this table. Question: how can I determine, for example, whether step No. X has been made? The given record can and not exist?
For example, I have 2 steps out of 3 recorded, and for example I want to select all records that do not have step number 3
Example:
id, name, step
1 Mark 1
2 Mark 2
3 Mark 3
4, Jenny, 1
5, Jenny, 2
6, Tony, 1
7, Tony, 2
8, Tony, 3
9, Joe, 1
For example, I want to show everyone who does not have step number 3
How can I do it?

For the question to decide whether step No. X has been made, the code is like:
select count() from steps where step = X
This will return the total number of records of X.
For the question to select all records that do not have step number 3:
select * from steps where step != 3

Related

Shared foreign keys without duplication of entries?

Sorry for the beginner question.
I have an Outputs table:
ID
value
0
x
1
y
2
z
And an Inputs table that is linked to the Outputs through the outputsID:
ID
outputsID
name
0
0
A
1
1
B
2
1
C
3
2
B
4
2
C
Assuming that multiple outputs have at least one shared input (in this example outputID 1,3 and 2,4 are the same), is there a way to avoid the duplication of entries in my Inputs table (inputID 3 and 4)?
The 'normal' answer to your question is no. Rows 1 and 2 address output 1, and Rows 3 and 4 address output 2. They aren't duplicates and each reflect something distinct.
So if you are a beginner, I would say you shouldn't want to get rid of these rows.
That said, there are some more advanced techniques. For example, you could have the OutputsID column be an array with multiple values. This is harder, more complex, and non-standard.

Determine number of factors of a given number without overlap in MySQL

I have a data set with orders of tickets. Tickets can be bought in packs of 5, or 3, as well as individually. I need to group the data using the quantity of tickets sold per order, to determine if it was a 5 pack (divisible by five), then 3 pack, or else/then individually (1 or 2 qty). So if I have a quantity of 27, I know that order consisted of five "5 packs", and 2 individual tickets.
SUM(CASE WHEN (id % 5) = 0 THEN 1 ELSE 0 END) fivepack
I have this in my query, but stringing these together for fivepack, and threepack, doesn't eliminate the starting number from the total quantity on the next operation. So a quantity of 27, would yield a result of 5 "five packs" and 9 "three packs", and then 27 "individuals".
So given a quantity, how would you first divide by a large factor, get the remainder and divide by the smaller, then finally handle the remainder?
Edit:
The sample packs provide a discount of the purchase price(not relevant to the technical issue), so the first maximum division needs to occur first. So as Gordon Linoff asked below, in the case of 27 tickets quantity, you would take the maximum number of 5 divisions first, then pass the remainder to try to divide by 3, and then return the final remainder as individuals.
The issue is passing the value of one operation in SQL to the next operation, so so on. So I can do Math1, pass Answer1 to Math2, and then pass Answer2 to Math3.
I don't fully understand why 27 would be 5 five packs and 2 individuals rather than any of the following:
27 individuals
9 3-packs
4 5-packs, 2 3-packs, 1-individual
8 3-packs and 3 individuals
and so on.
But, if you want a greedy approach, you can use the following arithmetic:
select floor(num / 5) as five_packs,
floor( (num - 5 * floor(num / 5)) / 3) as three_packs,
num - 5 * floor(num / 5) - 3 * floor( (num - 5 * floor(num / 5)) / 3) as singles
Here is a SQL Fiddle illustrating the logic.

T-SQL query procedure-insert

I am wondering if any of you would be able to help me. I am trying to loop through table 1 (which has duplicate values of the plant codes) and based on the unique plant codes, create a new record for the two other tables. For each unique Plant code I want to create a new row in the other two tables and regarding the non unique PtypeID I link any one of the PTypeID's for all inserts it doesnt matter which I choose and for the rest of the fields like name etc. I would like to set those myself, I am just stuck on the logic of how to insert based on looping through a certain table and adding to another. So here is the data:
Table 1
PlantCode PlantID PTypeID
MEX 1 10
USA 2 11
USA 2 12
AUS 3 13
CHL 4 14
Table 2
PTypeID PtypeName PRID
123 Supplier 1
23 General 2
45 Customer 3
90 Broker 4
90 Broker 5
Table 3
PCreatedDate PRID PRName
2005-03-21 14:44:27.157 1 Classification
2005-03-29 00:00:00.000 2 Follow Up
2005-04-13 09:27:17.720 3 Step 1
2005-04-13 10:31:37.680 4 Step 2
2005-04-13 10:32:17.663 5 General Process
Any help at all would be greatly appreciated
I'm unclear on what relationship there is between Table 1 and either of the other two, so this is going to be a bit general.
First, there are two options and both require a select statement to get the unique values of PlantCode out of table1, along with one of the PTypeId's associated with it, so let's do that:
select PlantCode, min(PTypeId)
from table1
group by PlantCode;
This gets the lowest valued PTypeId associated with the PlantCode. You could use max(PTypeId) instead which gets the highest value if you wanted: for 'USA' min will give you 11 and max will give you 12.
Having selected that data you can either write some code (C#, C++, java, whatever) to read through the results row by row and insert new data into table2 and table3. I'm not going to show that, but I'll show how the do it using pure SQL.
insert into table2 (PTypeId, PTypeName, PRID)
select PTypeId, 'YourChoiceOfName', 24 -- set PRID to 24 for all
from
(
select PlantCode, min(PTypeId) as PTypeId
from table1
group by PlantCode
) x;
and follow that with a similar insert.... select... for table3.
Hope that helps.

Compare rows and get percentage

I found it hard to find a fitting title. For simplicity let's say I have the following table:
cook_id cook_rating
1 2
1 1
1 3
1 4
1 2
1 2
1 1
1 3
1 5
1 4
2 5
2 2
Now I would like to get an output of 'good' cooks. A good cook is someone who has a rating of at least 70% of 1, 2 or 3, but not 4 or 5.
So in my example table, the cook with id 1 has a total of 10 ratings, 7 of which have type 1, 2 and 3. Only three have type 4 or 5. Therefore the cook with id 1 would be a 'good' cook, and the output should be the cook's id with the number of good ratings.
cook_id cook_rating
1 7
The cook with id 2, however, doesn't satisfy my condition, therefore should not be listed at all.
select cook_id, count(cook_rating) - sum(case when cook_rating = 4 OR cook_rating = 5 then 1 else 0 end) as numberOfGoodRatings from cook
where cook_rating in (1,2,3,4,5)
group by cook_id
order by numberOfGoodRatings desc
However, this doesn't take into account the fact that there might be more 4 or 5 than good ratings, resulting in negative outputs. Plus, the requirement of at least 70% is not included.
You can get this with a comparison in your HAVING clause. If you must have just the two columns in the result set, this can be wrapped as a sub-select select cook_id, positive_ratings FROM (...)
SELECT
cook_id,
count(cook_rating < 4 OR cook_rating IS NULL) as positive_ratings,
count(*) as total_ratings
FROM cook
GROUP BY cook_id
HAVING (positive_ratings / total_ratings) >= 0.70
ORDER BY positive_ratings DESC
Edit Note that count(cook_rating < 4) is intended to only count rows where the rating is less than 4. The MySQL documentation says that count will only count non-null rows. I haven't tested this to see if it equates FALSE with NULL but I would be surprised it it doesn't. Worst case scenario we would need to wrap that in an IF(cook_rating < 4, 1,NULL).
I suggest you change a little your schema to make this kind of queries trivial.
Suppose you add 5 columns to your cook table, to simply count the number of each ratings :
nb_ratings_1 nb_ratings_2 nb_ratings_3 nb_ratings_4 nb_ratings_5
Updating such a table when a new rating is entered in DB is trivial, just as would be recomputing those numbers if having redundancy makes you nervous. And it makes all filterings and sortings fast and easy.

MySQL Basic Select Query

I have a MySQL table called connections, with two unsigned integer fields, called a and b (which are unique), with the following values (and many more).
A, B
1, 2
1, 3
8, 9
4, 6
5, 1
3, 7
1 is connected to 2, 3, and 5. 3 is connected to 7. I have been struggling to come up with a query that will select all connections for a given number. For example, number 2 would return the following...
1
2
3
5
7
Number 5 would also return...
1
2
3
5
7
If someone can help me out I would greatly appreciate it. I have been stuck on this for the last week, and have made little to no progress. :(
Thanks in advance!
I don't think your problem cannot be solved with a single select statement. Solution requires multipass scan of your tables to arrive at the final answer
It sounds like you need a hierarchical query here, which exists in Oracle, but I don't think it is in mySql. Here is a link to an article which explains how to get hierarchical functionality in mySql. I have not tried it myself.
http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/