如何编写一个 SQL 查询,让我知道某个值在 table 中重复的次数?

How do I write an SQL query that gives me the amount of times a value is repeated in a table?

所以我创建了两个 table:

 CREATE TABLE IF NOT EXISTS `Advertising_Campaign` (
 `CampaignID` VARCHAR(10) NOT NULL,
 `AdvertName` varchar(45) NOT NULL,
 `ProjectLead` VARCHAR(10) NULL,
 `CostEstimate` decimal NULL,
 `CampaignCost` decimal NULL,
 `EndDateEst` date NULL,
 `StartDate` date NULL,
 `EndDate` date NULL,
 `Theme` VARCHAR(45) NOT NULL,
 `AdvertType` VARCHAR(45) NOT NULL,
  PRIMARY KEY (`CampaignID`))
  ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `staff_works_campaign` (
`CampaignID` VARCHAR(10) NOT NULL,
`StaffID` VARCHAR(10) NOT NULL,
`SalaryGrade` Integer NOT NULL,
`isSup` VARCHAR(3) NOT NULL,
PRIMARY KEY (`StaffID`, `CampaignID`), 
CONSTRAINT `FK_StaffID3` FOREIGN KEY (`StaffID`) REFERENCES `Staff` (`StaffID`),
CONSTRAINT `FK_CampaignID2` FOREIGN KEY (`CampaignID`) REFERENCES `Advertising_Campaign` (`CampaignID`))
ENGINE = InnoDB;

这给出了 tables:

基本上,我想编写一个查询,该查询将 return 向我提供 advertising_campaign.AdvertName 的列表,其中有 2 名以上的工作人员在处理这些工作,并计算 advertising_campaign.AdvertName 工作人员的数量 staff_works_campaign.SalaryGrade 大于 2。

我试过:

select a.advertname, count(*) as 'Greater Than 2'
from advertising_campaign a inner join staff_works_campaign
where staff_works_campaign.SalaryGrade > 2;

这不是我想要的,它 returns:

我有点不确定这是什么 returning 正是因为我认为它会 returned 计数为 2(因为事实上有 2 个条目带有table) 中的 SalaryGrade 为 4,可能是因为内部联接的工作方式?

我也有点困惑如何过滤'more than 2 staff members',我的想法是查看staff_works_campaign.CampaignID在staff_works_campaign[=49]中出现的次数=] 查看同一活动中有多少员工。

我不确定如何构建它来计算 campaignID 重复的次数以及 return 具有 2 名或更多工作人员处理的 campaignID 的广告的名称。

所以在这种情况下,我希望它 return 一个 table 的 AdvertName 仅包含那些有两个或更多人参与的广告系列以及有薪水的员工人数等级大于 2.

如果你想同时满足这两个条件,你可以做类似下面的事情, 2 人在营地工作,salary_grade >2

SELECT AdvertName 
FROM Advertising_Campaign 
WHERE CampaignID IN 
 ( 
   SELECT 
     CampaignID 
   FROM 
     staff_works_campaign 
   WHERE 
     SalaryGrade > 2 
   GROUP BY 
     CampaignID 
   HAVING 
   COUNT(DISTINCT StaffID) >= 2
)

首先你需要一个条件来连接两个表。其次,您可以使用 Group ByHaving 子句将过滤器放在聚合上。最后,您需要计算工资等级 > 2 的员工数量,您可以 SUM 作为条件。像这样:

select a.advertname, Sum(CASE WHEN c.SalaryGrade > 2 THEN 1 ELSE 0 END) as 'Greater Than 2'
from advertising_campaign a inner join staff_works_campaign c
    on a.CampaignId = c.CampaignId
Group By a.advertname Having count(*) >= 2;
SELECT 
    a.CampaignID
    ,a.AdvertName
    ,COUNT(DISTINCT s.StaffID) AS [Count of staff]
    ,SUM(
        --Use this to get a total of the staff who are 
        --in a SalaryGrade greater than 2
        CASE WHEN s.SalaryGrade > 2
            THEN 1
            ELSE 0 --anyone who is under this level will be a 0 and not count
        END
    ) as [Count of staff above salary grade]
FROM 
    advertising_campaign AS a 
    INNER JOIN staff_works_campaign AS s
        --dont forget the join condition
        ON a.CampaignID = s.CampaignID
--Dont want a where here, we want to include ALL staff.
--WHERE 
--  staff_works_campaign.SalaryGrade > 2
GROUP BY
    a.CampaignID
    ,a.AdvertName
HAVING
    --more than two members of staff working on the same campaign.
    COUNT(DISTINCT s.StaffID) > 2

您收到的查询结果是所有 薪资等级大于 2 的所有营销活动中的员工人数。它 returns "Star Wars 3" 作为广告名称只是因为它是它在 COUNT 操作的所有结果中遇到的第一个名字。 (其他一些 SQL 技术,例如 Microsoft SQL Server 实际上不允许您执行此类查询以避免这种混淆。)

为了让结果按活动拆分,您必须按照其他答案中的建议使用 GROUP BY 子句。这将告诉 SQL 计算所有匹配一个或多个字段的记录组的任何聚合函数(即 COUNT)。在您的情况下,您希望按活动 ID 进行分组,因为您希望为每个活动单独计算 COUNT。您也可以在广告名称上执行此操作,但最好在 ID 上执行此操作,以防您有两个名称相同。修改您的查询以执行此操作,我们得到:

select a.campaignID, count(*) as 'Greater Than 2'
from advertising_campaign a inner join staff_works_campaign
where staff_works_campaign.SalaryGrade > 2
group by a.campaignID;

虽然这仍然不太可行,因为工资等级条件在 COUNT 之前应用。我们需要将该部分移出到围绕该部分的新查询中。我们还需要将活动限制为只有两名员工的活动 - 谢天谢地,我们不需要为此再进行一次外部查询。 HAVING 关键字允许在 GROUP BY 之后应用条件,因此我们可以这样做:

select a.campaignID, count(*) as 'staff_amount'
from advertising_campaign a inner join staff_works_campaign
group by a.campaignID
having staff_amount > 2;

现在,在外部查询中添加员工工资条件和另一个 advertising_campaign 中的 select 以获取广告名称,我们最终得到:

select advertising_campaign.advertname
from advertising_campaign
inner join staff_works_campaign on advertising_campaign.campaignid = staff_works_campaign.campaignid
inner join
(
    select a.campaignID, count(*) as 'staff_amount'
    from advertising_campaign a inner join staff_works_campaign
    group by a.campaignID
    having staff_amount > 2
) large_campaigns on advertising_campaign.campaignid = large_campaigns.campaignid
where staff_works_campaign.salarygrade > 2