Comparando dos conjuntos de datos en SQL
Frecuentes
Visto 1,879 veces
0
I am wishing to compare two sets of data using SQL wherever possible. Please consider the following data structures:
tbl_users:
+---------+----------+
| user_id | avatar |
+---------+----------+
| 1 | test.jpg |
| 2 | 1234.jpg |
+---------+----------+
tbl_shortlists:
+------+--------+
| id | owner |
+------+--------+
| 1 | 1 |
| 2 | 2 |
+------+--------+
tbl_shortlist_items:
+---------+--------------+
| item_id | shortlist_id |
+---------+--------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 1 | 2 |
| 2 | 2 |
+---------+--------------+
Deseo seleccionar el tbl_users
.user_id
y tbl_users
.avatar
where the shortlist owned by any user contains two or more of the same item_id
as the current owner. So, let's assume I am looking up the user_id 1, with the above data structure. Since the Shortlist with the ID shares two items with shortlist_id
1 (i.e. user 1's shortlist), I would like to return user_id
= 2 y avatar
= 1234.jpg.
I am at a loss as to how to do this in pure SQL. I was thinking that it might be possible to use IN()
, but I don't know if that would work.
Here's some pseudo-code to hopefully explain a little better what I would like:
Select user_id and avatar for each shortlist that contains two or more item_ids that are in the shortlist that is owned by user_id = 1.
1 Respuestas
3
As always with SQL it helps to break it down into small sections. i.e. the first thing you need is all the items in short lists that the current user owns:
SELECT Item_ID
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Owner = 1 -- CURRENT USER
Next you need all users who have short lists with the same items in. For explanatory purposes I will build up as an IN
statement, but an INNER JOIN may perform better.
SELECT Owner
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Item_ID IN
-- RESULTS FROM LAST QUERY START
( SELECT Item_ID
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Owner = 1 -- CURRENT USER
)
-- RESULTS FROM LAST QUERY END
AND Owner != 1 -- CURRENT USER
You then need to limit this to those that have 2 or more, by adding a GROUP BY
y HAVING
SELECT Owner
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Item_ID IN
-- RESULTS FROM LAST QUERY START
( SELECT Item_ID
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Owner = 1 -- CURRENT USER
)
-- RESULTS FROM LAST QUERY END
AND Owner != 1 -- CURRENT USER
GROUP BY Owner
HAVING COUNT(DISTINCT tbl_ShortList_Items.Item_ID) > 1
Entonces necesitas usar tbl_users
to get the avatar for these owners
SELECT User_ID, Avatar
FROM tbl_Users
WHERE User_ID IN
-- RESULTS FROM LAST QUERY START
( SELECT Owner
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Item_ID IN
( SELECT Item_ID
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Owner = 1 -- CURRENT USER
)
AND Owner != 1 -- CURRENT USER
GROUP BY Owner
HAVING COUNT(DISTINCT tbl_ShortList_Items.Item_ID) > 1
)
-- RESULTS FROM LAST QUERY END
As I said, I think rearranging this to JOINs will be optimised better, but have not tested this theory.
SELECT User_ID, Avatar
FROM tbl_Users
INNER JOIN
( SELECT Owner
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
INNER JOIN
( SELECT Item_ID
FROM tbl_ShortList_Items
INNER JOIN tbl_ShortLists
ON tbl_ShortLists.ID = tbl_ShortList_Items.ShortList_ID
WHERE Owner = 1 -- CURRENT USER
) CurrentUserItems
ON CurrentUserItems.Item_ID = tbl_ShortList_Items.Item_ID
WHERE Owner != 1
GROUP BY Owner
HAVING COUNT(DISTINCT tbl_ShortList_Items.Item_ID) > 1
) MatchUsers
ON MatchUsers.Owner = tbl_Users.User_ID
Respondido 28 ago 12, 15:08
¡Gracias por tu gran respuesta! - Ben M
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas mysql sql or haz tu propia pregunta.
I think that your question is not clear enough, can you explain it different? if you can use sqlfiddle would be great - jcho360
I have edited the question to include a brief pseudo-code that should make things a little clearer. - BenM