sql query to find what is not in group three - sql

i have one SQL Table in which some dummy data.
i want that dummy data and update that row with column type
my table tbl
ID D1 M1 C1 QTY TYPE
1 D1 M1 C1 1 Y
2 D1 M2 C1 2 Y
3 D1 M3 C1 3 Y
4 D1 M1 C1 1 Y
5 D2 M1 C1 1 Y
6 D2 M2 C1 2 Y
7 D2 M3 C2 3 Y
8 D2 M1 C1 1 Y
9 D2 M2 C1 2 Y
10 D3 M1 C1 1 Y
11 D3 M2 C1 2 Y
12 D3 M3 C1 3 Y
13 D3 M1 C1 1 Y
14 D3 M2 C1 2 Y
15 D3 M3 C1 3 Y
16 D3 M1 C2 1 Y
grouping on Column D1 and M1
I have a N no. of records, now I have to identify group of 3 record and if any record remain then it should be set as "No" else "yes"
Ex:
condition 1: If I have 4 records, then make a group of 3-3 records so remain last 1 record should be set an "no".
condition 2: If I have 5 records, then make a group of 3-3 records so remain last 2 records will be set as "No"
Condition 3: if I have 7 records, then make a group of 3-3 records so remain last 1 record will be set as "No"
my expected answer is as below
ID D1 M1 C1 QTY TYPE
1 D1 M1 C1 1 YES
2 D1 M2 C1 2 YES
3 D1 M3 C1 3 YES
4 D1 M1 C1 1 NO
5 D2 M1 C1 1 YES
6 D2 M2 C1 2 YES
7 D2 M3 C2 3 YES
8 D2 M1 C1 1 NO
9 D2 M2 C1 2 NO
10 D3 M1 C1 1 YES
11 D3 M2 C1 2 YES
12 D3 M3 C1 3 YES
13 D3 M1 C1 1 YES
14 D3 M2 C1 2 YES
15 D3 M3 C1 3 YES
16 D3 M1 C2 1 NO
SQLFIDDLE
Please tell me solution.

Is this what you are looking for?
with toupdate as (
select t.*, row_number() over (partition by d1 order by id) as seqnum,
count(*) over (partition by d1) as cnt
from tbl t
)
update toupdate
set type = (case when seqnum <= 3*(cnt /3) then 'yes' else 'no' end);
You can also run similar logic as a select:
select t.*, (case when seqnum <= 3*(cnt /3) then 'yes' else 'no' end)
from (
select t.*, row_number() over (partition by d1 order by id) as seqnum,
count(*) over (partition by d1) as cnt
from tbl t
) t;

Related

Row wise and conditions average in sql

Below table input
Atm_ID
C1
C2
C3
C4
C5
R12673
2
5
3
1
10
R34721
3
5
2
1
8
R27835
1
2
2
8
6
I found the average Atm_Id wise but consider the data greater than equal 3 only and divide also count of number of greater than equal 3.
I need following output
Atm_ID
Average
R12673
6
R34721
5.33
R27835
7
Please any one to help me
You can simply use a CTE to generate a temp table and then can generate your desired table -
WITH CTE AS (SELECT Atm_ID,
CASE WHEN C1 >= 3 THEN C1 ELSE 0 END C1,
CASE WHEN C2 >= 3 THEN C2 ELSE 0 END C2,
CASE WHEN C3 >= 3 THEN C3 ELSE 0 END C3,
CASE WHEN C4 >= 3 THEN C4 ELSE 0 END C4,
CASE WHEN C5 >= 3 THEN C5 ELSE 0 END C5,
CASE WHEN C1 >= 3 THEN C1 ELSE 1 END +
CASE WHEN C2 >= 3 THEN C2 ELSE 0 END +
CASE WHEN C3 >= 3 THEN C3 ELSE 0 END +
CASE WHEN C4 >= 3 THEN C4 ELSE 0 END +
CASE WHEN C5 >= 3 THEN C5 ELSE 0 END tot_avg
)
SELECT Atm_ID, (C1 + C2 + C3 + C4 + C5)/tot_avg Average
FROM CTE;

presto DB group by rollup creating duplicate rows

