How to get a result for the below table using teradata - sql

I am new to Teradata. I have created the table with empno, mobile and office no as follows. I need mobile and office no in separate column.
empno mobile office
111 9999 4444
222 null 3333
333 5555 7896
444 6666 null
I need to have output as:
111 9999
111 4444
222 3333
333 5555
333 7896
444 6666

SELECT empno, mobile FROM t WHERE mobile IS NOT NULL
UNION ALL
SELECT empno, office FROM t WHERE office IS NOT NULL
ORDER BY empno;
This is not Teradata-specific, works for any SQL database.

Related

Break values in one column into multiple rows

I am trying to explode values belonging to one id into multiple rows.
category_id subcategory_ids
123 111
123
333
465 444
555
The result I am trying to achieve should look like below-
category_id subcategory_ids
123 111
123 123
123 333
465 444
465 555
Below is for BigQuery Standard SQL
#standardSQL
SELECT category_id, subcategory_ids
FROM `project.dataset.table`,
UNNEST(subcategory_ids) subcategory_ids

Query 1 table with multiple criteria from different rows that are dependent upon each other

ID segment Type start date end date added date
----------------------------------------------------------------
12345 10 2222 20170101 20200101 20180901
12345 20 2222 20140101 20160101 20150901
12345 50 4444 20170301 20200101 20180901
12345 60 4444 20140101 20160101 20150901
56789 4 2222 20170101 20200101 20180901
56789 6 2222 20140101 20160101 20150901
56789 10 3333 20170301 20200101 20180901
56789 56 3333 20140101 20160101 20150901
56789 7 4444 20110301 20120101 20180901
56789 12 4444 20100101 20100301 20150901
I am having a hard time querying data in 1 table where I need an ID depending on data in a different row in the same table. I am new to Oracle SQL.
I will have the following:
type
added date
I need to know which ID and segment has type 2222 added on the 20180901 with a start date before 20180901. Also for this ID there is a type 4444 with a start date before 20180901 and after the start date of 2222 segment.
In this example it would only be the first line ID - 12345 Segment -10.
Since the following:
The ID has a '2222' segment that has an added date that equals
The ID has a '4444' with a start date between the above '2222' segment start date and added date.
Thanks in advance for your help.
Truly,
Wendy
You don't post your DDL CREATE TABLE ... SQL statements, so I can only guess on the exact table name and column names/types. The query you are looking for should be similar to:
select
*
from my_table t1
where type = 2222
and added_date = date '2018-09-01'
and start_date < date '2018-09-01'
and exists (
select 1 from my_table t2
where t2.id = t1.id
and t2.type = 4444
and t2.start_date < date '2018-09-01'
and t2.start_date > t1.start_date
)

Oracle merge adding records when matched

