SQL Count number of column based on another column - sql

Simple question here but I don't have any data to test with so I'm not sure if it is right.
Let's say I have a table that looks something like this:
+---------+---------+
| ColumnA | ColumnB |
+---------+---------+
| 1 | a |
| 2 | a |
| 3 | a |
| 3 | b |
| 4 | a |
| 5 | a |
| 6 | a |
| 6 | b |
| 6 | c |
| 7 | a |
+---------+---------+
I want to count the number of distinct items in column b for each column a.
So the result table would look like this:
+---------+---------+
| ColumnA | Count |
+---------+---------+
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 1 |
| 5 | 1 |
| 6 | 3 |
| 7 | 1 |
+---------+---------+
How would I do this?
I've been trying something like this:
dense_rank() over (partition by ColumnA order by ColumnB) count

You can use GROUP BY and COUNT with DISTINCT:
SELECT ColumnA, COUNT(DISTINCT ColumnB) AS [Count]
FROM MyTable
GROUP BY ColumnA
demo on dbfiddle.uk

Related

SQL return only rows where value exists multiple times and other value is present

I have a table like this in MS SQL SERVER
+------+------+
| ID | Cust |
+------+------+
| 1 | A |
| 1 | A |
| 1 | B |
| 1 | B |
| 2 | A |
| 2 | A |
| 2 | A |
| 2 | B |
| 3 | A |
| 3 | B |
| 3 | B |
| 3 | C |
| 3 | C |
+------+------+
I don't know the values in column "Cust" and I want to return all rows where the value of "Cust" appears multiple times and where at least one of the "ID" values is "1".
Like this:
+------+------+
| ID | Cust |
+------+------+
| 1 | A |
| 1 | A |
| 1 | B |
| 1 | B |
| 2 | A |
| 2 | A |
| 2 | A |
| 2 | B |
| 3 | A |
| 3 | B |
| 3 | B |
+------+------+
Any ideas? I can't find it.
You may use COUNT window function as the following:
SELECT ID, Cust
FROM
(
SELECT ID, Cust,
COUNT(*) OVER (PARTITION BY Cust) cn,
COUNT(CASE WHEN ID=1 THEN 1 END) OVER (PARTITION BY Cust) cn2
FROM table_name
) T
WHERE cn>1 AND cn2>0
ORDER BY ID, Cust
COUNT(*) OVER (PARTITION BY Cust) to check if the value of "Cust" appears multiple times.
COUNT(CASE WHEN ID=1 THEN 1 END) OVER (PARTITION BY Cust) to check that at least one of the "ID" values is "1".
See a demo.

Postgresql: Group rows in a row and add array

Hi i have a table like this;
+----+----------+-------------+
| id | room_id | house_id |
+----+----------+-------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 1 | 2 |
| 5 | 2 | 2 |
| 6 | 3 | 2 |
| 7 | 1 | 3 |
| 8 | 2 | 3 |
| 9 | 3 | 3 |
+----+-------+----------------+
and i want to create a view like this
+----+----------+-------------+
| id | house_id | rooms |
+----+----------+-------------+
| 1 | 1 | [1,2,3] |
| 2 | 2 | [1,2,3] |
| 3 | 3 | [1,2,3] |
+----+-------+----------------+
i tried many ways but i cant gruop them in one line
Thanks for any help.
You can use array_agg():
select house_id, array_agg(room_id order by room_id) as rooms
from t
group by house_id;
If you want the first column to be incremental, you can use row_number():
select row_number() over (order by house_id) as id, . . .

Add Index to postgreSQL query result

My query result looks like this:
| A | B |
|-------|
| 1 | 2 |
| 1 | 4 |
| 1 | 6 |
| 1 | 9 |
| 1 | 1 |
| 1 | 6 |
| 1 | 9 |
Now I want to increase column A by the index of the result table, so the result would become like this:
| A | B |
|-------|
| 2 | 2 |
| 3 | 4 |
| 4 | 6 |
| 5 | 9 |
| 6 | 1 |
| 7 | 6 |
| 8 | 9 |
How can I do it?
Thanks!
You want row_number()
select (row_number() over (order by a) + 1) as A, b
from table t;
Maybe something like that:
SELECT
(row_number() OVER (ORDER BY A) + A) AS columnAIndex,
columnB
FROM ...
I don't have a PostgreSQL client installed here, therefore, i don't tested this query.

Limit a sorted number of rows joined

I have two tables, A and B, and a join table M. I want to, for each A.id, get the top 2 B.id's sorting on the value in table M, producing the results below. This is running on an Azure SQL database
Table A Table M Table B
+-----+ +-----+-----+-------+ +-----+
| Id | | AId | BId | Value | | Id |
+-----+ +-----+-----+-------+ +-----+
| 1 | | 1 | 3 | 4 | | 1 |
| 2 | | 1 | 2 | 3 | | 2 |
| 3 | | 3 | 2 | 3 | | 3 |
| 4 | | 3 | 5 | 6 | | 4 |
+-----+ | 3 | 3 | 4 | | 5 |
| 4 | 1 | 2 | +-----+
| 4 | 2 | 1 |
| 4 | 4 | 3 |
+-----+-----+-------+
Result
+-----+-----+-------+
| AId | BId | Value |
+-----+-----+-------+
| 1 | 3 | 4 |
| 1 | 2 | 3 |
| 3 | 5 | 6 |
| 3 | 3 | 4 |
| 4 | 1 | 2 |
| 4 | 4 | 3 |
+-----+-----+-------+
I know that I can select all the M.AId rows where they equal 1, sort it, and limit by 2, but I need to do this for every row in Table A. I've made an attempt to use group by, but I wasn't sure how to sort and limit it. I've also tried to search for resources associated with this issue but I couldn't find any resources.
(I also wasn't sure how to word the title for this issue)
You can just use ROW_NUMBER:
SELECT
AId, BId, Value
FROM (
SELECT *,
Rn = ROW_NUMBER() OVER(PARTITION BY AId ORDER BY Value DESC)
FROM M
) t
WHERE Rn <= 2

SQL - only display rows that have the max value

I have this table that is already sorted but I want it to only display the maximum values... so instead of this table:
+------+-------+
| id | value |
+------+-------+
| 1 | 3 |
| 5 | 3 |
| 4 | 3 |
| 9 | 2 |
| 8 | 2 |
| 3 | 2 |
| 2 | 1 |
| 6 | 1 |
| 7 | 1 |
+------+-------+
I want this:
+------+-------+
| id | value |
+------+-------+
| 1 | 3 |
| 5 | 3 |
| 4 | 3 |
+------+-------+
I'm using SQLite. thanks for any help.
You can do this using a subquery. Here is one way:
select t.*
from t
where t.value = (select max(value) from t);