关系代数 - sql(常用运算符)
Relational algebra - sql (common operators)
我有这些关系方案:
Participate (FestivalName, Artist)
Attend(ID, FestivalName)
Prefer (ID, FestivalName)
Like (ID, Artist)
I would like to list the people which only attend festivals that are
not of their preference and that at the same time, in one of those
festivals, at least two artists that they like participated (so, 2 or
more). Finally, show the ID and the festival.
我想用常用的运算符来解决这个问题:
selection operator, projection operator, union operator, difference operator and cartesian product
这是一个例子:
ATTEND TABLE
147|HannaBalusa |
147|FestivalTOP |
147|BestFestival|
PREFER TABLE
147|FestivalTOP|
LIKE TABLE
147|PaulMackarney|
147|BobDeylan |
PARTICIPATE TABLE
HannaBalusa |PaulMackarney |
HannaBalusa |BobMurley |
FestivalTOP |BobDeylan |
BestFestival|PaulMackarney |
BestFestival|BobDeylan |
所以,我应该得到这个输出:
147|BestFestival
我可以使用 SQL 解决这种情况,但我在使用关系代数时遇到问题。
可以帮我吗?
执行您想要的操作的惯用 SQL 查询可能看起来像这样,但是它使用的 SQL 功能比您列出的要多。
SELECT A.ID, A.FestivalName
FROM Attend A
JOIN Participate P
ON A.FestivalName = P.FestivalName --Adds rows with artists for each attended festival
JOIN Like L
ON L.ID = A.ID AND L.Artist = P.Artist --Leaves only rows with `Like`d artists
WHERE NOT EXISTS (
SELECT 1
FROM Prefer Pr
WHERE Pr.ID = A.ID AND Pr.FestivalName = A.FestivalName
) --Removes people who have ever attended a prefered festival
GROUP BY A.ID, A.FestivalName --Allows to count liked artists per festival
HAVING COUNT(L.Artist) >= 2 --Leaves only festivals with 2 or more liked artists
用你描述的操作来完成,它可能看起来像这样
SELECT DISTINCT S1.ID, S1.FestivalName
FROM (
SELECT A.ID, A.FestivalName, P.Artist
FROM Attend A
CROSS JOIN Participate P
CROSS JOIN Like L
WHERE A.FestivalName = P.FestivalName --Rows with artists for each attended festival
AND L.ID = A.ID AND L.Artist = P.Artist --Leaves only rows with `Like`d artists
) S1
CROSS JOIN ( -- Copy of the first subquery
SELECT A.ID, A.FestivalName, P.Artist
FROM Attend A
CROSS JOIN Participate P
CROSS JOIN Like L
WHERE A.FestivalName = P.FestivalName
AND L.ID = A.ID AND L.Artist = P.Artist
) S2
WHERE S1.ID = S2.ID
AND S1.FestivalName = S2.FestivalName
AND S1.Artist != S2.Artist --Removes festivals with only 1 liked artist
MINUS -- Remove all rows with people who ever attended prefered festivals
SELECT ID, FestivalName
FROM ( --People who attended prefered festivals
SELECT DISTINCT A.ID
FROM Attend A
CROSS JOIN Prefer P
WHERE A.ID = P.ID AND A.FestivalName = P.FestivalName
)
CROSS JOIN ( -- All existent festivals
SELECT FestivalName
FROM Attend
)
我有这些关系方案:
Participate (FestivalName, Artist)
Attend(ID, FestivalName)
Prefer (ID, FestivalName)
Like (ID, Artist)
I would like to list the people which only attend festivals that are not of their preference and that at the same time, in one of those festivals, at least two artists that they like participated (so, 2 or more). Finally, show the ID and the festival.
我想用常用的运算符来解决这个问题:
selection operator, projection operator, union operator, difference operator and cartesian product
这是一个例子:
ATTEND TABLE
147|HannaBalusa |
147|FestivalTOP |
147|BestFestival|
PREFER TABLE
147|FestivalTOP|
LIKE TABLE
147|PaulMackarney|
147|BobDeylan |
PARTICIPATE TABLE
HannaBalusa |PaulMackarney |
HannaBalusa |BobMurley |
FestivalTOP |BobDeylan |
BestFestival|PaulMackarney |
BestFestival|BobDeylan |
所以,我应该得到这个输出:
147|BestFestival
我可以使用 SQL 解决这种情况,但我在使用关系代数时遇到问题。
可以帮我吗?
执行您想要的操作的惯用 SQL 查询可能看起来像这样,但是它使用的 SQL 功能比您列出的要多。
SELECT A.ID, A.FestivalName
FROM Attend A
JOIN Participate P
ON A.FestivalName = P.FestivalName --Adds rows with artists for each attended festival
JOIN Like L
ON L.ID = A.ID AND L.Artist = P.Artist --Leaves only rows with `Like`d artists
WHERE NOT EXISTS (
SELECT 1
FROM Prefer Pr
WHERE Pr.ID = A.ID AND Pr.FestivalName = A.FestivalName
) --Removes people who have ever attended a prefered festival
GROUP BY A.ID, A.FestivalName --Allows to count liked artists per festival
HAVING COUNT(L.Artist) >= 2 --Leaves only festivals with 2 or more liked artists
用你描述的操作来完成,它可能看起来像这样
SELECT DISTINCT S1.ID, S1.FestivalName
FROM (
SELECT A.ID, A.FestivalName, P.Artist
FROM Attend A
CROSS JOIN Participate P
CROSS JOIN Like L
WHERE A.FestivalName = P.FestivalName --Rows with artists for each attended festival
AND L.ID = A.ID AND L.Artist = P.Artist --Leaves only rows with `Like`d artists
) S1
CROSS JOIN ( -- Copy of the first subquery
SELECT A.ID, A.FestivalName, P.Artist
FROM Attend A
CROSS JOIN Participate P
CROSS JOIN Like L
WHERE A.FestivalName = P.FestivalName
AND L.ID = A.ID AND L.Artist = P.Artist
) S2
WHERE S1.ID = S2.ID
AND S1.FestivalName = S2.FestivalName
AND S1.Artist != S2.Artist --Removes festivals with only 1 liked artist
MINUS -- Remove all rows with people who ever attended prefered festivals
SELECT ID, FestivalName
FROM ( --People who attended prefered festivals
SELECT DISTINCT A.ID
FROM Attend A
CROSS JOIN Prefer P
WHERE A.ID = P.ID AND A.FestivalName = P.FestivalName
)
CROSS JOIN ( -- All existent festivals
SELECT FestivalName
FROM Attend
)