I have a table 'Hobbys' with two columns. It looks like this:
NAME | HOBBY
Alice | sport
Bob | painting
... | ...
Yves | programming
Zooey | theatre
Rows could be duplicated. For example 'Bob' with hobby 'painting' can appear twice, thrice or even more times.
I want find that people, who have more than one hobby. I tried to use query like this one:
select NAME, HOBBY
from Hobbys
group by NAME, HOBBY
order by 1, 2
But I don't know how to use the query result for second grouping by NAME.
To find the users with more than one hobby, just group by the name and count the distinct hobbies;
SELECT name
FROM hobbies
GROUP BY name
HAVING COUNT(DISTINCT hobby)>1
An SQLfiddle to test with.
If you want the users and their hobbies, you can use a CTE;
WITH cte AS (
SELECT name FROM hobbies GROUP BY name HAVING COUNT(DISTINCT hobby)>1
)
SELECT * FROM hobbies JOIN cte ON hobbies.name = cte.name
Another SQLfiddle.
I want find that people, who have more than one hobby.
In my opinion the easiest is using EXISTS
SELECT NAME,HOBBY FROM dbo.Hobbys h1
WHERE EXISTS
(
SELECT 1 FROM dbo.Hobbys h2
WHERE h1.Name = h2.Name AND h1.HOBBY <> h2.HOBBY
)
Try this..
SELECT NAME,HOBBY
FROM Hobbys
GROUP BY NAME
HAVING COUNT(HOBBY) > 1
Related
I am trying to read records that match multiple values in the same field.
Example table : A
UserID License
1 DOG
1 CAT
1 FISH
2 DOG
2 CAT
3 FISH
4 CAT
4 DOG
4 FISH
5 CAT
5 FISH
How can I pull the UserIDs that have all three Licenses DOG, CAT and FISH ?
I am not sure how I could use INNER JOIN here since there are no two tables.
What is the best approach here ?
Thank you
PG
Don't even think about unnecessary INNER JOIN for this simple task. Let's do it using IN
SELECT UserID FROM A WHERE License IN('DOG','CAT','FISH');
N.B But still I'm little bit confused with this line though How can I pull the UserIDs that have all three Licenses DOG, CAT and FISH ?
Edited: This eliminate my confusion about all, try like this way and grab only the UserId from the output.
SELECT UserID,count(*) as lnt FROM A WHERE
License IN('DOG','CAT','FISH')
group by UserId having lnt = 3;
Output:
UserID lnt
1 3
4 3
Fiddle: http://sqlfiddle.com/#!9/e563ef/4
You can use case when... in your sql, like this:
SELECT UserID, SUM(CASE WHEN License IN ("DOG", "CAT", "FISH") THEN 1 ELSE 0 END) AS LICENSE_COUNT
FROM EXAMPLE_TABLE
GROUP BY UserID
HAVING LICENSE_COUNT = 3
"How can I pull the UserIDs that have all three Licenses DOG, CAT and FISH ?"
Like this:
SELECT USERID, COUNT(*) AS LICENSE_COUNT
FROM EXAMPLE_TABLE
GROUP BY USERID
HAVING COUNT(*) = 3
dbfiddle here
try to like this:
select userid
from example_table
WHERE License IN('DOG','CAT','FISH') group by user_id having count(distinct License)=3
As other answers stated, it is better to use IN operator instead of Join. You can get the desired result even without using group by or HAVING. Try this
Select DISTINCT(UserId) from A
Where UserID IN(Select userId from A where License='DOG')
AND UserID IN (Select UserId from A where License='CAT')
AND UserID IN (Select UserId from A where License='FISH')
I have a table in mysql of hashtags:
strHash | nPersonID
-------------------------
#dogowner | 1
#catowner | 1
#dogowner | 2
#mouseowner | 3
#fish | 3
#vancouver | 1
#vancouver | 3
I'd like to query the table with a MySQL statement and say, I want nPersonID = 1, return a result of all people that share one ore more strHash values.
This will allow me to show similar people when viewing a specific person. (or, people who share similar hash tags - some but not necessarily all)
The simplest way to get just a list of people that share hastags with person 1 is this:
SELECT DISTINCT nPersonID
FROM table
WHERE strHash IN (
SELECT b.strHash
FROM table b
WHERE b.nPersonID=1
)
But you can get some little bit of extra info without making things too complex.
For example, this query will list the same people, but also give you a quantifier of how similar these people's hashtags are to those person 1:
SELECT nPersonID, COUNT(DISTINCT strHash) AS shared_hashtags
FROM table
WHERE strHash IN (
SELECT b.strHash
FROM table b
WHERE b.nPersonID=1
)
GROUP BY nPersonID
ORDER BY shared_hashtags DESC
This will select all the people that have one or more of the hashtags that person 1 has... including person 1.
The resuling list will be ordered by the number of common hastags... with the most similar people on top (including person 1).
Try this SQL:
SELECT DISTINCT t2.nPersonID
FROM table t1
JOIN table t2
ON t1.strHash = t2.strHash
WHERE t1.nPersonID = 1
The idea:
Get the hashtags of the selected person
Get all persons which have similar hashtags
Count how many hastags are matching
The query:
SELECT
S.nPersonId
, COUNT(1) AS SimilarHashCount
FROM (
SELECT
strHash
FROM
hashtags
WHERE
nNersonID = 1
) P
INNER JOIN (
SELECT
strHash
, nPersonD
FROM
hashtags
WHERE
nNersonID != 1
) S
ON P.strHash = S.strHash
GROUP BY
S.nPersonID
ORDER BY
COUNT(1) DESC
You can limit the result, or you can use the HAVING statement to filter the results
Many ways to achieve this. I'll do it with following query
SELECT DISTINCT [nPersonID]
FROM [htag]
where strHash in (select strHash FROM [htag] where [nPersonID] = 1)
This will output as below
nPersonID
1
2
3
If you wish to get result without the ID '1' (request id) add another condition
SELECT DISTINCT [nPersonID]
FROM [htag]
where strHash in (select strHash FROM [htag] where [nPersonID] = 1)
and [nPersonID] != 1
Output:
nPersonID
2
3
Hope this helps!
SELECT *, COUNT(*) FROM XXX GROUP BY strHash HAVING COUNT(*) > 1
This question has been asked before - How to select non "unique" rows
The answer above belongs to judda (a bit modified)
Imagine a three-column table, let's say TRAVELS with the columns NAME, and COUNTRY which they've ever been to, and DATE so that there can be duplicate NAME+COUNTRY rows.
--> I don't want to show the actual NAME values, nor the actual COUNTRY values - just their count and only for those that have visited more than 1 country.
It would be a list like this:
| 9 | 2 | meaning 9 people have visited 2 countries,
| 4 | 3 | meaning 4 people have visited 3 countries,
| 2 | 4 | meaning 2 people have visited 4 countries,
etc.
I'm quite bad at SQL but I guess I need to build some kind of nested query:
select count(t1.NAME)
from TRAVELS t1
where (
select count(distinct COUNTRY)
from TRAVELS t2
where t1.name = t2.name
and count(t2.COUNTRY) > 1
)
Obviously this doesn't work, but I hope it shows my general intention. I haven't been able to find anything about this kind of nested double-count, although it's probably simple enough once I see it?
Try it here: http://sqlfiddle.com/#!2/b0762/3
The query:
select
count(*) as people,
countries_visited
from (
select
name,
count(distinct country) as countries_visited
from travels
group by name
having count(distinct country) > 1
) s
group by countries_visited
order by people desc, countries_visited desc
select country_count, count(*) as people_count
from (select name, count(distinct country) as country_count
from travels
group by name
having count(distinct country) > 1)
group by country_count
of course this assumes that name is unique. If not you may want to user the user_id in place of name.
I have two tables, one is a table of names with a category tag and the other is a table of scores for each name
ID Name Category
1 Dave 1
2 John 1
3 Lisa 2
4 Jim 2
and the score table is
PersonID Score
1 50
2 100
3 75
4 50
4 75
I would then like a query that returned something like
Category TotalScore Names
1 150 Dave, John
2 200 Lisa, Jim
Is this possible to do with one query?
I can get the totals with a sum query and grouping by category but cannot see a way to get the names as I would like.
Many thanks
You need to use group_concat:
select Category, sum(Score) as TotalScore, group_concat(Name) as Names from categories
join scores on scores.category = categories.category
group by category
Or even better:
group_concat(DISTINCT Name ORDER BY Name ASC SEPARATOR ',') as names
Just add group_concat(Name) as names into your sum query.
Here is a solution working for Postgres (which doesn't have a group_concat() function):
select category, sum(score) as TotalScore, array(select id from perso where category=P.category order by id) as Names from perso P JOIN scores S ON S."PersonID" = P.id GROUP BY category;
(I know this was a MySQL question, but nonetheless someone might google it up but needs an answer for Postgres :) )
I use similar queries (10) as following queries (modified) to find sum
SELECT sum(amount) AS amount
FROM `students`
WHERE sex='M'
&& name in ('salil', 'anil', 'gaikwad')
...and:
SELECT sum(amount) AS amount
FROM `students`
WHERE sex='M'
&& name in ('salil1', 'anil1', 'gaikwad1')
i want to make a single query of the above 10 queries. is it possible?
You can use UNION
SELECT 'subset1', sum(amount) AS amount FROM students WHERE sex='M' and name in ('salil', 'anil', 'gaikwad')
UNION
SELECT 'subset2', sum(amount) AS amount FROM students WHERE sex='M' and name in ('salil1', 'anil1', 'gaikwad1')
However, you probably query these sets of students for a reason, perhaps anil, salil and gaikwad are one group of students. If so, you should reflect this in the database structure, not in your code.
You could add a field 'SUbset' or 'Group' or whatever that is, to students table, so it looks like this:
name group_id
salil 1
anil 1
gaikwad 1
salil1 2
...
Then you can do
select group_id, sum(amount) from students group by group_id
Try something like this
SELECT sum(amount) AS amount
FROM students INNER JOIN
(SELECT 'salil%' Val UNION SELECT 'anil%' UNION SELECT 'gaikwad%') s ON students.NAME LIKE s.Val
WHERE sex='M'
This allows you to use the values in the second Table to join with LIKE.