Need to get difference between these two as output - sql

REQUIRED QUERY :
select all memberid from query 1 having higher count than query 2
the aim is to display all memberid who were leader/organiser/helper more times than they participate in event
how do i join these two select statement and view the required output
SELECT memberID, COUNT(*) AS cnt
FROM
(
SELECT memberID FROM leader UNION ALL
SELECT memberID FROM organiser UNION ALL
SELECT memberID FROM helper
) t
GROUP BY memberID;
=============
select memberid,count(*) as cnt2
from eventmember group by memberid;
=======

another, "all_in_one" solution
select
memberid,
count(*) as total_cnt,
sum(case when type = 'eventmember' then 1 else 0 end) as eventmember_cnt,
sum(case when type = 'eventmember' then 0 else 1 end) as other_cnt
from
( select memberid, 'leader' as type
from leader union all
select memberid, 'organiser' as type
from organiser union all
select memberid, 'helper' as type
from helper union all
select memberid, 'eventmember' as type
from eventmember
) t
group by
memberid
having
sum(case when type = 'eventmember' then 1 else 0 end)
< sum(case when type = 'eventmember' then 0 else 1 end)

try like below using cte
with cte as
(
SELECT memberID, COUNT(*) AS cnt
FROM
(
SELECT memberID FROM leader UNION ALL
SELECT memberID FROM organiser UNION ALL
SELECT memberID FROM helper
) t
GROUP BY memberID
),cte1 as
(
select memberid,count(*) as cnt2
from eventmember group by memberid
) select cte.memberID,cnt,cnt2 from cte join ct1 on cte.memberID=cte1.memberid

Related

How do I use SQL count with group by causing an error

