Multiple column condition check with multiple rows to be found - sql

ID A B c D E(Time)
---------------------------
1 J 1 A B 1
2 J 1 A S 2
3 M 1 A B 1
4 M 1 A B 2
5 M 2 A S 3
6 M 2 A S 4
7 T 1 A B 1
8 T 2 A S 2
9 T 1 A B 3
10 k 1 A B 1
11 k 1 A B 2
I need to find unique values with multiple column with some added condition. The unique value are combination of Col A,B and D.
If Col A has only two rows (like record 1 and 2) and the Column B is same on both data and there is a different value as in Column D , BUT the S are only coming after B we dont want to see those records
If Col A has only multiple rows (like record 3 to 6 ) with different Col B and D,
whereas in COulmn D S are coming after B we dont want to see those records.
If Col A has only multiple rows (like record 7 to 9 ) with different Col B and D,
whereas in COulmn D there is a S before B we want to see those records.
If Col A has only multiple rows (like record 10 to 11 ) with different Col B and same column D we dont want to see those records.
any input , able to get to see the first and last of it using partition by and using unbounded in query...
Seems like the basic logic to look for is on to See if S preceds any B on Column D then show all those records using the partition...
Desired output is row 7-9: THis is Based on logic for same column A , we had a Sell before Buy from customer on Column D when order by column E time.
ID A B C D E(Time)
---------------------------------------------------
7 T 1 A B 1
8 T 2 A S 2
9 T 1 A B 3

I started to write a query to do this, but ran out of "Spare time", your criteria is very hard to follow, If you comment out the "Where" at the bottom of the query it functions but doesn't yet produce your desired effect.
Possibly this can lead you in a direction to achive your goal ...
WITH Src AS (
SELECT 1 AS ID, 'J' AS A, 1 AS B, 'A' AS C, 'B' AS D, 1 AS E
UNION ALL SELECT 2, 'J', 1, 'A', 'S', 2
UNION ALL SELECT 3, 'M', 1, 'A', 'B', 1
UNION ALL SELECT 4, 'M', 1, 'A', 'B', 2
UNION ALL SELECT 5, 'M', 2, 'A', 'S', 3
UNION ALL SELECT 6, 'M', 2, 'A', 'S', 4
UNION ALL SELECT 7, 'T', 1, 'A', 'B', 1
UNION ALL SELECT 8, 'T', 2, 'A', 'S', 2
UNION ALL SELECT 9, 'T', 1, 'A', 'B', 3
UNION ALL SELECT 10, 'k', 1, 'A', 'B', 1
UNION ALL SELECT 11, 'k', 1, 'A', 'B', 2
), ACnt AS (
SELECT A, Count(*) AS Cnt
FROM Src
GROUP BY A
), FirstD AS (
SELECT A, D
FROM Src
WHERE E=1
), FirstSRow AS (
SELECT A, Min(E) AS E
FROM Src
WHERE D='S'
GROUP BY A
), LastBRow AS (
SELECT A, Max(E) AS E
FROM Src
WHERE D='B'
GROUP BY A
), Mins AS (
SELECT A, Min(D) AS D, Min(B) AS B
FROM Src
GROUP BY A
), Maxs AS (
SELECT A, Max(D) AS D, Max(B) AS B
FROM Src
GROUP BY A
)
SELECT Src.*
FROM Src
JOIN ACnt ON ACnt.A=Src.A
JOIN FirstD ON FirstD.A=Src.A
JOIN Mins ON Mins.A=Src.A
JOIN Maxs ON Maxs.A=Src.A
LEFT JOIN FirstSRow ON FirstSRow.A=Src.A
LEFT JOIN LastBRow ON LastBRow.A=Src.A
WHERE
NOT (ACnt.Cnt=2 AND Mins.B=Maxs.B AND Mins.D<>Maxs.D AND FirstSRow.E < LastBRow.E)
AND NOT (ACnt.Cnt>=3 AND Mins.B<>Maxs.B AND Mins.D<>Maxs.D AND FirstD.D='B')
AND (ACnt.Cnt>=3 AND Mins.B<>Maxs.B AND Mins.D<>Maxs.D AND FirstD.D='B')

Related

Bigquery - select last # distinct values

Given table as:
WITH table AS
(SELECT 'A' id, '11' ar, 1 ts UNION ALL
SELECT 'A', '12', 2 UNION ALL
SELECT 'A', '11', 3 UNION ALL
SELECT 'B', '11', 4 UNION ALL
SELECT 'B', '13', 5 UNION ALL
SELECT 'B', '12', 6 UNION ALL
SELECT 'B', '12', 7)
id ar ts
A 11 1
A 12 2
A 11 3
B 11 4
B 13 5
B 12 6
B 12 7
I need to get the unique last two rows as:
id ar
A 11
A 12
B 12
B 13
I tried ARRAY_AGG with DISTINCT and LIMIT,
But the ORDER BY must be the same as expression
Below is for BigQuery Standard SQL
#standardSQL
SELECT * EXCEPT(ars)
FROM (
SELECT id, ARRAY_AGG(ar ORDER BY ts DESC LIMIT 2) AS ars
FROM (
SELECT id, ar, MAX(ts) AS ts
FROM `project.dataset.table`
GROUP BY id, ar
)
GROUP BY id
) t, t.ars AS ar
if to apply to sample data from your question - output is
Row id ar
1 A 11
2 A 12
3 B 12
4 B 13

Is there a Dataprep rolling list equivalent function in BigQuery?

