我正在制作一份报告,该报告返回MEMBER表中加入日期范围的成员,关系(MEMBERS.relationship)列等于成员的'M',其成员类型是 THEN之一对于符合此条件的每个成员记录,我需要返回它们在CHKINS表中指定的时间段内的签到数。 CHKINS表中有一个条目用于每个签入,'缺血'字段需要设置为'真'才能成为有效签入。换句话说,John Doe在规定的时间内检查了10次。我需要返回一行指定的字段加上值“10”。我现在构建的内容为我提供了十行。
SELECT
EMPLOYEES.lname, EMPLOYEES.fname,
MEMBERS.fname AS Expr1, MEMBERS.scancode, MEMBERS.lname AS Expr2,
MEMBERTYPES.description,
MEMBERS.phone1, MEMBERS.phone2, MEMBERS.lastvisit, MEMBERS.email,
MEMBERS.datejoin, MEMBERS.dateexpire, MEMBERS.daterenewal,
CHKINS.checkin, SITES.sitename, MEMBERS.relationship, MEMBERS.mtypeid
FROM
MEMBERS
INNER JOIN
CHKINS ON MEMBERS.memid = CHKINS.memid
INNER JOIN
EMPLOYEES ON MEMBERS.employeeid = EMPLOYEES.employeeid
INNER JOIN
SITES ON MEMBERS.siteid = SITES.siteid
INNER JOIN
MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid
WHERE
(CHKINS.ischeckin = 'True')
AND (CHKINS.checkin BETWEEN @rvStartDate AND DATEADD(day, 45, @rvStartDate))
AND (MEMBERS.relationship = 'M')
AND (MEMBERS.status = 'A')
AND (MEMBERS.mtypeid = '1' OR MEMBERS.mtypeid = '10' OR
MEMBERS.mtypeid = '12' OR MEMBERS.mtypeid = '22' OR
MEMBERS.mtypeid = '28' OR MEMBERS.mtypeid = '32' OR
MEMBERS.mtypeid = '33' OR MEMBERS.mtypeid = '34' OR
MEMBERS.mtypeid = '35' OR MEMBERS.mtypeid = '36' OR
MEMBERS.mtypeid = '40' OR MEMBERS.mtypeid = '48')
AND (MEMBERS.datejoin BETWEEN @rvStartDate AND @rvEndDate)
答案 0 :(得分:1)
我不知道您的数据库架构的所有细节,但它似乎回答了您的问题,除非您希望报告中的其他列不需要某些联接。基本上,您希望使用带有计数的分组,它应该比您的子查询执行得快得多。在你的一条评论中看到你说你还在学习/相当新。我确实根据自己的口味改变了一些关于你的结构的事情。一个变化是我使用表缩写,例如。当你把表放在from区域时,只需添加一个空格,然后添加一个缩写(例如m代表成员)。另一个瘦是将mtypid的OR列表切换到一个基本上做同样事情的in语句。请注意,注释前面是 - 所以如果您在SSMS查询窗口中通过以下代码,您应该看到一些注释,我找到了使代码可读的有用提示。
使用group by并连接多个表时的技巧是了解一对一和一对一关系是什么。如果是一对多,例如在CHKINS表的情况下,这是你想要计算的,重要的是只使用一对一的其他表的成员表(例如membertypes)或使用count时确保你在计数中使用CHKINS的唯一id。鉴于您的问题没有询问在员工,膜类型或站点表中使用任何内容,您可以简单地删除它们,从而在成员和chckins之间留下直接的一对多关系。之后,对于您想要查看的关系一侧的所有列,包括组中的那些列。
SELECT
FirstName = m.fname --m.fname AS Expr1 can chane to ,FirtsName = m.fname or ,m.fname AS FisrtName if you don't want Expr1
,LastName = m.lname --m.lname AS Expr2 Again can replace Expr2 with something more meaninglfull if desired e.g. LastName (also is this exact same as e.lname ? do you want both?)
,m.description
,m.phone1
,m.phone2
,m.lastvisit
,m.email
,m.datejoin
,m.dateexpire
,m.daterenewal
,m.relationship
,m.mtypeid
,m.status
,CountOfCheckins = COUNT(*) --If you know the PrimaryKey for CHKINS you could aso do COUNT(DISNTINCT c.Id)
FROM
MEMBERS m
INNER JOIN CHKINS c
ON m.memid = c.memid
AND c.ischeckin = 'TRUE'
--AND c.checkin BETWEEN @rvStartDate AND DATEADD(day, 45, @rvStartDate) --only include if you want to also limit the checkins by the same date range
WHERE
m.relationship = 'M'
AND m.status = 'A' --if you want all statuses comment this line by adding -- in front
AND m.mtypeid IN ('1','10','12','22','28','32','33','34','35','36','40','48')
--AND m.mtypeid IN (1,10,12,22,28,32,33,34,35,36,40,48) --uncomment and use this line instead of above if m.mtypeid is a numeric data type (int, smallint, tinyint, etc.)
AND m.datejoin BETWEEN @rvStartDate AND @rvEndDate
GROUP BY
m.fname
,m.lname
,m.description
,m.phone1
,m.phone2
,m.lastvisit
,m.email
,m.datejoin
,m.dateexpire
,m.daterenewal
,m.relationship
,m.mtypeid
,m.status
ORDER BY
m.fname
,m.lastname
--this sorts list by First name then Last Name switch order if you want last first
--or you can simply put CountOfCheckins to order by the least to greatest checkins or CountOfCheckins to get the greatest to the least
答案 1 :(得分:0)
您可以通过在选择列表中添加一个子查询来从CHKINS表中获取有效签到的计数,该子查询选择与MEMBERS.memid匹配的记录数,其中缺席为True
SELECT EMPLOYEES.lname
,EMPLOYEES.fname
,MEMBERS.fname AS Expr1
,MEMBERS.scancode
,MEMBERS.lname AS Expr2
,MEMBERTYPES.[description]
,MEMBERS.phone1
,MEMBERS.phone2
,MEMBERS.lastvisit
,MEMBERS.email
,MEMBERS.datejoin
,MEMBERS.dateexpire
,MEMBERS.daterenewal
,MEMBERS.relationship
,MEMBERS.mtypeid
,CHKINS.checkin
,SITES.sitename
,(SELECT COUNT(*) FROM CHKINS WHERE CHKINS.memid = MEMBERS.memid AND CHKINS.ischeckin = 'True') AS CheckinCount
FROM MEMBERS
INNER JOIN CHKINS ON MEMBERS.memid = CHKINS.memid
INNER JOIN EMPLOYEES ON MEMBERS.employeeid = EMPLOYEES.employeeid
INNER JOIN SITES ON MEMBERS.siteid = SITES.siteid
INNER JOIN MEMBERTYPES ON MEMBERS.mtypeid = MEMBERTYPES.mtypeid
WHERE (CHKINS.ischeckin = 'True')
AND (CHKINS.checkin BETWEEN @rvStartDate AND DATEADD(day, 45, @rvStartDate))
AND (MEMBERS.relationship = 'M')
AND (MEMBERS.[status] = 'A')
AND (MEMBERS.mtypeid = '1' OR
MEMBERS.mtypeid = '10' OR
MEMBERS.mtypeid = '12' OR
MEMBERS.mtypeid = '22' OR
MEMBERS.mtypeid = '28' OR
MEMBERS.mtypeid = '32' OR
MEMBERS.mtypeid = '33' OR
MEMBERS.mtypeid = '34' OR
MEMBERS.mtypeid = '35' OR
MEMBERS.mtypeid = '36' OR
MEMBERS.mtypeid = '40' OR
MEMBERS.mtypeid = '48')
AND (MEMBERS.datejoin BETWEEN @rvStartDate AND @rvEndDate)