Here is my code
SELECT
(SELECT count(*) WHERE status_id = #TO) as 'TO' ,
(SELECT count(*) WHERE status_id = #RO)as 'RO' ,
(SELECT count(*) WHERE status_id = #AO)as 'AO',
(SELECT count(*) WHERE status_id = #IO)as 'IP',
(SELECT count(*) WHERE status_id = #SO)as 'SO',
created_user
FROM
table1
GROUP BY
created_user
Now i'm getting the following error
Column 'status_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I don't want to group by status_id, how to fix this issue?
I guess you can try to use conditional aggregation
SELECT created_user,
SUM
(
CASE
WHEN status_id = #TO THEN 1 ELSE 0 END
)AS 'TO',
SUM
(
CASE
WHEN status_id = #RO THEN 1 ELSE 0 END
)AS 'RO'
FROM table1
GROUP BY created_user

In CTE query, count records in another table based on first table retrieved ID

I am working on CTE based query. I have never used this before. I am using the following query which is getting records from user_detail table.
with cte as ( select cust_ID, parentid, name, joinside,regdate,package,null lnode, null rnode from user_detail
where cust_ID = #nodeid
union all select t.cust_ID, t.parentid,t.name, t.joinside,t.regdate,t.package,
ISNULL(cte.lnode, CASE WHEN t.joinside = 0 THEN 1 ELSE 0 END) lnode,
ISNULL(cte.rnode, CASE WHEN t.joinside = 1 THEN 1 ELSE 0 END) rnode from user_detail
t inner join cte on cte.cust_ID = t.parentid )
select #nodeid nodeid,name,cust_ID,parentid,regdate,package from cte
where rnode='0' order by cust_id asc option (maxrecursion 0)
Above query is giving me 6 columns (nodeid,name,cust_ID,parentid,regdate,package).
Now what i actually want is, i want 7th column which will count rows based on cust_id from another table installments.
I am doing like below but when i add group by in the query it is giving me error..
declare #nodeid int = '1';
with cte as ( select cust_ID, parentid, name, joinside,regdate,package,null lnode, null rnode from user_detail
where cust_ID = #nodeid
union all select t.cust_ID, t.parentid,t.name, t.joinside,t.regdate,t.package,
ISNULL(cte.lnode, CASE WHEN t.joinside = 0 THEN 1 ELSE 0 END) lnode,
ISNULL(cte.rnode, CASE WHEN t.joinside = 1 THEN 1 ELSE 0 END) rnode from user_detail
t inner join cte on cte.cust_ID = t.parentid )
select #nodeid nodeid,name,ctttt.cust_ID,parentid,regdate,package,insttt.cust_id from cte as ctttt left join installments as insttt
on ctttt.cust_id = insttt.cust_id
where rnode='0' order by ctttt.cust_id asc option (maxrecursion 0)
Using sub query
(select count(*) from installments as insttt where ctttt.cust_id = insttt.cust_id ) cnt
Query:
declare #nodeid int = '1';
with cte as ( select cust_ID, parentid, name, joinside,regdate,package,null lnode, null rnode
from user_detail
where cust_ID = #nodeid
union all
select t.cust_ID, t.parentid,t.name, t.joinside,t.regdate,t.package,
ISNULL(cte.lnode, CASE WHEN t.joinside = 0 THEN 1 ELSE 0 END) lnode,
ISNULL(cte.rnode, CASE WHEN t.joinside = 1 THEN 1 ELSE 0 END) rnode
from user_detail t
inner join cte on cte.cust_ID = t.parentid )
select #nodeid nodeid,name,ctttt.cust_ID,parentid,regdate,package,insttt.cust_id ,
(select count(*) from installments as insttt where ctttt.cust_id = insttt.cust_id ) cnt
from cte as ctttt
where rnode='0'
order by ctttt.cust_id asc option (maxrecursion 0)

Find Top Most AND Lowest In a Table's Group Column

I have a table and there are 4 fields in it, ID, Price, QTY, Ratting and Optional [Position].
I have all the records Grouped By Columns [Qty,Ratting]
I have to define the position of groupwise and store that Position into Optional column.
For better understanding I have added an image with data in table:
On the basis of QTY in Each Rating I have to Mark Top3, Bottom3 and Rest of them as remaining.
I am not getting how to do it.
Can anybody suggest me how to do it?
So far what I've tried is:
Declare #RankTable TABLE
(
ID INT,
Price Decimal (10,2),
Qty INT,
Ratting INT
)
INSERT INTO #RankTable
SELECT 1,10,15,1
UNION ALL
SELECT 2,11,11,1
UNION ALL
SELECT 3,96,10,1
UNION ALL
SELECT 4,96,8,1
UNION ALL
SELECT 5,56,7,1
UNION ALL
SELECT 6,74,5,1
UNION ALL
SELECT 7,93,4,1
UNION ALL
SELECT 8,98,2,1
UNION ALL
SELECT 9,12,1,1
UNION ALL
SELECT 10,32,80,2
UNION ALL
SELECT 11,74,68,2
UNION ALL
SELECT 12,58,57,2
UNION ALL
SELECT 13,37,43,2
UNION ALL
SELECT 14,79,32,2
UNION ALL
SELECT 15,29,28,2
UNION ALL
SELECT 16,46,17,2
UNION ALL
SELECT 17,86,13,2
UNION ALL
SELECT 19,75,110,3
UNION ALL
SELECT 20,27,108,3
UNION ALL
SELECT 21,38,104,3
UNION ALL
SELECT 22,87,100,3
UNION ALL
SELECT 23,47,89,3
DECLARE #PositionGroup VARCHAR(1)
SELECT *,ISNULL(#PositionGroup,'') AS Position FROM #RankTable
You can try this:
SELECT ID
,Price
,Qty
,Ratting
,CASE WHEN RowID >= 1 AND RowID <= 3
THEN 0
ELSE CASE WHEN RowID > Total - 3 THEN 1 ELSE 2 END END AS Position
FROM (SELECT ID
,Price
,Qty
,Ratting
,COUNT(*) OVER(PARTITION BY Ratting) AS Total
,ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) AS RowID
,ISNULL(#PositionGroup,'') AS Position
FROM #RankTable) AS T
Use Window Function. Try this.
;WITH cte
AS (SELECT *,
Row_number()OVER(partition BY rating ORDER BY id) rn,
count(id)OVER(partition BY rating) mx
FROM #RankTable)
SELECT ID,
Price,
Qty,
Rating,
mx - rn,
CASE WHEN rn IN ( 1, 2, 3 ) THEN 0
WHEN mx - rn IN( 0, 1, 2 ) THEN 1
ELSE 2
END position
FROM cte
try this as well.
;WITH cte AS
(
SELECT MAX(Row) [Max],
MIN(Row) [Min],
LU.Ratting
FROM (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) Row
FROM #RankTable)LU
GROUP BY LU.Ratting
)
SELECT ID,
R.Price,
R.Qty,
cte.Ratting,
CASE WHEN (Row - Min) <= 2 THEN 0 WHEN (Max - Row) <= 2 THEN 1 ELSE 2 END Position
FROM cte
JOIN (
SELECT Ratting,
ID,
Price,
Qty,
ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) [Row]
FROM #RankTable
) R ON R.Ratting = cte.Ratting
Result:

Joining two different queries under one answer

I have two different queries that have produced the correct result, but I would like to have them produce the answer out in one table. How do I do that?
Here is my code:
SELECT count(distinct ID) as NoOfEmployees
FROM Table_Name
WHERE date<= '2012-05-31';
select count(subA.ID) as EmployeesChanged from (
SELECT A.ID
FROM Table_Name A
WHERE A.date < '2012-06-01'
GROUP BY 1
HAVING COUNT(A.Service_type) > 1 ) subA
Currently I have the following output:
Number of Employees
x
Employees Changed
x
How do I make it
Number of Employees | Employees Changed | (Number of employees - number changed)
x | x | x
I don't know what database do you use. But for some databases you can try:
select q1.Value, q2.Value, q1.Value - q2.Value from
(SELECT count(distinct ID) as Value FROM Table_Name
WHERE date<= '2012-05-31') q1,
(select count(subA.ID) as Value from
( SELECT A.ID FROM Table_Name A
WHERE A.date < '2012-06-01' GROUP BY 1
HAVING COUNT(A.Service_type) > 1 ) subA) q2
If date<= '2012-05-31' is the same as A.date < '2012-06-01' ?
SELECT COUNT(1) AS NoOfEmployees,
SUM(CASE WHEN STCount > 0 then 1 else 0 end) as HasChange,
SUM(CASE WHEN STCount = 0 then 1 else 0 end) as NoChange
FROM
(SELECT ID,
COUNT(A.Service_type) STCount
FROM Table_Name
WHERE date<= '2012-05-31'
GROUP BY ID) AS Data
You can use CROSS JOIN:
SELECT a.*, b.*, a.NoOfEmployees - b.EmployeesChanged
FROM
(
SELECT count(distinct ID) as NoOfEmployees
FROM Table_Name
WHERE date<= '2012-05-31'
) a
CROSS JOIN
(
SELECT count(subA.ID) as EmployeesChanged
FROM
(
SELECT A.ID
FROM Table_Name A
WHERE A.date < '2012-06-01'
GROUP BY 1
HAVING COUNT(A.Service_type) > 1
) subA
) b
Edit:
You might be able to greatly optimize your query by using conditional aggregation instead of executing two separate queries:
SELECT a.NoOfEmployees, a.EmployeesChanged, a.NoOfEmployees - a.EmployeesChanged
FROM
(
SELECT
COUNT(DISTINCT CASE WHEN date <= '2012-05-31' THEN ID END) as NoOfEmployees,
COUNT(DISTINCT CASE WHEN date < '2012-06-01' AND COUNT(Service_type) > 1 THEN ID END) AS EmployeesChanged
FROM Table_Name
GROUP BY ID
) a

SQL Select for multiple where clause

I am trying to create SQL Select that returns counts of a certain field based on a field.
So, here is what I am trying to do.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct id where type='A') as TotalA, -- this will be total when type='A'
count(distinct id where type='B') as TotalB -- This will be total when type = 'B'
from MyTable
Basically, TotalCount = TotalA + TotalB.
How can I achieve this in SQL Select Statement?
Thanks.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct case type when 'A' then id else NULL end) as TotalA,
count(distinct case type when 'B' then id else NULL end) as TotalB
from MyTable;
Of course TotalCount may or may not be TotalA + TotalB, depending on the actual data.
You can do it like that:
SELECT
count(distinct id) as TotalCount,
sum(CASE WHEN type = 'A' THEN 1 ELSE 0) as TotalA,
sum(CASE WHEN type = 'B' THEN 1 ELSE 0) as TotalB,
FROM
MyTable
Count per type:
SELECT
type,
count(DISTINCT id)
FROM
MyTable
GROUP BY
type
Why not simply UNION the separate queries.
Select 'all' as which, count(distinct id) as Total from mytable
union
select 'a' as which, count(distinct id) where type='A' as Total from mytable
union
select 'b' as which, count(distinct id) where type='B' as Total from mytable