SQL query return no rows - sql

acid
tran_id
tran_date
tran_particular
tran_amt
part_tran_type
ab500
m1
01-01-2022
123:qwe
10
C
ab500
m5
10-01-2022
124:qse
20
C
ab500
m16
11-01-2022
123:pyh
10
D
I have the above table named htd. I am trying to fetch the result where tran_particular is unique before the ":"
Final output looking for:
acid
tran_id
tran_date
tran_particular
tran_amt
part_tran_type
ab500
m5
10-01-2022
124:qse
20
C
But below query returns no rows:
select tran_id||'|'||tran_date||'|'|| TRAN_PARTICULAR||'|'|| tran_amt
||'|'|| part_tran_type from htd a where a.acid ='ab500' and
Substr(TRAN_PARTICULAR,1,instr(TRAN_PARTICULAR,':')-1) not in (select Substr(TRAN_PARTICULAR,1,instr(TRAN_PARTICULAR,':')-1) from htd b where b.acid ='ab500'
and b.tran_id not in( a.tran_id)) order by tran_date;

koen >CREATE TABLE htd (tran_id, tran_particular)AS
2 (
3 SELECT 'm1', '123:qwe' FROM DUAL UNION ALL
4 SELECT 'm5', '124:qse' FROM DUAL UNION ALL
5 SELECT 'm16', '123:pyh' FROM DUAL
6* );
Table HTD created.
koen >WITH tp_unique_vals (tran_particular, cnt) AS
2 (
3 SELECT SUBSTR(tran_particular,1,INSTR(tran_particular,':')-1), COUNT(*)
4 FROM htd
5 GROUP BY SUBSTR(tran_particular,1,INSTR(tran_particular,':')-1)
6 HAVING COUNT(*) = 1
7 )
8 SELECT h.*
9 FROM htd h
10* JOIN tp_unique_vals u ON SUBSTR(h.tran_particular,1,instr(h.tran_particular,':')-1) = u.tran_particular;
TRAN_ID TRAN_PARTICULAR
__________ __________________
m5 124:qse
koen >

Try to use a regular expression and an aggregation:
with a as (select '123:qwe' b from dual union all
select '124:qse' from dual union all
select '123:pyh' from dual)
select b
from a
where regexp_substr(b, '[^:]+') in ( select c
from (select b, regexp_substr(b, '[^:]+') c
from a)
group by c
having count(*) = 1);
Returns 124:qse.

Related

How to write SQL join to find description of id using Oracle?

I have 2 input tables, and I need output in string format.
I tried following query, but it does not work. How can I get the above output?
with
cte1 as --table 1
(select 1 as id , 'A' as abc from dual
union
select 2 as id , 'B' as abc from dual
union
select 3 as id , 'C' as abc from dual
union
select 4 as id , 'D' as abc from dual
union
select 5 as id , 'E' as abc from dual
union
select 6 as id , 'F' as abc from dual
),
cte2 as --table2
(select 1 as id, 3 as name from dual
union
select 1 as id, 5 as name from dual
union
select 1 as id, 4 as name from dual
union
select 2 as id, 3 as name from dual
union
select 2 as id, 6 as name from dual
)
SELECT e.id, e.abc, m.id as mgr, e.abc, c.*
FROM
cte1 e, cte2 m, cte2 c
WHERE e.id = m.id
and
e.id=c.name;
You are trying to join each row in table 1 to two rows in table 2, and the conditions can never both be true.
You want to join each row in table 2 to two rows in table 1:
SELECT e.abc, m.abc
FROM cte2 c, cte1 e, cte1 m
WHERE e.id = c.id
AND m.id = c.name
ORDER BY c.id, c.name;
A A
- -
A C
A D
A E
B C
B F
or with 'modern' join syntax, which you should really be using:
SELECT e.abc, m.abc
FROM cte2 c
JOIN cte1 e ON e.id = c.id
JOIN cte1 m ON m.id = c.name
ORDER BY c.id, c.name;
A A
- -
A C
A D
A E
B C
B F

Explode and Count all items from 2 dates column

