Полусложный набор результатов в SQL-запросе - PullRequest
0 голосов
/ 28 марта 2012

У меня есть user таблица, подобная этой

FIRSTNAME  |  LASTNAME  |  ID  |
--------------------------------
James      |  Hay       |  1   |
Other      |  Person    |  2   |

У меня также есть attendance таблица, подобная этой

EVENTID  |  USERID  |  ATTENDANCE  |  STATUS  |
-----------------------------------------------
1           1          True           3
2           1          False          1
3           1          False          3
1           2          False          1
2           2          True           3
3           2          True           3

Обычно, когда пользователя приглашают на событиев таблицу attendance добавляется строка с идентификатором события, идентификатором пользователя, ложным посещением и статусом 0.

Статус является просто индикатором их ответа

0 = No Response
1 = Said No
2 = Said Yes
3 = Said yes and seats confirmed

Мой конечный результат, который я хочу получить от запроса этих двух таблиц, довольно сложен, и я не могу понять, что мне нужно делать.

Я хочу получить такой результат, как этот

NAME          |  % of saying YES to an RSVP  | % of attending after saying yes
-------------------------------------------------------------------------------
James Hay     |             66               |                50
Other Person  |             66               |                100

Я уверен, что вы можете понять, как я получил эти цифры, но, чтобы объяснить, Джеймс Хей имел статус 3 (да), чтобыПриглашено 2/3 мероприятия.Таким образом,% от «да» - 66. Из 2, которые он сказал «да», он посещал только 1/2, поэтому% после того, как он сказал «да», составляет 50%

.так как я не могу разобраться с этим.

РЕДАКТИРОВАТЬ:

Также очень важно то, что я хочу, чтобы результаты включали каждого пользователя в базу данных, даже еслиу них 0 строк в таблице attendance.

Ответы [ 3 ]

2 голосов
/ 28 марта 2012
select
u.firstname, u.lastname
-- said yes, as percentage
,floor(100.0
    * count(case when a.status in (2,3) then 1 end)
    / count(u.id)) yes
-- attended after saying yes, as percentage
,floor(100.0
    * count(case when a.status in (2,3) and attendance='true' then 1 end)
    / nullif(count(case when a.status in (2,3) then 1 end),0)) attendance
--,count(u.id) rsvp -- total invites
from users u
left join attendance a on a.userid = u.id
group by u.firstname, u.lastname

Примечание: Для особого случая, когда пользователь никогда не получал приглашение, статистика отображается как 0% и NULL.

Объяснение терминов:

  • count(case when a.status in (2,3) then 1 end)
    • представляет, сколько раз они сказали «да», дважды использовали
  • count(u.id)
    • сколько приглашений (записано при посещении) получено. Особый случай - когда они не получили ни одного, и в этом случае LEFT JOIN делает его 1 (не важно)
  • count(case when a.status in (2,3) and attendance='true' then 1 end)
    • подсчитайте, сколько раз они посетили, ПОСЛЕ того как сказал да
1 голос
/ 28 марта 2012

Изменить:

Ой, забыл присоединиться к пользователям:)

select firstname, lastname,
  convert(decimal (5, 2), 1. * count(case when status in (2, 3) then 1 end) / count(*) * 100) SaidYes,
  convert(decimal (5, 2), 1. * count(case when status in (2, 3) and attendance = 'True' then 1 end) / count(case when status in (2, 3) then 1 end) * 100) ActuallyAttended
from attendance a
join users u on a.userid = u.id
group by firstname, lastname
1 голос
/ 28 марта 2012
SELECT A.NAME,B.PERCENTAGE_YES_RSVP,B.PERCENTAGE_AFTER_YES
FROM 
( 
  SELECT U.ID AS ID,U.FIRSTNAME+''+U.LASTNAME AS NAME
  FROM USERS U
) A,
(
  SELECT A.USERID,A.PERCENTAGE_YES_RSVP,B.PERCENTAGE_AFTER_YES
FROM   
  (
    SELECT B.USERID,ROUND((CAST(B.COUNT_YES_RSVP AS FLOAT)/B.TOTAL_COUNT)*100,0) AS PERCENTAGE_YES_RSVP    
    FROM  
    (SELECT A.USERID,
       SUM(CASE WHEN A.STATUS=3 THEN 1 END)AS COUNT_YES_RSVP,
       COUNT(*) AS TOTAL_COUNT
       FROM ATTENDANCE A  
       GROUP BY A.USERID
     ) B
  ) A,  
(
  SELECT C.USERID,(CAST(C.COUNT_AFTER_YES_RSVP AS FLOAT)/C.TOTAL_COUNT)*100 AS PERCENTAGE_AFTER_YES   
  FROM  
  (SELECT A.USERID,
       SUM(CASE WHEN A.STATUS=3 AND A.ATTENDANCE='TRUE' THEN 1 END)AS COUNT_AFTER_YES_RSVP,
       SUM(CASE WHEN A.STATUS=3 THEN 1 END) AS TOTAL_COUNT
   FROM ATTENDANCE A  
   GROUP BY A.USERID
   ) C
)B   
WHERE A.USERID=B.USERID
) B
WHERE A.ID = B.USERID;
...