SQL statement to get similar records inside lookup table - mysql

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)

Related

Select by fixed categories top result and rest in others

On the begging Im gonna say that I can't change any structure of database, only select is allowed.
I thought about this about 1 week and can't find solution for my problem.
Lets assume I have table like this: https://www.db-fiddle.com/f/cEbW3ZoQBRpun3Pt5g3h3v/1
There I have products with their categories and I'd to make report which show me how much there is product in X category and select TOP 3 with count and others display in "Others" with all other count. But some categories should be count together (I'd like to predefined them in select query), for example I'd have A count with G and B-C, E-F.
So result should looks like:
B-C = 7
A-G = 6
D = 5
OTHERS = 6
Tell me, it's even possible with just select, if yes please tell me how (example would be nice) if not I'm gonna tell this to my manager because RN he won't believe me saying "you can do it".
I would approach this with a derived table that represents the mapping between categories, that the original table can be left joined with. You can then aggregate, which gives you the count of product for each of these "real" categories. Then, you can use window functions (available in MySQL 8.0 only) and an additional level of aggregation to separate the top 3 from the rest of the "real" categories.
select
case when rn <= 3 then real_category else 'Other' end final_category,
sum(no_products) no_products
from (
select
coalesce(x.new_category, p.category) real_category,
count(*) no_products,
rank() over(order by count(*) desc) rn
from products p
left join (
select 'A' category, 'A-G' new_category
union all select 'G', 'A-G'
union all select 'B', 'B-C'
union all select 'C', 'B-C'
union all select 'E', 'E-F'
union all select 'F', 'E-F'
) x on x.category = p.category
group by real_category
) t
group by final_category
order by no_products desc
Demo on DB Fiddle:
final_category | no_products
:------------- | ----------:
A-G | 6
B-C | 6
D | 5
Other | 5

Guidance required for sql query

I have a database with one table as shown below. Here I'm trying to write a query to display the names of medication manufactured by the company that manufactures the most number of medications.
By looking at the table we could say the medication names which belongs to the company id 1 and 2 - because those company manufactures the most medication according to this table, but I'm not sure how to write a query for selecting the same i said before.
ID | COMPANY_ID | MEDICATION_NAME
1 1 ASPIRIN
2 1 GLUCERNA
3 2 SIBUTRAMINE
4 1 IBUPROFEN
5 2 VENOFER
6 2 AVONEN
7 4 ACETAMINOPHEN
8 3 ACETAMINO
9 3 GLIPIZIDE
Please share your suggestions. Thanks!
Several ways to do this. Here's one which first uses a subquery to get the maximum count, then another subquery to get the companies with that count, and finally the outer query to return the results:
select *
from yourtable
where companyid in (
select companyid
from yourtable
group by companyid
having count(1) = (
select count(1) cnt
from yourtable
group by companyid
order by 1 desc
limit 1
)
)
SQL Fiddle Demo
This Query might work. I have not tested but the logic is correct
SELECT MEDICATION_NAME
FROM TABLE where
COMPANY_ID=(SELECT
MAX(counted)
FROM ( SELECT COUNT(*) AS counted FROM TABLE ) AS counts);

Grouping users by group ids in mysql, exclude specified userid from the results?

There is a small application that I've been tasked on, that deals with getting latest posts in a group. In this sample below, I have there is a MySQL table formatted as such:
groupid userid date_updated
1 1 [date]
1 2 [date]
2 1 [date]
2 2 [date]
2 3 [date]
...
How do I do an SQL statement as such as the results go out in this manner (assuming I give a userid with a value of 1 for example):
groupid userid date
1 2 [date]
2 2 [date]
2 3 [date]
These are all ordered by date. As you may have noticed, the results do not include the provided userid (as the requirement is only to get users other than the supplied user ID). In other words, show only users other than the specified user in groups where the specified user is part of.
Is it possible to do this in a single SQL statement?
Search select query with where
select * from table where userid != '1'
Try the following solution.
select
tbl.*
from
tbl INNER JOIN
(select groupid, userid, max(date_updated)
from tbl
group by groupid, userid) tbl2
USING(groupid, userid)
ORDER BY tbl.date_updated;
You can use this
SELECT tbl.* FROM (SELECT * FROM tablename ORDER BY date DESC) as tbl GROUP BY tbl.groupid
I managed to find a possible answer to my question here with this SQL statement:
SELECT a.groupid, a.userid, a.date_updated
FROM group_participants a
WHERE a.groupid IN (
SELECT DISTINCT b.groupid FROM group_participants b WHERE b.userid = 1
)
AND a.user_id <> 1
GROUP BY a.userid
ORDER by a.date_updated DESC
Thank you guys those SQL statements you posted, gave me an idea. I don't know if the SQL statement above can still be optimized, but this one above gave me the correct answer.

MS SQL double group by

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

MYSQL Query for SUM and DISTINCT?

I have a database with the first five columns like this:
ID NAME QUANTITY PRICE KIND
1 Dog 2 5 A
2 Cat 1 6 B
3 Dog 2 5 C
4 Bird 5 5 C
(DOG QUANTITY and PRICE will always be the same)
What I want to do to is to something like
SELECT KIND, SUM(QUANTITY * PRICE) GROUP BY KIND WHERE DISTINCT NAME
So that I get something that looks like this:
A 10
B 6
C 25
(The duplicate DOG is eliminated.)
I know my syntax above is grossly wrong -- it's just seems to be the most eloquent way of explaining what sort of thing I'm looking for.
In other words, I want to get rid of non-distinct NAMES then SUM the rest. I seem to be able to do one or the other but not both.
Any ideas? If worse comes to worst I can do it as a loop in PHP rather than as a single MYSQL query.
I'm not really clear about either what the rules are or why your table is in that format (with repeated name, quantity,price) but here is one way of getting your expected output.
select kind, SUM(quantity*price)
from
(
SELECT name, quantity, price, min(kind) kind
FROM YourTable
group by name, quantity, price
) t
group by kind
Here I chose the item with the lowest ID as the one to keep:
Select T.Kind, Sum( T.Quantity * T.Price ) As Total
From Table As T
Where Id = (
Select Min(T2.Id)
From Table As T2
Where T2.Name = T.Name
)
Group By T.Kind
Assuming that your table is unique on Name and Kind, you can do:
Select T.Kind, Sum( T.Quantity * T.Price ) As Total
From Table As T
Where T.Kind = (
Select Min(T2.Kind)
From Table As T2
Where T2.Name = T.Name
)
Group By T.Kind