I would like to get all possible date (in this case : event_day) and number of event that happen between start_date and end_date. please look table below
---------------------------------
start_date | end_date | event
---------------------------------
2019-01-01 | 2019-01-04 | A
2019-01-02 | 2019-01-03 | B
2019-01-01 | 2019-01-06 | C
and I want to query to get number of event_count in all date. please see the following result
----------------------------
event_day | event_count
----------------------------
2019-01-01 | 2
2019-01-02 | 3
2019-01-03 | 3
2019-01-04 | 2
2019-01-05 | 1
2019-01-06 | 1
I read others source but can only find how to explode date from 2 dates. Any helps here? Thanks
You can use a calendar table to solve this:
SELECT date_value AS event_day, COUNT(*) AS event_count
FROM (
SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS date_value
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) calendar INNER JOIN events ON calendar.date_value BETWEEN events.start_date AND events.end_date
WHERE calendar.date_value BETWEEN '2019-01-01' AND '2019-01-04' -- to filter for a specific date range.
GROUP BY date_value
demo on dbfiddle.uk
If you are using postgres you can generate a calendar table using generate_series, basically you need a calendar table to be able to explode the dates.
WITH a AS(
Select '2019-01-01'::date as start_date ,'2019-01-04'::date as end_date union all
Select '2019-01-02'::date , '2019-01-03'::date union all
Select '2019-01-01'::date, '2019-01-06'::date
)
Select t.date_generated,count(*) as event
from a
JOIN(Select date_generated
from generate_series(date '2019-01-01',
date '2019-12-31',
interval '1 day') as t(date_generated)
) t
ON t.date_generated between a.start_date and a.end_date
group by t.date_generated
order by t.date_generated
select Calendar.Calndr_date , count(Calendar.Calndr_date) count_events
from event_table
join Calendar on
Calendar.Calndr_date between event_table.start_date and event_table.end_date
group by Calendar.Calndr_date
please discuss if any problem.
Please create calendar table and insert data of calendar.

Oracle: Analytical functions Sub totals after each change in value

I have the following data (order of records as in the example):
A B
1 10
1 20
1 30
1 40
2 50
2 65
2 75
1 89
1 100
from SQL:
with x as (
select A, B
from (
select 1 as A, 10 as B from dual
union all
select 1 as A, 20 as B from dual
union all
select 1 as A, 30 as B from dual
union all
select 1 as A, 40 as B from dual
union all
select 2 as A, 50 as B from dual
union all
select 2 as A, 65 as B from dual
union all
select 2 as A, 75 as B from dual
union all
select 1 as A, 89 as B from dual
union all
select 1 as A, 100 as B from dual
)
)
select A, B
from X
I want to group the data for each change of value in column A,
I want to get the following result:
A MIN(B) MAX(B)
1 10 40
2 50 75
1 89 100
How to get such a result in the ORACLE 11. I would expect a simple implementation...
This is a gaps and islands problem, solved using row_number analytic function
SELECT a,
MIN(b),
MAX(b)
FROM (
SELECT x.*,
ROW_NUMBER() OVER(
ORDER BY b
) - ROW_NUMBER() OVER(
PARTITION BY a
ORDER BY b
) AS seq
FROM x
)
GROUP BY a,
seq;
Demo

How to combine and count two columns in oracle?

My table seems like this;
A B
1 100
1 102
1 105
2 100
2 105
3 100
3 102
I want output like this:
A Count(B)
1 3
1,2 2
1,2,3 3
2 2
3 2
2,3 2
How can i do this?
I try to use listagg but it didn't work.
I suspect that you want to count the number of sets of A that are in the data -- and that your sample results are messed up.
If so:
select grp, count(*)
from (select listagg(a, ',') within group (order by a) as grp
from t
group by b
) b;
This gives you the counts for the full combinations present in the data. The results would be:
1,2,3 1
1,3 1
1,2 1
You can get the original number of rows by doing:
select grp, sum(cnt)
from (select listagg(a, ',') within group (order by a) as grp, count(*) as cnt
from t
group by b
) b;
Oracle Setup:
CREATE TABLE table_name ( A, B ) AS
SELECT 1, 100 FROM DUAL UNION ALL
SELECT 1, 102 FROM DUAL UNION ALL
SELECT 1, 105 FROM DUAL UNION ALL
SELECT 2, 100 FROM DUAL UNION ALL
SELECT 2, 105 FROM DUAL UNION ALL
SELECT 3, 100 FROM DUAL UNION ALL
SELECT 3, 102 FROM DUAL;
Query:
SELECT A,
COUNT(B)
FROM (
SELECT SUBSTR( SYS_CONNECT_BY_PATH( A, ',' ), 2 ) AS A,
B
FROM table_name
CONNECT BY PRIOR B = B
AND PRIOR A + 1 = A
)
GROUP BY A
ORDER BY A;
Output:
A COUNT(B)
----- ----------
1 3
1,2 2
1,2,3 1
2 2
2,3 1
3 2

