SQL count number of users hava a value > 1 - sql
I need a select which brings two lines, one with the number of people with the " number of hits " > 0 and the other line with the number of people with the " number of hits " = 0
SELECT u.name as 'Usuário',u.full_name as 'Nome do Usuário',count(l.referer) as 'Número de Acessos'
FROM mmp_user u
LEFT JOIN MMP_MMPUBLISH_LOG l
on u.id=l.user_id
AND l.event_date between '2015-08-01' and '2015-08-08'
group by u.name,u.full_name
order by count(l.referer) desc
I have,
151 Users
9 accessed and
142 not accessed.
But i don't return this values in select, help me please.
Table mmp_user fields (ID,CREATED_BY,AVATAR_ID,CREATION_DATE,EMAIL,FULL_NAME,LAST_EDITED_BY,LAST_EDITION_DATE,NAME,OBSERVATION,USER_PASSWORD,PASSWORD_REMINDER,SIGNATURE,STATUS,ADMINISTRATOR,DESIGNER,SECURITY_OFFICE,PUBLISHER,BRANCH_ID,DEPARTMENT_ID,EXTENSION,PHONE,COMPANY_ID,POSITION,ADMISSION_DATE,PASSWORD_LAST_EDITION_DATE,DISMISSED_DATE,NEWSLETTER,EXPIRE_DATE,COMPANY,BRANCH,DEPARTMENT,AREA_ID,SITE,USER_NUMBER,PREFIX_HOME_PHONE,PREFIX_MOBILE_PHONE,ADDRESS,ADDRESS_COMPLEMENT,ADDRESS_TYPE,CITY,NEIGHBORHOOD,STATE,ZIP_CODE,BIRTHDATE,GENDER,HOME_PHONE,MOBILE_PHONE,CPF,MARIAGE_STATUS,NATIONALITY,RG,EDUCATION,URL_SITE,FIRST_NAME,LAST_NAME,ID_SAP,PASSWORD_GAFISA,NICKNAME,CODE_POSITION,CREATION_USER_ORIGIN,LEVEL_POSITION,BIRTH_DATE_VISIBILITY,HOME_PHONE_COUNTRY_PREFIX,HOME_PHONE_VISIBILITY,MOBILE_PHONE_COUNTRY_PREFIX,MOBILE_PHONE_VISIBILITY,AREA_PREFIX,COUNTRY_PREFIX,PHONE_OBSERVATION,RESPONSIBLE,RESOURCE_ID,AVATAR_RF_ID,RESOURCE_AVATAR_ID,AVATAR_URL_LUCENE,avatarurl,PASSWORD_EXCHANGE,USER_NAME_EXCHANGE,DOMAIN_EXCHANGE,I18N,LAST_IMPORT_FILE,HIERARCHY_POSITION,SECRET_NICKNAME,PROFILE_TYPE,NOT_VIEW_USER,CHANGE_POSITION_DATE,DISTINGUISHED_NAME,OU_USER,AUTH_TOKEN,AUTH_TOKEN_EXPIRATION)
TableMMP_MMPUBLISH_LOG fields (ID,MMPUBLISH_LOG_TYPE,EVENT_DATE,USER_ID,TRANSACTION_NAME,USER_IP,USER_LOGIN,USER_NAME,SESSION_ID,REFERER,PUBLISHING_OBJECT_ID,PUBLISHING_OBJECT_NAME,PHASE_ID,PHASE_NAME,PHASE_COMMENT,ACCESS_URL,HOME_PAGE_ID,HOMEPAGE_ID,phaseComment,phaseId,phaseName,PO_VERSION_NUMBER)
Thanks
You could wrap this query with another query and apply a case expression to the count:
SELECT access_code, COUNT(*)
FROM (SELECT u.name,
u.full_name,
CASE WHEN COUNT(l.referer) > 0 THEN 'access'
ELSE 'no access'
END as access_code
FROM mmp_user u
LEFT JOIN mmp_mmpupluish_log l ON
u.id=l.user_id AND
l.event_date BETWEEN '2015-08-01' AND '2015-08-08'
GROUP BY u.name, u.full_name) t
GROUP BY access_code
ORDER BY access_code ASC
SELECT u.name Usuário, u.full_name [Nome do Usuário],
count(l.referer) [Número de Acessos],
Sum(case when NumberOfHits = 0 then 1 else 0 end) ZeroHitsCount,
Sum(case when NumberOfHits > 0 then 1 else 0 end) HasSomeHitsCount
FROM mmp_user u
LEFT JOIN MMP_MMPUBLISH_LOG l
on u.id=l.user_id
AND l.event_date between '2015-08-01' and '2015-08-08'
group by u.name, u.full_name
order by count(l.referer) desc
Use a case statement:
SELECT (case when l.referer is null then 'Not Accessed'
else 'Accessed'
end) as which,
count(*) as 'Número de Acessos'
FROM mmp_user u LEFT JOIN
MMP_MMPUBLISH_LOG l
on u.id = l.user_id AND
l.event_date between '2015-08-01' and '2015-08-08'
group by (case when l.referer is null then 'Not Accessed'
else 'Accessed'
end)
order by count(l.referer) desc;
Actually, the above counts the number of accesses. One way to get the number of users is to use count(distinct u.id). Another way uses a subquery:
select AccessType, count(*)
from (select u.*,
(case when exists (select 1
from MMP_MMPUBLISH_LOG l
where u.id = l.user_id AND
l.event_date between '2015-08-01' and '2015-08-08'
)
then 'Accessed' else 'Not Accessed'
end) as AccessType
from mmp_user u
) u
group by AccessType;
Related
SQL query to conditionally select a field value
I have an SQL query that joins 3 tables to return me the required data. The query is as follows: SELECT (s.user_created, u.first_name, u.last_name, u.email, s.school_name, p.plan_name, substring( a.message, 11), u.phone1) FROM cb_school s inner join ugrp_user u on s.user_created = u.user_id inner join cb_plan p on s.current_plan = p.plan_id inner join audit a on u.user_id = a.user_id where s.type = 'sample' and a.module_short = 'sample-user' and s.created_time > current_timestamp - interval '10 day'; The query works fine if all the attributes are present. Now for few of my rows, the following value would be a.module_short = 'sample-user' missing. But since I have included it as an AND condition, those rows will not be returned. I am trying to return an empty string for that field if it is present, else the value as per my current query. Is there any way to achieve this.
Think you could possibly use a CASE WHEN statement, like this: SELECT CASE WHEN a.module_short = 'sample-user' THEN a.module_short ELSE '' END AS a.module_short FROM TableA
you can use COALESCE it returns the first not null. SELECT COALESCE(a.module_short,'') FROM TableA AS a
SELECT (s.user_created, u.first_name, u.last_name, u.email, s.school_name, p.plan_name, substring( a.message, 11), u.phone1) FROM cb_school s INNER JOIN ugrp_user u ON s.user_created = u.user_id INNER JOIN cb_plan p ON s.current_plan = p.plan_id INNER JOIN audit a ON u.user_id = a.user_id AND a.module_short = 'sample-user' WHERE s.type = 'sample' AND s.created_time > current_timestamp - interval '10 day';
You want to show all users that have at least one module_short. If the module_short contains 'sample-user' then it should show it, else it should show NULL as module_short. You only want 1 row per user, even if it has multiple module_shorts. You can use a CTE, ROW_NUMBER() and the CASE clause for this question. Example Question I have 3 tables. Users: Users with an ID Modules: Modules with an ID UserModules: The link between users and modules. You user can have multiple models. I need a query that returns me all users that have at least 1 module with 2 columns UserName and ModuleName. I only one 1 row for each user. The ModuleName should only display SQL if the user has that module. Else it should display no module. Example Tables: Users: id name 1 Manuel 2 John 3 Doe Modules: id module 1 StackOverflow 2 SQL 3 StackExchange 4 SomethingElse UserModules: id module_id user_id 1 1 2 2 1 3 4 2 2 5 2 3 6 3 1 7 3 3 8 4 1 9 4 3 Example Query: with CTE as ( select u.name as UserName , CASE WHEN m.module = 'SQL' THEN 'SQL' ELSE NULL END as ModuleName , ROW_NUMBER() OVER(PARTITION BY u.id ORDER BY (CASE WHEN m.module = 'SQL' THEN 'Ja' ELSE NULL END) DESC) as rn from UserModules as um inner join Users as u on um.user_id = u.id inner join Modules as m on um.module_id = m.id ) select UserName, ModuleName from CTE where rn = 1 Example Result: UserName ModuleName Manuel NULL John SQL Doe SQL Your query would look like this: with UsersWithRownumbersBasedOnModule_short as ( SELECT s.user_created, u.first_name, u.last_name, u.email, s.school_name, p.plan_name, substring( a.message, 11), u.phone1) CASE WHEN a.module_short = 'sample-user' THEN a.module_short ELSE NULL END AS ModuleShort ROW_NUMBER() OVER(PARTITION BY u.user_id ORDER BY ( CASE WHEN a.module_short = 'sample-user' THEN a.module_short ELSE NULL END) DESC) as rn FROM cb_school s inner join ugrp_user u on s.user_created = u.user_id inner join cb_plan p on s.current_plan = p.plan_id inner join audit a on u.user_id = a.user_id where s.type = 'sample' and s.created_time > current_timestamp - interval '10 day';) select * from UsersWithRownumbersBasedOnModule_short where rn = 1 PS: I removed a lose bracket after SELECT and your SUBSTRING() is missing 1 parameter, it needs 3.
Aggregate case when inside non aggregate query
I have a pretty massive query that in its simplest form looks like this: select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum from table1 r left join table2 u on r.user_id=u.user_id left join table3 pi on u.user_id=pi.user_id I need to add one more condition that gives me count of users with non null application date per rep (like: rep 1 has 3 users with filled application dates), and assign it into categories (since 3 users, rep is a certain status category). This looks something like this: case when sum(case when application_date is not null then 1 else 0 end) >=10 then 'status1' when sum(case when application_date is not null then 1 else 0 end) >=5 then 'status2' when sum(case when application_date is not null then 1 else 0 end) >=1 then 'status3' else 'no_status' end as category However, if I was to simply add it to the select statement, all reps will becomes of status1 because the sum() is done over all advisors with application dates filled: select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum, ( select case when sum(case when application_date is not null then 1 else 0 end) >=10 then 'status1' when sum(case when application_date is not null then 1 else 0 end) >=5 then 'status2' when sum(case when application_date is not null then 1 else 0 end) >=1 then 'status3' else 'no_status' end as category from table3 ) as category from table1 r left join table2 u on r.user_id=u.user_id left join table3 pi on u.user_id=pi.user_id Can you assist with having the addition to my query to be across reps and not overall? Much appreciated!
Based on your description, I think you need a window function: select r.rep_id, u.user_id, u.signup_date, pi.application_date, pi.management_date, aum, count(pi.application_date) over (partition by r.rep_id) as newcol from table1 r left join table2 u on r.user_id = u.user_id left join table3 pi on u.user_id = pi.user_id; You can use the count() in a case to get ranges, if that is what you prefer.
Return string when division result is zero
I have an SQL query like this: SELECT u.id, tu.score/(CASE tu.mo_count WHEN 0 THEN NULL ELSE tu.mo_count END) AS score_avg FROM tournament_userscore tu INNER JOIN users u ON u.id = tu.user_id WHERE tournament_id = 1 ORDER BY tu.score DESC When tu.mo_count is zero, Null has been replaced instead of zero. How can I set a string like 'EMPTY' for this line: tu.score/(CASE tu.mo_count WHEN 0 THEN NULL ELSE tu.mo_count END) AS score_avg I mean when division result is zero or empty, I want to return "anything" string.
You could use NULLIF and COALESCE if you don't want to use a CASE: SELECT u.id, COALESCE(tu.score/NULLIF(tu.mo_count, 0), 0) AS score_avg FROM tournament_userscore tu INNER JOIN users u ON u.id = tu.user_id WHERE tournament_id = 1 ORDER BY tu.score DESC;
Try moving the CASE-statement outside: SELECT u.id, CASE WHEN tu.mo_count = 0 THEN 'EMPTY' ELSE (tu.score/tu.mo_count)::text END as score_avg FROM tournament_userscore tu INNER JOIN users u ON u.id = tu.user_id WHERE tournament_id = 1 ORDER BY tu.score DESC
SQL join two simple query with count and groupby
hello i have 2 queries and i wanna join together but i don't know how... SELECT *, count(*) as invii FROM professionisti JOIN preventivi_invii ON professionisti.email=preventivi_invii.email GROUP BY professionisti.email HAVING invii> 300 SELECT *, count(*) as acquisti FROM professionisti JOIN contatti_acquistati ON professionisti.email=contatti_acquistati.email GROUP BY professionisti.email HAVING acquisti> 5 the problem for me is multiple count and the group by with same column. thank u
How about the below query. You would just change the WHERE clause to meet your needs. SQL Fiddle Example: SELECT * FROM ( SELECT p.email, CASE WHEN ISNULL(m1.invii) THEN 0 ELSE m1.invii END AS invii, CASE WHEN ISNULL(m2.acquisti) THEN 0 ELSE m2.acquisti END AS acquisti FROM professionisti p LEFT JOIN ( SELECT pp.email, COUNT(*) AS invii FROM preventivi_invii pp GROUP BY pp.email ) AS m1 ON p.email = m1.email LEFT JOIN ( SELECT c.email, COUNT(*) AS acquisti FROM contatti_acquistati c GROUP BY c.email ) AS m2 ON p.email = m2.email ) AS mm WHERE mm.invii = 0 OR mm.acquisti = 0; Or you could use: SELECT * FROM ( SELECT p.email, ( SELECT CASE WHEN ISNULL(COUNT(*)) THEN 0 ELSE COUNT(*) END FROM preventivi_invii pp WHERE pp.email = p.email ) AS invii, ( SELECT CASE WHEN ISNULL(COUNT(*)) THEN 0 ELSE COUNT(*) END FROM contatti_acquistati c WHERE c.email = p.email ) AS acquisti FROM professionisti p ) AS mm WHERE mm.invii = 0 OR mm.acquisti = 0
HAVING clause on SUM column
I want to have a condition on my score column that I get from sum, but HAVING score =< 1 is not working if I put it after group by. That would have to show me projects that have good score. I am using hsqldb, what's going wrong? I get 'user lacks privelege or object not found: SCORE' SELECT p.id, p.project_name, SUM(CASE r.type_code WHEN 'GOOD' THEN 1 WHEN 'VERY_GOOD' THEN 1 WHEN 'BAD' THEN -1 WHEN 'VERY_BAD' THEN -1 ELSE 0 END) AS score FROM record_project AS rp JOIN project AS p ON p.id = rp.project_id JOIN record AS r ON r.id = rp.record_id GROUP BY p.id, p.project_name HAVING score =< 1 <<<---- wrong?! ORDER BY score DESC LIMIT 1
You should be using the whole calculated column, SELECT p.id, p.project_name, SUM(CASE WHEN r.type_code IN ('GOOD','VERY_GOOD') THEN 1 WHEN r.type_code IN ('BAD','VERY_BAD') THEN -1 ELSE 0 END) score FROM record_project AS rp JOIN project AS p ON p.id = rp.project_id JOIN record AS r ON r.id = rp.record_id GROUP BY p.id, p.project_name HAVING SUM(CASE WHEN r.type_code IN ('GOOD','VERY_GOOD') THEN 1 WHEN r.type_code IN ('BAD','VERY_BAD') THEN -1 ELSE 0 END) <= 1 ORDER BY score DESC -- LIMIT 1
You can incorporate the HAVING as a WHERE over a subquery: SELECT * FROM ( SELECT p.id, p.project_name, SUM(CASE r.type_code WHEN 'GOOD' THEN 1 WHEN 'VERY_GOOD' THEN 1 WHEN 'BAD' THEN -1 WHEN 'VERY_BAD' THEN -1 ELSE 0 END) AS score FROM record_project AS rp JOIN project AS p ON p.id = rp.project_id JOIN record AS r ON r.id = rp.record_id GROUP BY p.id, p.project_name) x WHERE score =< 1 ORDER BY score DESC LIMIT 1