How to partition based on two columns in Oracle/sql - sql

Please help me with the following
Question:
+------+----------+
| Name | Sub-name |
+------+----------+
| A | x |
| A | x |
| B | x |
| A | y |
| B | y |
+------+----------+
Desired Result:
+------+----------+-------+
| Name | Sub-name | Count |
+------+----------+-------+
| A | x | 2 |
| A | x | 2 |
| B | x | 1 |
| A | y | 1 |
| B | y | 1 |
+------+----------+-------+
Three columns Name, Subname, Count
I want to partition based on both name and subname.

SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE test ( Name, "Sub-name" ) AS
SELECT 'A', 'x' FROM DUAL
UNION ALL SELECT 'A', 'x' FROM DUAL
UNION ALL SELECT 'B', 'x' FROM DUAL
UNION ALL SELECT 'A', 'y' FROM DUAL
UNION ALL SELECT 'B', 'y' FROM DUAL;
Query 1:
SELECT Name,
"Sub-name",
COUNT( 1 ) OVER ( PARTITION BY "Sub-name", Name ) AS "Count"
FROM test
Results:
| NAME | Sub-name | Count |
|------|----------|-------|
| A | x | 2 |
| A | x | 2 |
| B | x | 1 |
| A | y | 1 |
| B | y | 1 |

Try this:
select name, sub_name, count(name) over (partition by name, sub_name) as count from table

select ra.Name,ra.sub-name,ta.count from table ra
inner join
(select Name,sub-name,count(*) from table
group by Name,sub-name)ta
on ra.Name=ta.Name
on ra.sub-name=ta.sub-name
order by sub-name desc
Really i don't understand why we need to use partition for this solution.Even the above join query works fine...hope it should....

Related

SQL Select random rows partitioned by a column

I have a dataset looks like this
| Country | id |
-------------------
| a | 5 |
| a | 1 |
| a | 2 |
| b | 1 |
| b | 5 |
| b | 4 |
| b | 7 |
| c | 5 |
| c | 1 |
| c | 2 |
and i need a query which returns 2 random values from where country in ('a', 'c'):
| Country | id |
------------------
| a | 2 | -- Two random rows from Country = 'a'
| a | 1 |
| c | 1 |
| c | 5 | --Two random rows from Country = 'c'
This should work:
select Country, id from
(select Country,
id,
row_number() over(partition by Country order by rand()) as rn
from table_name
) t
where Country in ('a', 'c') and rn <= 2
Replace rand() with random() if you're using Postgres or newid() in SQL Server.

How to select distinct records based on a given condition?

I have the following table in the MySQL database:
| id | col | val |
| -- | --- | --- |
| 1 | 1 | y |
| 2 | 1 | y |
| 3 | 1 | y |
| 4 | 1 | n |
| 5 | 2 | n |
| 6 | 3 | n |
| 7 | 3 | n |
| 8 | 4 | y |
| 9 | 5 | y |
| 10 | 5 | y |
Now I want to distinctly select the records where all the values of similar col are equal to y. I tried both the following queries:
SELECT DISTINCT `col` FROM `tbl` WHERE `val` = 'y'
SELECT `col` FROM `tbl` GROUP BY `col` HAVING (`val` = 'y')
But it's not working out as per my expectation. I want the result to look like this:
| col |
| --- |
| 4 |
| 5 |
But 1 is also being included in the results with my queries. Can anybody help me building the correct query? As far as I understand, I may need to create a derived table, but can't quite figure out the right path.
You are close, with the second query. Instead, compare the min and max values:
SELECT `col`
FROM `tbl`
GROUP BY `col`
HAVING MIN(val) = MAX(val) AND MIN(`val`) = 'y';
Check that 'y' is the minimum value:
HAVING MIN(val) = 'y'

Count NULL values by column in SQL

Suppose I have the following table:
table
| a | b | c |
|:-----|:----|:-----|
| 1 | a | NULL |
| NULL | b | NULL |
| 3 | c | NULL |
| 4 | d | 23 |
| NULL | e | 231 |
How can I count the number of NULL values by each column?
My final result would be:
| column_name | n_nulls |
|:---------------|:----------|
| a | 2 |
| b | 0 |
| c | 3 |
You can use union all:
select 'a', count(*) - count(a) as n_nulls from t
union all
select 'b', count(*) - count(b) as n_nulls from t
union all
select 'c', count(*) - count(c) as n_nulls from t;
Redshift is a column-store database, so there probably is not a more efficient method.

SQLite: average of column indexed by two columns

Given the following table
+----+----+------+
|id1 |id2 |value |
+----+----+------+
| 1 | 2 | 10 |
| 1 | 3 | 20 |
| 1 | 4 | 30 |
| 2 | 3 | 10 |
| 2 | 4 | 40 |
| 3 | 4 | 10 |
+----+----+------+
I want to have avg(value) of each id, whether located the id1 or id2 column.
Thus, the output should be:
1,20
2,20
3,16.66
4,26.6
Help would be greatly appreciated.
You could use UNION ALL:
WITH cte AS (
SELECT id, value FROM tab
UNION ALL
SELECT id2, value FROM tab
)
SELECT id, AVG(value) AS value
FROM cte
GROUP BY id;
DBFidde Demo

Oracle sql recursive

I have the following table:
+----+-----------+------+
| ID | Parent_ID | Name |
+----+-----------+------+
| 1 | null | A |
| 2 | null | B |
| 3 | null | C |
| 4 | 1 | D |
| 5 | 4 | E |
| 6 | 2 | F |
+----+-----------+------+
And I need to get table like this:
+----+------+
| ID | Name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | AD |
| 5 | ADE |
| 6 | BF |
+----+------+
I checked the ORACLE related questions here, but I did't find anything useful.
Try this.
SELECT ID, REPLACE (SYS_CONNECT_BY_PATH (NAME, ' '), ' ')
FROM TABLE1
START WITH PARENT_ID IS NULL
CONNECT BY PRIOR ID = PARENT_ID
ORDER BY ID;
SQL Fiddle
Try this
WITH b(ID, Parent_ID) AS (
-- Anchor member.
SELECT ID,
Parent_ID
FROM DataTable
WHERE Parent_ID IS NULL
UNION ALL
-- Recursive member.
SELECT a.ID,
a.Parent_ID
FROM DataTable a, b
WHERE a.Parent_ID = b.id
)
SELECT ID,
Parent_ID
FROM b;