use count in sql - sql

I need a SQL statement, the requirement is: there is a table, which has two columns: ID, Owner_ID; I inserted several records, for example:
ID Owner_ID
0 0
1 0
2 1
3 1
4 2
5 3
6 3
7 3
8 3
9 0
Now I need a SQL statement, which returns a ID list sorted by the number of rows owned by different user, from largest to smallest. In this example, owner 3 has four rows; owner 0 has three rows, owner 1 has two rows; and owner 2 has one rows. the result should be
ID Owner_ID
5 3
6 3
7 3
8 3
0 0
1 0
9 0
2 1
3 1
4 2
I think I should use the aggregate function count, does anybody have an idea?
I am using HSQLDB.
Thanks in advance!!

This will work with most SQL DBMS, but shows the count value.
SELECT ID, Owner_ID, Owner_Count
FROM AnonymousTable AS A
JOIN (SELECT Owner_ID, COUNT(*) AS Owner_Count
FROM AnonymousTable
GROUP BY Owner_ID
) AS B ON B.Owner_ID = A.Owner_ID
ORDER BY Owner_Count DESC, Owner_ID ASC, ID ASC;
This will work with some, but not necessarily all, DBMS; it orders by a column that is not shown in the result list:
SELECT ID, Owner_ID
FROM AnonymousTable AS A
JOIN (SELECT Owner_ID, COUNT(*) AS Owner_Count
FROM AnonymousTable
GROUP BY Owner_ID
) AS B ON B.Owner_ID = A.Owner_ID
ORDER BY Owner_Count DESC, Owner_ID ASC, ID ASC;

This is very straight-forward.
SELECT
ID,
Owner_ID
FROM
TheTable t
ORDER BY
(SELECT COUNT(*) FROM TheTable i WHERE i.Owner_ID = t.Owner_ID) DESC

Yes, you have the general idea. Try the following query:
select t.ID, t.Owner_ID
from table t
inner join (select Owner_ID, count(*) c from table t group by Owner_ID) tc
on t.Owner_ID = tc.Owner_ID
order by
tc.c desc, t.ID asc

Related

How to select varying count of items per colum value?

I work with Postgresql.
I have a sql code
SELECT lp."RegionId", COUNT(w."Id") FROM public.workplace w
GROUP BY lp."RegionId"
that returns to me
RegionId | Count
1 | 3
2 | 12
3 | 5
I have table 'person'. Each person have RegionId.
So i for region 1 i want to select first 3 persons, for region 2 select first 12 persons, for region 3 select first 5 persons.
So how can i use it as subquery to table 'person'?
WITH (SELECT lp."RegionId", COUNT(w."Id") FROM public.workplace w
GROUP BY lp."RegionId") AS pc
SELECT * FROM public.person p
???????
limit pc."Count"
???
Something like:
SELECT p.*
FROM (SELECT *, row_number() OVER (PARTITION BY RegionId ORDER BY PersonId) AS rn
FROM person) AS p
JOIN (SELECT RegionId, count(*) AS cnt
FROM workplace
GROUP BY RegionId) AS r ON p.RegionId = r.RegionId
WHERE p.rn <= r.cnt
ORDER BY p.RegionId, p.PersonId;

SQL: Searching for the correct record group

Lets say that we have a Groupings table that has 2 columns: Group_ID and Item_ID. Both are ints. For a simplified example lets imagine that the Item_ID can be one of only 3 values: {1,2,3}. The Group_IDs then represent the different groups of permutations of this data. So for example:
Group_ID Item_ID
1 1
2 2
3 3
4 1
4 2
5 1
5 3
6 2
6 3
7 1
7 2
7 3
What SQL could I write that if I inputted a collection of Item_Ids it would return the Group_ID related to that collection?
So for example in the above with an input of (2,3) => 6
Edit: I want to use the solution query on a more complex table, where there are 16 different values for the Item_ID
use conditional aggregation
select group_id
from table t1
where Item_ID in(2,3)
and exists( select 1 from table t2 where t1.group_id=t2.group_id
having count(distinct t2.Item_ID)=2 )
group by group_id
having count(distinct item_id)=2
Another Sql to do this
SELECT Group_id
FROM YourTable
GROUP BY Group_id
HAVING COUNT(Item_ID) = 2
AND COUNT(CASE WHEN Item_ID = 2 THEN Item_ID END) > 0
AND COUNT(CASE WHEN Item_ID = 3 THEN Item_ID END) > 0
Assuming you have no duplicates, I would simply do:
select group_id
from t
group by group_id
having sum(case when Item_ID in (2, 3) then 1 else 0 end) = count(*) and
count(*) = 2;
This seems like the simplest approach.

