Counting the amount of object with the same value in another column - sql

I want to count the amount of an occurrance the reattacht that the row back and couldn't find any good way to do it.
So 1 table would look like
id | value
1. a
2. a
3. b
4. a
5. b
6. b
7. c
8. c
9. a
which I would like to result in:
id | value | count
1. a, 4
2. a, 4
3. b, 3
4. a, 4
5. b, 3
6. b, 3
7. c, 2
8. c, 2
9. a, 4
I can only find answers with group by so any help is appreciated. This should also be matched to another table so if the result is joinable that would be helpful as well.

If your RDBMS support window functions, no need to join: you can just do a window count:
select t.*, count(*) over(partition by value) cnt from mytable t

select t.id, t.value, tmp.cnt
from your_table t
join
(
select value, count(*) as cnt
from your_table
group by value
) tmp on tmp.value = t.value

Related

Snowflake: Repeating rows based on column value

How to repeat rows based on column value in snowflake using sql.
I tried a few methods but not working such as dual and connect by.
I have two columns: Id and Quantity.
For each ID, there are different values of Quantity.
So if you have a count, you can use a generator:
with ten_rows as (
select row_number() over (order by null) as rn
from table(generator(ROWCOUNT=>10))
), data(id, count) as (
select * from values
(1,2),
(2,4)
)
SELECT
d.*
,r.rn
from data as d
join ten_rows as r
on d.count >= r.rn
order by 1,3;
ID
COUNT
RN
1
2
1
1
2
2
2
4
1
2
4
2
2
4
3
2
4
4
Ok let's start by generating some data. We will create 10 rows, with a QTY. The QTY will be randomly chosen as 1 or 2.
Next we want to duplicate the rows with a QTY of 2 and leave the QTY =1 as they are.
Obviously you can change all parameters above to suit your needs - this solution works super fast and in my opinion way better than table generation.
Simply stack SPLIT_TO_TABLE(), REPEAT() with a LATERAL() join and voila.
WITH TEN_ROWS AS (SELECT ROW_NUMBER()OVER(ORDER BY NULL)SOME_ID,UNIFORM(1,2,RANDOM())QTY FROM TABLE(GENERATOR(ROWCOUNT=>10)))
SELECT
TEN_ROWS.*
FROM
TEN_ROWS,LATERAL SPLIT_TO_TABLE(REPEAT('hire me $10/hour',QTY-1),'hire me $10/hour')ALTERNATIVE_APPROACH;

Is there a way to display the first two results of each unique id?

I work in healthcare. In a Postgres database, we have a table member IDs and dates. I'm trying to pull the latest two dates for each member ID.
Simplified sample data:
A 1
B 1
B 2
C 1
C 5
C 7
D 1
D 2
D 3
D 4
Desired result:
A 1
B 1
B 2
C 1
C 5
D 1
D 2
I get a strong feeling this is for a homework assignment and would recommend that you look into partitioning and specifically rank() function by yourself first before looking at my solution.
Moreover, you have not specified how you received the initial result you provided, so I'll have to assume you just did select letter_column, number_column from my_table; to achieve the result.
So, what you actually want here is partition the initial query result into groups by the letter_column and select the first two rows in each. rank() function lets you assign each row a number, counting within groups:
select letter_column,
number_column,
rank() over (partition by letter_column order by number_column) as rank
from my_table;
Since it's a function, you can't use it in a predicate in the same query, so you'll have to build another query around this one, this time filtering the results where rank is over 2:
with ranked_results as (select letter_column,
number_column,
rank() over (partition by letter_column order by number_column asc) as rank
from my_table mt)
select letter_column,
number_column
from ranked_results
where rank < 3;
Here's an SQLFiddle to play around: http://sqlfiddle.com/#!15/e90744/1/0
Hope this helps!

SQL Query get common column with diff values in other columns

I am not very fluent with SQL.. Im just facing a little issue in making the best and efficient sql query. I have a table with a composite key of column A and B as shown below
A
B
C
1
1
4
1
2
5
1
3
3
2
2
4
2
1
5
3
1
4
So what I need is to find rows where column C has both values of 4 and 5 (4 and 5 are just examples) for a particular value of column A. So 4 and 5 are present for two A values (1 and 2). For A value 3, 4 is present but 5 is not, hence we cannot take it.
My explanation is so confusing. I hope you get it.
After this, I need to find only those where B value for 4 (First Number) is less than B value for 5 (Second Number). In this case, for A=1, Row 1 (A-1, B-1,C-4) has B value lesser than Row 2 (A-1, B-2, C-5) So we take this row. For A = 2, Row 1(A-2,B-2,C-4) has B value greater than Row 2 (A-2,B-1,C-5) hence we cannot take it.
I Hope someone gets it and helps. Thanks.
Rows containing both c=4 and c=5 for a given a and ordered by b and by c the same way.
select a, b, c
from (
select tbl.*,
count(*) over(partition by a) cnt,
row_number() over (partition by a order by b) brn,
row_number() over (partition by a order by c) crn
from tbl
where c in (4, 5)
) t
where cnt = 2 and brn = crn;
EDIT
If an order if parameters matters, the position of the parameter must be set explicitly. Comparing b ordering to explicit parameter position
with params(val, pos) as (
select 4,2 union all
select 5,1
)
select a, b, c
from (
select tbl.*,
count(*) over(partition by a) cnt,
row_number() over (partition by a order by b) brn,
p.pos
from tbl
join params p on tbl.c = p.val
) t
where cnt = (select count(*) from params) and brn = pos;
I assume you want the values of a where this is true. If so, you can use aggregation:
select a
from t
where c in (4, 5)
group by a
having count(distinct c) = 2;

Oracle: how to select rows that are not duplicated

I have to eliminate the ones with an X in value and repeated. If they don't have an X, they stay, if they have an X but are not repeated they stay. Can you please help?
Table
Id Value
1. A.
2. X.
3. X.
3. C.
3. D.
4. X.
4. F
5. G
6. Z
7. X
8. X
8. G
Result from query should be:
1. A
2. X
5. G
6. Z
7. X
Maybe that helps:
SELECT Id,
Value
FROM(SELECT Id,
Value,
COUNT(*) OVER (PARTITION BY Id) cnt,
SUM(DECODE(Value, 'X', 1, 0)) OVER (PARTITION BY Id) sumx
FROM your_table
)
WHERE cnt = 1 OR sumx = 0;
Isn't that sufficient?
SELECT "Id", MIN("Value") "Value" FROM T
GROUP BY "Id" HAVING COUNT("Id") = 1
ORDER BY "Id"
It will discard multiple only-non-X values for a given id too. At the very least, according to your sample data, it seems to produce the desired result:
ID VALUE
1 A
2 X
5 G
6 Z
7 X
See http://sqlfiddle.com/#!4/81baa/10

update incremental values into an SQL column

I'm looking for some help with the following query:
I have a bunch of rows with column TYPE, VERSION - however in some cases the version got messed up so I want to rewrite it.
Basically, it now looks this:
Type, Version
A, 0
A, 0
A, 1
A, 2
B, 1
B, 3
I want it to look like this:
Type, Version
A, 0
A, 1
A, 2
A, 3
B, 0
B, 1
Any help would be greatly appreciated,
Thanks
WITH T AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Type ORDER BY Version) - 1 AS V
FROM YourTable
)
UPDATE T
SET Version = V