presto DB group by rollup creating duplicate rows - sql

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.

Related

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

SQL recursive hierarchy

I am struggling to get one recursive CTE to work as desired but still with no chance..
So, I have the following similar table structures:
tblMapping:
map_id | type_id | name | parent_id
1 1 A1 0
2 1 A2 0
3 1 A3 1
4 1 A4 3
5 2 B1 0
6 2 B2 5
7 2 B3 6
8 1 A5 4
9 2 B4 0
tblRoleGroup:
role_group_id | type_id | map_id | desc_id
1 1 0 null
1 2 0 null
2 1 3 1
2 2 6 0
3 1 8 1
3 2 9 1
In tblRoleGroup, the desc_id field means:
null - allow all (used only in combination with map_id=0)
0 - allow all from parent including parent
1 - allow only current node
Still in tblRoleGroup if map_id=0 then the query should get all elements from same type_id
The query result should look like this:
role_group_id | type_id | map_id | path
1 1 1 A1
1 1 2 A2
1 1 3 A1.A3
1 1 4 A1.A3.A4
1 1 8 A1.A3.A4.A5
1 2 5 B1
1 2 6 B1.B2
1 2 7 B1.B2.B3
1 2 9 B4
2 1 3 A1.A3
2 2 6 B1.B2
2 2 7 B1.B2.B3
3 1 8 A1.A3.A4.A5
3 2 9 B4
The query below solves only a part of the expected result, but I wasn't able to make it work as the expected result..
WITH Hierarchy(map_id, type_id, name, Path) AS
(
SELECT t.map_id, t.type_id, t.name, CAST(t.name AS varchar(MAX)) AS Expr1
FROM dbo.tblMapping AS t
LEFT JOIN dbo.tblMapping AS t1 ON t1.map_id = t.parent_id
WHERE (t1.parent_id=0)
UNION ALL
SELECT t.map_id, t.type_id, t.name, CAST(h.Path + '.' + t.name AS varchar(MAX)) AS Expr1
FROM Hierarchy AS h
JOIN dbo.tblMapping AS t ON t.parent_id = h.map_id
)
SELECT h.map_id, h.type_id, t.role_group_id, h.Path AS Path
FROM Hierarchy AS h
LEFT JOIN dbo.tblRoleGroup t ON t.map_id = h.map_id
Could someone help me on this?
Thank you
At first I create a function that brings all descendants of passed map_id:
CREATE FUNCTION mapping (#map_id int)
RETURNS TABLE
AS
RETURN
(
WITH rec AS (
SELECT map_id,
[type_id],
CAST(name as nvarchar(max)) as name,
parent_id
FROM tblMapping
WHERE map_id = #map_id
UNION ALL
SELECT m.map_id,
m.[type_id],
r.name+'.'+m.name,
m.parent_id
FROM rec r
INNER JOIN tblMapping m
ON m.parent_id = r.map_id
)
SELECT *
FROM rec
);
GO
Then run this:
;WITH rec AS (
SELECT map_id,
[type_id],
CAST(name as nvarchar(max)) as name,
parent_id
FROM tblMapping
WHERE parent_id=0
UNION ALL
SELECT m.map_id,
m.[type_id],
r.name+'.'+m.name,
m.parent_id
FROM rec r
INNER JOIN tblMapping m
ON m.parent_id = r.map_id
)
SELECT t.role_group_id,
r.[type_id],
r.map_id,
r.name as [path]
FROM tblRoleGroup t
CROSS JOIN rec r
WHERE r.[type_id] = CASE WHEN t.desc_id IS NULL AND t.map_id = 0 THEN t.[type_id] ELSE NULL END
OR r.map_id = CASE WHEN t.desc_id = 1 THEN t.map_id ELSE NULL END
OR r.map_id IN (
SELECT map_id
FROM dbo.mapping (CASE WHEN t.desc_id = 0 THEN t.map_id ELSE NULL END)
)
ORDER BY role_group_id, r.[type_id], r.map_id
Will give you:
role_group_id type_id map_id path
1 1 1 A1
1 1 2 A2
1 1 3 A1.A3
1 1 4 A1.A3.A4
1 1 8 A1.A3.A4.A5
1 2 5 B1
1 2 6 B1.B2
1 2 7 B1.B2.B3
1 2 9 B4
2 1 3 A1.A3
2 2 6 B1.B2
2 2 7 B1.B2.B3
3 1 8 A1.A3.A4.A5
3 2 9 B4

Conditional UNPIVOT in TSQL

Let's say I have a table with an ID column, and several property columns
MyTable (ID, PI, P2, P3, P4)
ID P1 P2 P3 P4
1 A1 B C1 D1
2 C1 C2 B NULL
3 C2 Z NULL NULL
4 X A1 C1 NULL
So, I need to write a query to find out how many distinct property values out there, no matter in which column they are.
Value Count
A1 2
B 2
C1 3
C2 2
X1 1
...
I think I can get this by using UNPIVOT (correct me, if I am wrong)
Now, how can I get similar count but grouped by a number of non-null values in the row (the count of non-null values per row may, or may not include key columns, doesn't matter), i.e. output like this:
Value NonNullCount Count
A1 3 1
A1 4 1
B 3 1
B 4 1
C1 2 3
C1 4 1
C2 3 1
C2 2 1
...
Here is one method, using cross apply for the unpivot:
select vals.p, t.NonNullCount, count(*)
from (select t.*,
((case when p1 is not null then 1 else 0 end) +
(case when p2 is not null then 1 else 0 end) +
(case when p3 is not null then 1 else 0 end) +
(case when p4 is not null then 1 else 0 end)
) as NonNullCount
from table t
) t cross apply
(values (p1), (p2), (p3), (p4)) vals(p)
where vals.p is not null
group by vals.p, t.NonNullCount;

sql query to find what is not in group three

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;