SQL select top if columns are same

If I have a table like this:
Id StateId Name
1 1 a
2 2 b
3 1 c
4 1 d
5 3 e
6 2 f
I want to select like below:
Id StateId Name
4 1 d
5 3 e
6 2 f
For example, Ids 1,3,4 have stateid 1. So select row with max Id, i.e, 4.
; WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY STATEID ORDER BY ID DESC) AS RN
)SELECT ID, STATEID, NAME FROM CTE WHERE RN = 1
You can use ROW_NUMBER() + TOP 1 WITH TIES:
SELECT TOP 1 WITH TIES
Id,
StateId,
[Name]
FROM YourTable
ORDER BY ROW_NUMBER() OVER (PARTITION BY StateId ORDER BY Id DESC)
Output:
Id StateId Name
4 1 d
6 2 f
5 3 e
Disclaimer: I gave this answer before the OP had specified an actual database, and hence avoided using window functions. For a possibly more appropriate answer, see the reply by #Tanjim above.
Here is an option using joins which should work across most RDBMS.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT StateId, MAX(Id) AS Id
FROM yourTable
GROUP BY StateId
) t2
ON t1.StateId = t2.StateId AND
t1.Id = t2.Id
The following using a subquery, to find the maximum Id for each of the states. The WHERE clause then only includes rows with ids from that subquery.
SELECT
[Id], [StateID], [Name]
FROM
TABLENAME S1
WHERE
Id IN (SELECT MAX(Id) FROM TABLENAME S2 WHERE S2.StateID = S1.StateID)

Select row minimum col for each id

I have a table like following
id id_a id_b uds
--------------------------
1 1 3 20
1 2 8 17
2 1 3 5
3 1 1 32
3 2 1 6
What I would need is to get the row with minimum "uds" for each "id". So the result would be:
id id_a id_b uds
--------------------------
1 2 8 17
2 1 3 5
3 2 1 6
Thank you in advance...
Use Min with a group by clause:
select id, id_a, id_b, min(uds) as uds
from table1
group by id, id_a, id_b
order by id, id_a, id_b;
However, I should mention this is going to get you all of the items, you need to also specify an aggregate on the other columns, or do not include them.
select id, min(uds) as uds
from table1
group by id
order by id;
Judging by your desired output though, the following may be what you want:
select id, max(id_a) as id_a, max(id_b) as id_b, min(uds) as uds
from table1
group by id
order by id;
Most databases support the ANSI standard window functions. An easy way to do what you want:
select t.*
from (select t.*, row_number() over (partition by id order by uds) as seqnum
from t
) t
where seqnum = 1;
you have to set condition with minimum uds value or you have to decides how many numbers of records you want with minimum uds
More one way:
select
a.*
from
#temp a inner join (select id, min(uds) minUds from #temp group by id) b on
a.id = b.id
and a.uds = b.minUds

How to GROUP BY in SQL and then mark as 0,1

I need to GROUP BY item_id and check if user_id in any of those matches a variable. If so, I want it to = 1, if not 0.
for example, imagine table like this:
item_id, user_id
1 1
1 3
2 4
2 1
2 7
2 3
3 4
3 6
4 8
4 1
5 3
IF (user_id = 3,1,0) AS match,
Want my Query to come back as
item_id, match
1 1
2 1
3 0
4 0
5 1
Where "1" all occurrences of user_id 3 in an item_id group.
You need the right aggregation function:
select item_id,
max(case when user_id = 3 then 1 else 0 end) as hasmatch
from t
group by item_id
order by item_id
In MySQL, true is 1 and false is 0, so you can just do:
SELECT item_id, MAX(user_id = 3) AS has_match
FROM table
GROUP BY 1
You can even count the number of matches:
SELECT item_id, SUM(user_id = 3) AS matches
FROM table
GROUP BY 1
GROUP BY 1 is short for GROUP BY item_id, as item_id is the first select expression.
I would do it as follows:
SELECT
A.item_id, ISNULL(B.count, 0)
FROM
(SELECT DISTINCT item_id 'item_id' FROM myTable) AS A
LEFT JOIN
(
SELECT item_id, count(*) 'count'
FROM myTable WHERE user_id IN (3, 1, 0)
GROUP BY item_id
) AS B
ON A.item_id = B.item_id