sql server : count records

I have a tableA (ID int, Match varchar, tot int)
ID Match Tot
1 123
2 123
3 12
4 12
5 4
6 12
7 8
Now, I want to calculate Tot which is total number of match exists in the table. for example 123 occured twice, 12 exist thrice and so on. Also note that I want the count only at first match. here is the expected result.:
ID Match Tot
1 123 2
2 123
3 12 3
4 12
5 4 1
6 12
7 8 1
Another case:
ID Match Count Tot
1 123 2
2 123 1
3 12 10
4 12 10
5 4 3
6 12 5
7 8 7
Now I want to add the count for the same match. expected result:
ID Match Count Tot
1 123 2 3
2 123 1
3 12 10 25
4 12 10
5 4 3 3
6 12 5
7 8 7 7
Thanks
WITH tableA(ID, Match) AS
(
SELECT 1,123 UNION ALL
SELECT 2,123 UNION ALL
SELECT 3,12 UNION ALL
SELECT 4,12 UNION ALL
SELECT 5,4 UNION ALL
SELECT 6,12 UNION ALL
SELECT 7,8
)
SELECT *,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY Match ORDER BY ID) = 1
THEN COUNT(*) OVER (PARTITION BY Match)
END AS Tot
FROM tableA
ORDER BY ID
SELECT match, COUNT(match ) as Tot
FROM tableA
GROUP BY match
Solution 1:
DECLARE #MyTable TABLE
(
ID INT PRIMARY KEY
,Match VARCHAR(10) NOT NULL
,Tot INT NULL
);
INSERT #MyTable(ID, Match)
SELECT 1, 123
UNION ALL
SELECT 2, 123
UNION ALL
SELECT 3, 12
UNION ALL
SELECT 4, 12
UNION ALL
SELECT 5, 4
UNION ALL
SELECT 6, 12
UNION ALL
SELECT 7, 8;
--SELECT
SELECT *
,CASE
WHEN ROW_NUMBER()OVER(PARTITION BY a.Match ORDER BY a.ID ASC)=1
THEN COUNT(*)OVER(PARTITION BY a.Match)
END TotCalculated
FROM #MyTable a;
--UPDATE
WITH MyCTE
AS
(
SELECT a.Tot
,CASE
WHEN ROW_NUMBER()OVER(PARTITION BY a.Match ORDER BY a.ID ASC)=1
THEN COUNT(*)OVER(PARTITION BY a.Match)
END TotCalculated
FROM #MyTable a
)
UPDATE MyCTE
SET Tot = TotCalculated;
SELECT *
FROM #MyTable;
Solution 2:
UPDATE #MyTable
SET Tot = NULL;
SELECT x.ID, y.Num
FROM
(
SELECT b.Match, MIN(b.ID) ID
FROM #MyTable b
GROUP BY b.Match
) x INNER JOIN
(
SELECT a.Match, COUNT(*) AS Num
FROM #MyTable a
GROUP BY a.Match
) y ON x.Match = y.Match
ORDER BY x.ID
UPDATE #MyTable
SET Tot = t.Num
FROM #MyTable z
INNER JOIN
(
SELECT x.ID, y.Num
FROM
(
SELECT b.Match, MIN(b.ID) ID
FROM #MyTable b
GROUP BY b.Match
) x INNER JOIN
(
SELECT a.Match, COUNT(*) AS Num
FROM #MyTable a
GROUP BY a.Match
) y ON x.Match = y.Match
) t ON z.ID = t.ID;
SELECT *
FROM #MyTable;