I'm looking for functionality similar to this in BigQuery: https://cloud.google.com/dataprep/docs/html/ROLLINGLIST-Function_118228853
Does anyone know of a suitable function?
Below example for BigQuery Standard SQL
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'a' col1, 1 col2 UNION ALL
SELECT 'b', 2 UNION ALL
SELECT 'c', 3 UNION ALL
SELECT 'd', 4 UNION ALL
SELECT 'e', 5 UNION ALL
SELECT 'f', 6 UNION ALL
SELECT 'g', 7 UNION ALL
SELECT 'h', 8
)
SELECT *,
STRING_AGG(col1)
OVER(ORDER BY col2 ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) rolling_list
FROM `project.dataset.table`
with output
Row col1 col2 rolling_list
1 a 1 a
2 b 2 a,b
3 c 3 a,b,c
4 d 4 b,c,d
5 e 5 c,d,e
6 f 6 d,e,f
7 g 7 e,f,g
8 h 8 f,g,h

oracle hierarchy query error ORA-01436: CONNECT BY loop in user data

i have a table called abc
columns and data are like:-
a b c
------------
ab 1 2
bc 2 3
cd 3 4
de 4 5
maybe there is data for cyclic like-
ef 5 1
i want output as:-
A b d
------------
ab 1 5/4/3/2/1
bc 2 5/4/3/2
cd 3 5/4/3
de 4 5/4
ef 5 5
please help me out find a query to retrive data like this
with
my_data(a,b,c) AS (
select 'ab', 1, 2 from dual union all
select 'bc', 2, 3 from dual union all
select 'cd', 3, 4 from dual union all
select 'de', 4, 5 from dual union all
select 'ea', 5, 1 from dual
)
select a, b, sys_connect_by_path(b, '/') d
from my_data t
connect by nocycle c = prior b
start with c = 1
order by a;
You may use listagg with select level from dual connect by level <= ? statement, and do not need column c( and column a is only needed for output ), as in the following routine :
create table tab( a varchar2(2), b int );
insert all
into tab values('ab',1)
into tab values('bc',2)
into tab values('cd',3)
into tab values('de',4)
into tab values('ef',5)
select * from dual;
select a, b,
( select listagg(6-level,'/') within group (order by level)
from dual
connect by level <= 6-b ) as d
from tab t;
SQL Fiddle Demo
You may use a recursive CTE with a CYCLE clause to avoid cyclic data
WITH cte(a, b, c, d) AS
( SELECT a,
b,
c,
to_char(b) AS d
FROM abc
WHERE c = 1
UNION ALL SELECT t.a,
t.b,
t.c,
cte.d ||'/'||t.b
FROM abc t
JOIN cte ON (cte.b = t.c) )
CYCLE b SET CYCLE TO 1 DEFAULT 0
SELECT a,
b,
d
FROM cte
WHERE CYCLE = 0
ORDER BY b ;
Demo

How to convert table using SQL

I'm sorry if this is a duplicate question, but I had no idea which search keywords to use (that's why the question is vague as well)
I have a table like this
Parent_ID Parent_item Child_Item
1 A B
1 A C
2 H I
2 H J
2 H K
And I would like to have the results in the following format:
Parent_ID Parent_or_Child
1 A
1 B
1 C
2 H
2 I
2 J
2 K
How can this be done?
Thanks!
You need to unpivot the data, use UNION
select Parent_ID,Parent_item
from yourtable
Union
select Parent_ID,Child_Item
from yourtable
You need to unpivot the data, and it seems you don't want duplicates so you need to select distinct. In Oracle 11.1 or above, you can use the UNPIVOT operator - the advantage is that the base table will be read just once.
You can add an order by clause if you need it; I didn't, so the rows in the output are in arbitrary order (if you compare to your "desired output").
with
test_data ( Parent_ID, Parent_item, Child_Item ) as (
select 1, 'A', 'B' from dual union all
select 1, 'A', 'C' from dual union all
select 2, 'H', 'I' from dual union all
select 2, 'H', 'J' from dual union all
select 2, 'H', 'K' from dual
)
-- End of test data (NOT part of the query).
-- SQL query begins BELOW THIS LINE.
select distinct parent_id, parent_or_child
from test_data
unpivot (parent_or_child
for col in (parent_item as 'parent_item', child_item as 'child_item'))
;
PARENT_ID PARENT_OR_CHILD
---------- ---------------
2 I
1 A
1 B
1 C
2 H
2 J
2 K
7 rows selected.

How to group by to get rid of duplicates rows

How do I remove duplicates from the table where all the columns are significant apart from PK.
declare #dummy table
(
pk int,
a char(1),
b char(1),
c char(1)
)
insert into #dummy
select 1, 'A', 'B', 'B' union all
select 2, 'A', 'B', 'B' union all
select 3, 'P', 'Q', 'R' union all
select 4, 'P', 'Q', 'R' union all
select 5, 'X', 'Y', 'Z' union all
select 6, 'X', 'Y', 'Z' union all
select 7, 'A', 'B', 'Z'
what I get with out distinction:
select * from #dummy
pk a b c
----------- ---- ---- ----
1 A B B
2 A B B
3 P Q R
4 P Q R
5 X Y Z
6 X Y Z
7 A B Z
What I'd like is:
select ... do magic ....
pk a b c
----------- ---- ---- ----
1 A B B
3 P Q R
5 X Y Z
7 A B Z
Found it:
select min(pk), a, b, c
from #dummy
group by a, b, c
You want something like this, I think:
DELETE FROM f
FROM #dummy AS f INNER JOIN #dummy AS g
ON g.data = f.data
AND f.id < g.id
Check out this article: http://www.simple-talk.com/sql/t-sql-programming/removing-duplicates-from-a-table-in-sql-server/
At first, I thought distinct would do it, but I'm fairly certain what you want is group by:
select * from #dummy group by a,b,c
Since there's a unique primary key, all rows are distinct.