Get related rows in the same table? - mysql

I'm struggling with this one. What I need is to Select a row AND other rows from the same table that are related. Here is an example of the table:
table
key | value | related
=================================
1 | omg | 0
2 | lol | 0
3 | rofl | 2
4 | barfoo | 0
5 | foo | 0
6 | bar | 0
...
20000 | haha | 2
(where the related "2" is the row key for "lol")
So in the case that i do (not simultaneously) either this:
SELECT * FROM table Where value='lol'
or this
SELECT * FROM table Where value='rofl'
or this
SELECT * FROM table Where value='haha'
it should return:
key | value | related
=================================
2 | lol | 0
3 | rofl | 2
20000 | haha | 2
Any ideas guys?
Thanks a lot!

try this:
Select * From table t
Where Exists
(Select * From Table
where value = #theValue
and valueKey in (t.ValueKey, t.related))

Related

How can i calculate the average of fields and exclude the 0 values

I have this:
SELECT
ROUND(AVG(coffee)) 'coffee',
ROUND(AVG(cappucino)) 'cappucino',
ROUND(AVG(espresso)) 'espresso',
ROUND(AVG(machine)) 'machine'
FROM `reviews` ORDER BY `username`
My Table looks like:
+-----+-----------+---------------+---------------+---------------+---------------+
| id | name | coffee | cappucino | espresso | machine |
+-----+-----------+---------------+---------------+---------------+---------------+
| 1 | Joe | 5 | 4 | 5 | 4 |
| 2 | Jane | 3 | 5 | 2 | 5 |
| 3 | Mike | 0 | 0 | 0 | 5 |
+-----+-----------+---------------+---------------+---------------+---------------+
I need the average of the reviews but Mike doesn't drink any coffee and he clicked the "Does not apply" button. So the current average is:
coffee 2.66666667
cappucino 3
espresso 2.33333333
machine 4.66666667
But it should be:
coffee 4
cappucino 4.5
espresso 3.5
machine 4.66666667
How can I figure this out?
NULL values are ignored by AVG, so do AVG(NULLIF(coffee,0)). Or store NULL instead of 0 in the first place.
This is definitely a great question. I have come up with a solution.
select avg(coffee) from data where coffee>0 union select avg(cappucino) from data where cappucino >0 union select avg(expresso) from data where expresso>0 union select avg(machine) from data where machine>0;
Try this. I'm calculating averages of all fields separately using the where condition that the value in the field should be greater than 0 and then I am displaying the UNION of all queries.
This will be the output... To avoid getting avg(coffee) as the column header, you may use ALIAS.
+-------------+
| avg(coffee) |
+-------------+
| 4.0000 |
| 4.5000 |
| 3.5000 |
| 4.6667 |
+-------------+
I hope this was helpful.
This was the fix:
SELECT
ROUND(AVG(NULLIF(coffee,0))) 'coffee',
ROUND(AVG(NULLIF(cappucino,0))) 'cappucino',
ROUND(AVG(NULLIF(espresso,0))) 'espresso',
ROUND(AVG(NULLIF(machine,0))) 'machine'
FROM `reviews` ORDER BY `username`

How to delete table rows that have not matches rows in second table

I have 2 tables in 1 database.
In the 2 tables there are several rows with the same contents.
table visitor
--------------------------
id | mytoken1 |
--------------------------
1 | token_abcd |
2 | token_efgh |
3 | token_ijkl |
4 | token_mnop |
--------------------------
table favorites
--------------------------
id | mytoken2 |
--------------------------
1 | token_abcd |
2 | token_efgh |
3 | token_ijkl |
4 | token_mnop |
5 | token_aaaa |
6 | token_bbbb |
7 | token_cccc |
8 | token_dddd |
--------------------------
How do I delete the mytoken2 column that is not in the mytoken1 column?
So in the example above I want to delete 4 rows of data, including:
token_aaaa
token_bbbb
token_cccc
token_dddd
I have tried to find a solution until I was dizzy but it has not been resolved, I hope someone will help me here ..
You can do using NOT IN
DELETE FROM favorites
WHERE token2 NOT IN (SELECT token1 FROM visitor)
You can use NOT EXISTS.
DELETE FROM favorites
WHERE NOT EXISTS (SELECT *
FROM visitor
WHERE visitor.mytoken1 = favorites.mytoken2);
JOIN also can be used here:
DELETE favorites.*
FROM favorites
LEFT JOIN visitor ON visitor.mytoken1 = favorites.mytoken2
WHERE visitor.id IS NULL;
Here you can test SQL query

How to find max of mysql varchar column