for the following table
country_id
country_name
state_id
state_name
district_id
district_name
1
C1
1
S1
1
D1
1
C1
1
S1
2
D2
1
C1
1
S1
3
D3
1
C1
2
S2
4
D4
1
C1
2
S2
5
D5
I need the count of districts under each state and country
so I used this code
select country_id,
country_name,
state_id,
state_name,
district_id,
district_name,
count(distinct district_name) as ct
from test
group by rollup(country_id, country_name, state_id, state_name, district_id, district_name)
to rollup at every level but the output looks like this
country_id
country_name
state_id
state_name
district_id
district_name
ct
1
5
1
C1
5
1
C1
1
3
1
C1
1
S1
3
1
C1
2
2
1
C1
2
S2
2
1
C1
1
S1
1
1
1
C1
1
S1
1
D1
1
1
C1
1
S1
2
1
1
C1
1
S1
2
D2
1
1
C1
1
S1
3
1
1
C1
1
S1
3
D3
1
1
C1
2
S2
4
1
1
C1
2
S2
4
D4
1
1
C1
2
S2
5
1
1
C1
2
S2
5
D5
1
how do I get rid of the rows that have an id but no name? I can't remove the columns in rollup.

Sql query - I have three columns in one table and I need to check each column data into another table

For Example:
1 23 12
33 AB1 A1
5 AC4 B5
77 AD9 B5
7 93C 1
.
A B C D E F G
1 EA12 B5
2 B29 7
3 AD9 AC4
7 AB1 1
Result
A B C
1 1 23 null 12 null
33 null AB1 AB1 A1 null
5 5 AC4 AC4 B5 B5
77 null AD9 AD9 B5 B5
7 7 93C null 1 1
I think this is what you need:
with
x as (
select c as v from t2
union select e from t2
union select g from t2
)
select
a,
(case when a in (select v from x) then a end) as found_a,
b,
(case when b in (select v from x) then b end) as found_b,
c,
(case when c in (select v from x) then c end) as found_c
from t1

SQL - need to print the same number of records and same product for customer in same table

I have table with customer_id and product_id
customer_id product_id
c1 1
c1 2
c1 3
c2 1
c2 2
c2 3
c3 5
c4 5
c5 3
I need to filter the same number of customers who brought the same number of products.
In addition to that, the customer (c5,3) is not valid because he have same product_id but the number of records are not matched with the customers.
This is the query i have tried
SELECT T1.ORDER_ID FROM #ORDER T1
WHERE EXISTS (SELECT * FROM #ORDER T2
WHERE T2.PRODUCT_ID = T1.PRODUCT_ID
AND T2.ORDER_ID != T1.ORDER_ID
GROUP BY T2.ORDER_ID)
The output should be like this
customer_id product_id
customer_id product_id
c1 1
c1 2
c1 3
c2 1
c2 2
c2 3
c3 5
c4 5
I tried the below approach, see if it applies in your case too. It doesn't seem like the best solution, but it works.
TEST_DROP1:
cust_id Prod_id
C1 1
C1 2
C1 3
C2 1
C2 2
C2 3
C3 5
C4 5
C5 3
Solution:
Step 1:
CREATE TABLE TEST_DROP2 AS
SELECT CUST_ID,
LISTAGG(PRODUCT_ID, ',') WITHIN GROUP (
ORDER BY PRODUCT_ID) prods
FROM TEST_DROP1
GROUP BY CUST_ID;
TEST_DROP2:
cust_id prod_id
C1 1,2,3
C2 1,2,3
C3 5
C4 5
C5 3
Run the below query,
SELECT *
FROM TEST_DROP1
WHERE cust_id IN
(SELECT CUST_ID
FROM TEST_DROP2
WHERE PRODS IN
( SELECT PRODS FROM TEST_DROP2 GROUP BY PRODS HAVING COUNT(1)>1
)
)
ORDER BY CUST_ID,
product_id;**
Result:
C1 1
C1 2
C1 3
C2 1
C2 2
C2 3
C3 5
C4 5

Get a limited number of rows for each match in Postgres

I have a table like:
1 a a1 a2
1 b b1 b2
1 c c1 c2
1 d d1 d2
2 a a1 a2
2 b b1 b2
2 c c1 c2
3........
3........
........
........
n x x1 x2
n y y1 y2
n z z1 z2
From this, I want to get for each number(1,2,3,4....n) some specified number(say 2) of rows.
Result:
1 a a1 a2
1 b b1 b2
2 a a1 a2
2 b b1 b2
.........
.........
n x x1 x2
n y y1 y2
I am trying to do group by and string_agg(). But I can't limit it to a specified number.
How can I go about it?
This can be done using a window function:
select nr, col1, col2, col3
from (
select nr, col1, col2, col3,
row_number() over (partition by nr order by col1) as rn
from the_table
) t
where rn <= 2;
If you want to influence which rows are returned, you can adjust the order by that defines the ordering of the rows in the window function.