I have been struggling with getting an opposite search in MySQL.
Here is a sample database:
+-------+--------+
| name | fruits |
+-------+--------+
| Jimmy | pear |
| Jimmy | apple |
| Jimmy | peach |
| Becky | pear |
| Garry | apple |
| Garry | pear |
+-------+--------+
What I'm trying to get is names of all people that did not eat apple. When I do query searching for WHERE fruits NOT LIKE "%apple%" I get not only Becky (which is the only one who did not eat it), but also two fields of Jimmy and one of Garry, because there were other occurrences where they ate something else.
How should I write a query?
this is one possible approach
select name where name not in (select name where fruits like '%apple%')
Related
I'm not sure how to word this correctly, but I need to get the sequential number on duplicates in google sheets. For example, column Count is what I'm looking for:
+-------+-------+
| Name | Count |
+-------+-------+
| Joe | 1 |
| Lisa | 1 |
| Jenny | 1 |
| Lisa | 2 |
| Lisa | 3 |
| Joe | 2 |
| Jenny | 2 |
Sample sheet: https://docs.google.com/spreadsheets/d/1BB4bzzR3TTAfW5SwvNG_W3AsIYqlSEaSOad5wB4sdko/edit#gid=0
Any help is appreciated, thanks!
For an array-enabled solution, you could try in C1
={"Count"; ArrayFormula(iferror(SORT(ROW(A2:A),SORT(ROW(A2:A),A2:A,1),1)-MATCH(A2:A,SORT(A2:A),0)-ROW()+1))}
For more background, also see this thread.
Got it, it's: =COUNTIF($A$2:A2,A2)
These are my tables, I've created a tbl_relation which have data_id from tbl_data and tag_id from tbl_tags. data_id can have as many tag_ids.
For instance in the below case:
John is associated with food, apple, orange.
Linus is associated with food, potato.
Is this the right way to do it in terms of speed and storage? as my tbl_tags and tbl_data can have at least 1 million entries and a name in tbl_data can be associated with at least 5 tag_name.
tbl_tags
+----+--------+
| id | name |
+----+--------+
| 1 | food |
+----+--------+
| 2 | apple |
+----+--------+
| 3 | orange |
+----+--------+
| 4 | potato |
+----+--------+
| 5 | fruit |
+----+--------+
tbl_data
+----+--------+
| id | name |
+----+--------+
| 1 | John |
+----+--------+
| 2 | Linus |
+----+--------+
| 3 | Bill |
+----+--------+
| 4 | Steve |
+----+--------+
| 5 | Dennis |
+----+--------+
tbl_relation
+---------+--------+
| data_id | tag_id |
+---------+--------+
| 1 | 1 |
+---------+--------+
| 1 | 2 |
+---------+--------+
| 1 | 3 |
+---------+--------+
| 2 | 1 |
+---------+--------+
| 2 | 4 |
+---------+--------+
Which is it?
The title says "1 to many". In that case, tags should have a column saying which one person (data_id) is related to that tag.
Perhaps Sam likes apple and potato and kiwi? That is, the text implies that it might be many:many. In this case, you need a 2-column table, essentially as you describe. Here are my tips on the optimal design of such a table. The tips address your questions of speed and space.
This seems like a many-to-many relation, as tbl_data_id can associated with multiple tbl_tags_id and vice-versa (seeing entries in tbl_relation).
If this is the case, your approach seems pretty standard as per the normal forms.
One recommedation is that create foreign key constraints on your tbl_relation table.
ID | fruit | who | days_ago |
----------------------------------
1 | orange | Adam | 2 |
2 | banana | Adam | 3 |
3 | apple | Adam | 4 |
4 | kiwi | Adam | 2 |
6 | banana | Jimmy | 3 |
7 | apple | Jimmy | 5 |
8 | grapes | Jimmy | 1 |
9 | orange | Carol | 2 |
10 | grapes | Carol | 6 |
11 | lemon | Carol | 3 |
And my problem is:
The table contained information about who bought what fruit and when (when is an extra information I just need to keep).
I need to select all the fruits that Adam didn't buy.
ID | fruit | who | days_ago |
----------------------------------
8 | grapes | Jimmy | 1 |
10 | grapes | Carol | 6 |
11 | lemon | Carol | 3 |
And if Jimmy bought them, I don't want to know if Carol bought them too.
And my result should be this:
ID | fruit | who | days_ago |
----------------------------------
8 | grapes | Jimmy | 1 |
11 | lemon | Carol | 3 |
When I GROUP BY fruit, I lose information about who and days_ago (I don't understand how they're chosen).
And when I select unique fruits and drop all that Adam bought, I lose grapes which both Jimmy and Carol bought.
This isn't the actual table I'm working on. Just a simplification of what I'm struggling with.
Any ideas?
If you want the fruits that Adam didn't buy, you can use a subquery for this. Have the subquery select the fruits he did buy, and then have the main query say "not those".
SELECT *
FROM fruits
WHERE fruit NOT IN(
SELECT fruit
FROM fruits
WHERE who = "Adam"
)
DEMO: http://sqlfiddle.com/#!9/3974d/1
When you use GROUP BY, you are combining multiple rows into one. The other rows' data isn't gone, just hidden. Try using GROUP_CONCAT to see the list of who fields.
SELECT ID, fruit,
GROUP_CONCAT(who) as who,
GROUP_CONCAT(days_ago) AS days_ago
FROM fruits
WHERE fruit NOT IN(
SELECT fruit
FROM fruits
WHERE who = "Adam"
)
GROUP BY fruit
DEMO: http://sqlfiddle.com/#!9/3974d/3
Here's what I'm trying to achieve. I have this table:
Table 'Receipts':
Fruit |Receipt| Name
| No |
--------|-------|-------
Apple | 534 | Mike
Apple | 422 | Mike
Apple | 355 | Mike
Peach | 646 | Robert
Banana | 412 | Alex
Banana | 124 | Alex
Banana | 067 | Sam
Banana | 975 | Sam
Banana | 645 | Sam
And I want to display each unique combination, so each item every person has:
Apple | Mike
Peach | Robert
Banana | Alex
Banana | Sam
I can only manage to either group things by fruit or by name, no idea how I could get this done.
Can anybody help?
SELECT Fruit, Name FROM tableName
GROUP BY Fruit, Name
Or if you want to have a unique combination, you can even do it as
SELECT Fruit, Name
FROM mytable
GROUP BY concat(Fruit,'-', Name) //group the data based on unique word formed
Trying to figure out how to display the content of two mysql tables when one table has multiple matching rows, eg. so that the tables below display the results:
London - Harry Smith, Oliver Jones, Jack Taylor
Manchester - Charlie Williams, Jacob Brown
Table One Table two
+-----------------------------+ +----------------------------------+
| id | branchid | store | | branchid | firstname | employee |
+-----------------------------+ +----------------------------------+
| 1 | 1 | London | | 1 | Harry | Smith |
| 2 | 2 | Manchester | | 1 | Oliver | Jones |
+-----------------------------+ | 1 | Jack | Taylor |
| 2 | Charlie | Williams |
| 2 | Jacob | Brown |
+----------------------------------+
Many thanks.
GROUP_CONCAT will do the job, although we first need to CONCAT as well to put firstname and lastname together:
SELECT b.store, GROUP_CONCAT(CONCAT(e.firstname, ' ', e.employee)) AS Employees
FROM TableOne b INNER JOIN TableTwo e on b.branch = e.branchid
GROUP BY b.store;
SqlFiddle here
Result:
Store Employees
London Harry Smith,Jack Taylor,Oliver Jones
Manchester Jacob Brown,Charlie Williams`