i have a table like this with a var char field reference_number
actually i need to get the max of number in that field
<<student>>
|`id` | `reference_number`(varchar(25))
--------------------------
| 1 | L250
| 2 | SP521
| 3 | S120
| 4 | SP500
| 5 | S122
the desired result is 521 because if we are avoiding the non numeric value then it will come like this
|`id` | `reference_number`
--------------------------
| 1 | 250
| 2 | 521
| 3 | 120
| 4 | 500
| 5 | 122
how to get the the value 521 from the table
I assume you have extracted 'reference_number' as shown in the second snippet from the first snippet. if so, try :::
select max(cast (reference_number as int)) from student
In order to get the number 521 (and all the numbers from the reference_number column) you could try:
SELECT *
FROM yourtable
WHERE reference_number REGEXP '^[0-9]+$';
And then you can add an order by statement.

Count the rows of a table, while checking if the value is NULL or not and grouping the results by the values of another column

I am stuck trying to find a solution to my silly little problem.
The MySQL table looks as follows:
-- Create a table that will record all AdCamp hits
CREATE TABLE `advertising_campaign_hits` (
`adcamp_hit_id` INT NOT NULL AUTO_INCREMENT,
`adcamp_id` INT,
`customer_id` INT,
`recorded_at` DATETIME,
PRIMARY KEY (`adcamp_hit_id`)
) ENGINE=MyISAM;
Example values would look like this:
a_h_id | a_id | c_id | ...
1 | 1 | 1 | ...
2 | 1 | 2 | ...
3 | 1 | 3 | ...
4 | 1 | 0 | ...
5 | 1 | 0 | ...
6 | 2 | 1 | ...
7 | 2 | 0 | ...
The goal here is to count the number of hits for each of the advertising campaigns, but divide them into two groups of KnownCustomers and UnknownCustomers and then further divide them each by adcamp_id.
So the results I would expect to get are:
adcamp_id | HitsByKnown | HitsByUnknown
1 | 3 | 2
2 | 1 | 1
I am currently stuck in where I can get SQL to give me two separate rows for each of the adcamps, but the results of COUNT(*) list all of my entries.
So what I get is:
adcamp_id | HitsByKnown | HitsByUnknown
1 | 4 | 3
2 | 4 | 3
I can't figure out how to split it all up.
select adcamp_id,sum(if(customer_id>0,1,0)) as HitsByKnown,sum(if(customer_id=0,1,0)) as HitsByUnknown from advertising_campaign_hits group by adcamp_id
or even easier:
select adcamp_id,sum(customer_id!=0) as HitsByKnown,sum(customer_id=0) as HitsByUnknown from advertising_campaign_hits group by adcamp_id

Is it possible to share a set between two tables in MySQL?

I am currently in the process of designing a database.
I have a table of 20,000+ records, which has a set in it (4 values). I also am making another table (100+ records) which will have an enum over the same set (1 value from the same set)
Example of current:
tbl1 tbl2
ID | Letters | Stuff ID | Letter | Stuff
---------------------- ---------------------
0 | A,B,C,D | ... 0 | D | ...
1 | A,B,C,D | 1 | C |
2 | C,D | 2 | A |
3 | B,C,D | 3 | D |
...
Is there a way to make sure that the sets are the same, and can I compare the enum and the set?
I also might need to add more options to the set as our data changes. Would a separate table for that set be necessary, and then an association table for that?
Example of what I just said:
tbl1 tbl2
ID | Stuff ID | LetterID | Stuff
------------ ------------------------
0 | ... 0 | 3 | ...
1 | 1 | 2 |
2 | 2 | 0 |
3 | 3 | 3 |
...
tblLetters tblLetters1 (Association table)
ID | Letter tbl1Id | letterId
------------ ------------------
0 | A 0 | 0
1 | B 0 | 1
2 | C 0 | 2
3 | D 0 | 3
...? ...
My only major concern with this is whether the size of the association table would be too big (most of the rows in tbl1 will have all 4 elements of the set).
Thank you! Sorry if I didn't explain my problem very well. I'm very green when it comes to SQL.
Your second solution seems fine, comma separated values in 1 column should normally be avoided. You might not need an ID, and I'd drop the ENUM type for the column, and use the actual type / column definition of the letter in tblLetters:
tbl1 tbl2
ID | Stuff ID | Letter | Stuff
------------ ------------------------
0 | ... 0 | D | ...
1 | 1 | C |
2 | 2 | A |
3 | 3 | D |
tblLetters tblLetters1 (Association table)
Letter tbl1Id | letter
------------ ------------------
A 0 | A
B 0 | B
C 0 | C
D 0 | D
Possibly add a FOREIGN KEY constraint to tblLetters1.letter & tbl2.letter to enforce an existing letter from tblLetters.
And 80K rows in total is not many by any standard, it should be fine (use the proper indexes though)
I'm going to take a stab at your question....
So from what I understand, you just want to make sure the tables have the "options" or "variables" in the enum and set fields.
What you can do is:
Show create table tbl1;
What you should see is
Create table tbl1
(id int unsigned,
stuff set('A','B','C','D'),
.....)
Show create table tbl2;
Create table tbl2
(id int unsigned,
stuff enum('A','B','C','D'),
.....)
All you would need to to, technically, is make sure both tables have the same variables. You can do this with a script or just be aware of it when you do an ALTER TABLE.