I have a table that has an ID field with a trigger (so it's essentially an IDENTITY field) as my primary key. I mostly don't care about that.
The rest of the data are several linking keys, and I want to query my data, and if any of those keys have changed, add a new record with a new effective date. If all the keys are the same, then nothing should be added.
However, even when all of the keys match, it is adding new records. All of the fields I care about are exactly the same, so I'm essentially getting duplicate records, but with a new ID and new effective date.
I'll simplify my code a bit, but this is essentially what I have:
MERGE_TABLE (
merge_ID NUMBER(18) PRIMARY KEY NOT NULL,
asof_Date Date,
keyA varchar2(10 byte),
keyB varchar2(10 byte),
keyC varchar2(10 byte),
table_date Date)
There is a trigger on merge_ID on insert to use a sequence.
MERGE INTO merge_table mt
USING (
select keyA, keyB, keyC, table_date
from table -- it's actually a complex query, but it's getting data
) tbl
ON (rtrim(tbl.keyA) = rtrim(mt.keyA)
AND rtrim(tbl.keyB) = rtrim(mt.keyB)
AND rtrim(tbl.keyC) = rtrim(mt.keyC))
WHEN NOT MATCHED THEN
INSERT (asof_Date, keyA, keyB, keyC, table_date)
VALUES (sysdate, tbl.keyA, tbl.keyB, tbl.keyC, tbl.table_date)
If my MERGE_TABLE starts with the following data:
merge_ID asof_Date keyA keyB keyC table_date
10 1/1/2018 333 456 987 12/31/2017
11 1/1/2018 444 234 876 12/31/2017
12 1/1/2018 222 789 654 12/31/2017
then, after running it, I have the following data:
merge_ID asof_Date keyA keyB keyC table_date
10 1/1/2018 333 456 987 12/31/2017
11 1/1/2018 444 234 876 12/31/2017
12 1/1/2018 222 789 654 12/31/2017
13 3/22/2018 333 456 987 12/31/2017
14 3/22/2018 444 234 876 12/31/2017
15 3/22/2018 222 789 654 12/31/2017
My keys all matched, but it did an insert anyway. Why?
If KeyB had changed on the first record from 456 to 678, the data I would want is:
merge_ID asof_Date keyA keyB keyC table_date
10 1/1/2018 333 456 987 12/31/2017
11 1/1/2018 444 234 876 12/31/2017
12 1/1/2018 222 789 654 12/31/2017
13 3/22/2018 333 678 987 12/31/2017

Select records for batch processing in loop

I need to select the records in batch wise, like in below example we have 20 records. if I give batch of size of 10 there would be two loops. the problem here is if I do top 10 then 555 value will be split as its position is 10 and 11. hence 555 should also include in that top first batch. how I can achieve this? this is just example, I have 900 million records to process and my batch will be 2 million in real scenario.
ID
-------
111
111
111
222
222
333
333
444
444
555
555
666
666
777
777
888
888
You can use top with ties - this might return more records then stated but will not break similar ids to different batches:
Create and populate sample table (Please save us this step in your future questions):
DECLARE #T AS TABLE
(ID int)
INSERT INTO #T VALUES
(111),(111),(111),
(222),(222),
(333),(333),
(444),(444),
(555),(555),
(666),(666),
(777),(777),
(888),(888)
The select statement:
SELECT TOP 10 WITH TIES ID
FROM #T
ORDER BY ID
Results:
row ID
1 111
2 111
3 111
4 222
5 222
6 333
7 333
8 444
9 444
10 555
11 555
While selecting the records, you can group them by id prior to limiting their number.

Why joining tables in this order returns nothing?

I have two tables A and B that I am trying to join on a particular column.
While the column of A contains NULLs besides values, the column of B does not contain any NULLs.
When I try to join A and B in the following way
SELECT *
FROM A INNER JOIN B ON A.XXX = B.XXX;
returns nothing, but doing
SELECT *
FROM B INNER JOIN A ON B.XXX = A.XXX;
returns the results I expected.
Why is this happening?
Simplified table structure:
Table A: TableB:
XXX XXX
----- ------
111 111
222 222
333 222
NULL 333
444 444
: :
That's strange as the order of JOIN generally won't matter but you can try checking for NULL on join condition like
FROM A INNER JOIN B ON A.XXX = B.XXX
OR A.XXX IS NULL;
Here is my test data.
SQL> select * from a;
XXX COL2
---------- ---------
22-MAR-17
111 22-MAR-17
222 22-MAR-17
333 22-MAR-17
444 22-MAR-17
SQL> select * from b;
XXX COL1
---------- ----------
555 678
444 567
333 456
222 345
222 234
111 123
6 rows selected.
SQL>
As we would expect, join order has no difference on the result set. In both cases we get one row for every match on A.XXX and B.XXX:
SQL> select a.*, b.*
2 from a inner join b
3 on a.xxx = b.xxx
4 /
XXX COL2 XXX COL1
---------- --------- ---------- ----------
444 22-MAR-17 333 567
333 22-MAR-17 333 456
222 22-MAR-17 222 345
222 22-MAR-17 222 234
111 22-MAR-17 111 123
6 rows selected.
SQL> select a.*, b.*
2 from b inner join a
3 on b.xxx = a.xxx
4 /
XXX COL2 XXX COL1
---------- --------- ---------- ----------
444 22-MAR-17 333 567
333 22-MAR-17 333 456
222 22-MAR-17 222 345
222 22-MAR-17 222 234
111 22-MAR-17 111 123
6 rows selected.
SQL>
So you are doing something different from what you've posted here, or there's some peculiarity in your data which you're not showing us.