我在MySQL中有这个日志表,列有ActionName和SourceName。
可以从不同来源多次注册相同的操作。
因此示例表可能看起来像
ActionName SourceName
----------------------------
Add S01
Add S02
Add S02
Edit S01
Edit S01
Delete S01
Delete S02
现在我想查询此表并找到S01和S02已执行的操作。结果将是:
ActioName
--------------
Add
Delete
我如何用SQL解决这个问题?
答案 0 :(得分:4)
具体答案......
SELECT
ActionName
FROM
yourTable
WHERE
SourceName in ('S01', 'S02')
GROUP BY
ActionName
HAVING
COUNT(DISTINCT SourceName) = 2
你的具体问题可能会更快......
SELECT
a.SourceName
FROM
yourTable AS a
INNER JOIN
yourTable AS b
ON a.ActionName = b.ActionName
WHERE
a.SourceName = 'S01'
AND b.SourceName = 'S02'
一般答案......
SELECT
ActionName
FROM
yourTable
INNER JOIN
tableWithSourceNames
ON yourTable.SourceName = tableWithSourceNames.SourceName
GROUP BY
ActionName
HAVING
COUNT(DISTINCT yourTable.SourceName) = (SELECT COUNT(DISTINCT SourceName) FROM tableWithSourceNames)
事实证明,这种情况非常严重(因为你的桌子尺寸增加,性能直线下降)。你可以进行优化......
通过保存一些关于每个SourceName的选择性的元数据......
CREATE TABLE sourceNameMetaData (
sourceName VARCHAR(64),
occurances INT
)
我建议用触发器或其他东西保持这个最新版本。然后,您可以通过最具限制性的条目过滤ActionTable,然后照常执行其余逻辑。
SELECT
yourTable.ActionName
FROM
(
SELECT
ActionName
FROM
(
SELECT
sourceName
FROM
sourceNameMetaData
INNER JOIN
tableWithSourceNames
ON tableWithSourceNames.SourceName = sourceNameMetaData.SourceName
ORDER BY
occurances ASC
LIMIT
1
)
AS filter
INNER JOIN
yourTable
ON yourTable.SourceName = filter.SourceName
GROUP BY
ActionName
)
AS filter
INNER JOIN
yourTable
ON yourTable.ActionName = filteredData.ActionName
INNER JOIN
tableWithSourceNames
ON yourTable.SourceName = tableWithSourceNames.SourceName
GROUP BY
yourTable.ActionName
HAVING
COUNT(DISTINCT yourTable.SourceName) = (SELECT COUNT(DISTINCT SourceName) FROM tableWithSourceNames)
注意:
答案 1 :(得分:3)
SELECT ActionName
FROM LogTable
WHERE SourceName IN ('S01', 'S02')
GROUP BY ActionName
HAVING COUNT(DISTINCT SourceName) = 2
或:
SELECT ActionName
FROM
( SELECT DISTINCT ActionName
FROM LogTable
) AS dn
WHERE
EXISTS
( SELECT *
FROM LogTable AS a
WHERE a.ActionName = dn.ActionName
AND a.SourceName = 'S01'
)
AND
EXISTS
( SELECT *
FROM LogTable AS b
WHERE b.ActionName = dn.ActionName
AND b.SourceName = 'S02'
)
答案 2 :(得分:0)
也许我没有得到你的问题,但如果结果中你想要的只是你所展示的内容,你就不需要做任何事情或任何事情。
select distinct ActionName from YourTable
where SourceName in ('S01', 'S02')